Modified: websites/production/tapestry/content/tapestry-for-jsf-users.html
==============================================================================
--- websites/production/tapestry/content/tapestry-for-jsf-users.html (original)
+++ websites/production/tapestry/content/tapestry-for-jsf-users.html Sat Feb 3
18:21:36 2018
@@ -45,13 +45,26 @@
<div class="wrapper bs">
- <div id="navigation"><div class="nav"><ul class="alternate"><li><a
href="index.html">Home</a></li><li><a href="getting-started.html">Getting
Started</a></li><li><a href="documentation.html">Documentation</a></li><li><a
href="download.html">Download</a></li><li><a
href="about.html">About</a></li><li><a class="external-link"
href="http://www.apache.org/licenses/LICENSE-2.0">License</a></li><li><a
href="community.html">Community</a></li><li><a class="external-link"
href="http://www.apache.org/security/">Security</a></li><li><a
class="external-link" href="http://www.apache.org/">Apache</a></li><li><a
class="external-link"
href="http://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li><li><a
class="external-link"
href="http://www.apache.org/foundation/thanks.html">Thanks</a></li></ul></div></div>
+ <div id="navigation"><div class="nav"><ul class="alternate"><li><a
href="index.html">Home</a></li><li><a href="getting-started.html">Getting
Started</a></li><li><a href="documentation.html">Documentation</a></li><li><a
href="download.html">Download</a></li><li><a
href="about.html">About</a></li><li><a class="external-link"
href="http://www.apache.org/licenses/LICENSE-2.0">License</a></li><li><a
href="community.html">Community</a></li><li><a class="external-link"
href="http://www.apache.org/security/">Security</a></li><li><a
class="external-link" href="http://www.apache.org/">Apache</a></li><li><a
class="external-link"
href="http://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li><li><a
class="external-link"
href="http://www.apache.org/foundation/thanks.html">Thanks</a></li></ul></div>
+
+</div>
<div id="top">
- <div id="smallbanner"><div class="searchbox"
style="float:right;margin: .3em 1em .1em 1em"><span style="color: #999;
font-size: 90%">Tapestry docs, issues, wikis & blogs:</span><form
enctype="application/x-www-form-urlencoded" method="get"
action="http://tapestry.apache.org/search.html">
- <input type="text" name="q">
- <input type="submit" value="Search">
-</form></div><div class="emblem" style="float:left"><p><a
href="index.html"><span class="confluence-embedded-file-wrapper"><img
class="confluence-embedded-image confluence-external-resource"
src="http://tapestry.apache.org/images/tapestry_small.png"
data-image-src="http://tapestry.apache.org/images/tapestry_small.png"></span></a></p></div><div
class="title" style="float:left; margin: 0 0 0 3em"><h1
id="SmallBanner-PageTitle">Tapestry for JSF Users</h1></div></div>
+ <div id="smallbanner"><div class="searchbox"
style="float:right;margin: .3em 1em .1em 1em"><span style="color: #999;
font-size: 90%">Tapestry docs, issues, wikis & blogs:</span>
+<form enctype="application/x-www-form-urlencoded" method="get"
action="http://tapestry.apache.org/search.html">
+ <input type="text" name="q">
+ <input type="submit" value="Search">
+</form>
+
+</div>
+
+
+<div class="emblem" style="float:left"><p><a href="index.html"><span
class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image
confluence-external-resource"
src="http://tapestry.apache.org/images/tapestry_small.png"
data-image-src="http://tapestry.apache.org/images/tapestry_small.png"></span></a></p></div>
+
+
+<div class="title" style="float:left; margin: 0 0 0 3em"><h1
id="SmallBanner-PageTitle">Tapestry for JSF Users</h1></div>
+
+</div>
<div class="clearer"></div>
</div>
@@ -63,37 +76,67 @@
</div>
<div id="content">
- <div id="ConfluenceContent"><p> </p><p>This is a
brief guide for learning Tapestry, designed for those who already know
JavaServer Faces (JSF).</p><p>Because both JSF and Tapestry are component
oriented frameworks designed to serve mostly the same kinds of problems in
similar ways, developers who already know JSF will find it very easy to learn
Tapestry. In fact, Facelets, the default view technology in JSF 2.0, was
created specifically to give JSF a Tapestry-like templating capability, so
Facelets users should feel right at home.</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="tapestry-for-jsf-users.html">Tapestry for JSF Users</a>
- </div> </li><li>
- <div>
- <span class="icon aui-icon aui-icon-small aui-iconfont-page-default"
title="Page">Page:</span>
- </div>
- <div class="details">
- <a href="tapestry-tutorial.html">Tapestry Tutorial</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="principles.html">Principles</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="getting-started.html">Getting Started</a>
- </div> </li><li>
- <div>
- <span class="icon aui-icon aui-icon-small aui-iconfont-page-default"
title="Page">Page:</span>
- </div>
- <div class="details">
- <a href="introduction.html">Introduction</a>
- </div> </li></ul></div><p>Since almost all modern JSF applications use
Facelets as their view technology, we assume the use of Facelets here when
discussing JSF features.</p><p>JSF is a rich, mature web framework
specification, and there are lots of smart people who use it productively. This
guide isn't intended as a pro-versus-con comparison or as advocacy of any kind.
Instead, it just attempts to make transitions between the two frameworks
easier, regardless of the reason for doing so.</p><h2
id="TapestryforJSFUsers-Side-by-sideComparison">Side-by-side
Comparison</h2><p>JSF and Tapestry have a lot of superficial similarities, so
the first steps in that transition are all about relating similar concepts,
terms and components in your mind:</p><div class="table-wrap"><table
class="confluenceTable"><tbody><tr><th colspan="1" rowspan="1"
class="confluenceTh"><p>Concepts & Terminology</p></th><th colspan="1"
rowspan="1" class="confluenceTh"><p>JSF</p></th><th colspan="1" rowspan="
1" class="confluenceTh"><p>Tapestry</p></th></tr><tr><td colspan="1"
rowspan="1" class="confluenceTd"><p>Java class associated with a page or
component</p></td><td colspan="1" rowspan="1" class="confluenceTd"><p>"Backing
Bean"</p></td><td colspan="1" rowspan="1" class="confluenceTd"><p>"<a
href="component-classes.html">Component Class</a>"</p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Component
attributes/parameters</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>"attributes"</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>"<a
href="component-parameters.html">parameters</a>"</p></td></tr><tr><th
colspan="1" rowspan="1" class="confluenceTh"><p>Common
Attributes/Parameters</p></th><th colspan="1" rowspan="1"
class="confluenceTh"><p>JSF</p></th><th colspan="1" rowspan="1"
class="confluenceTh"><p>Tapestry</p></th></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>HTML Attribute used for invisible
instrumentation</p></td><td cols
pan="1" rowspan="1"
class="confluenceTd"><p>jsfc="someComponentType"</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><a
href="component-templates.html">t:type="someComponentType"</a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>CSS "class" attribute
name</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>styleClass</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>class</p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Alternating "zebra" striped rows</p></td><td
colspan="1" rowspan="1"
class="confluenceTd"><p>rowclasses="class1,class2"</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p>class="${cycle:class1,class2}" using <a
class="external-link"
href="https://wiki.apache.org/tapestry/Tapestry5HowToAddBindingPrefixCycle">cycle
binding prefix</a>, or with CSS: .rowClass:nth-child(even) {background-color:
#e8e8e8;}</p></td></tr><tr><th colspan="1" rowspan="1"
class="confluenceTh"><p>Output and Messag
es</p></th><th colspan="1" rowspan="1" class="confluenceTh"><p>JSF</p></th><th
colspan="1" rowspan="1" class="confluenceTh"><p>Tapestry</p></th></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Escaped HTML from
property</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><h:outputText
value="myBean.myValue"/></p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>${myValue}</p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Raw HTML from property</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p>#{myBean.myValue}</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/OutputRaw.html"><t:outputRaw
value="myValue"/></a></p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Error messages</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><h:message> and <h:messages></p
></td><td colspan="1" rowspan="1" class="confluenceTd"><p><a
>class="external-link"
>href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Error.html"><t:error></a>
> and <a class="external-link"
>href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Errors.html"><t:errors></a>
> (for forms) or <a class="external-link"
>href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Alerts.html"><t:alerts></a></p></td></tr><tr><td
> colspan="1" rowspan="1" class="confluenceTd"><p>Image display</p></td><td
>colspan="1" rowspan="1"
>class="confluenceTd"><p><h:graphicImage></p></td><td colspan="1"
>rowspan="1" class="confluenceTd"><p><em>use standard <img>
>tag</em></p></td></tr><tr><th colspan="1" rowspan="1"
>class="confluenceTh"><p>Conditionals and Looping</p></th><th colspan="1"
>rowspan="1" class="confluenceTh"><p>JSF</p></th><th colspan="1" rowspan="1"
>class="confluence
Th"><p>Tapestry</p></th></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Render-time loop</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><ui:repeat></p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Loop.html"><t:loop></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Compile-time loop</p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p><c:forEach></p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Loop.html"><t:loop></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Conditional</p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p><c:if
test="#{myBean.myValue}"></p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><a
class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/If.html"><t:if
test="myValue"></a></p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Conditional</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><ui:fragment
rendered="#{myBean.someCondition}"/>...</ui:fragment></p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/If.html"><t:if
test="someCondition">...</t:if></a></p></td></tr><tr><td colspan="1"
rowspan="1" class="confluenceTd"><p>Switch</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><c:choose><c:when ...
></c:choose></p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>See <a href="switching-cases.html">Switching
Cases</a></p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Server-side
comment</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><ui:remove></p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><a
href="component-templates.html"><t:remove></a></p></td></tr><tr><th
colspan="1" rowspan="1" class="confluenceTh"><p>Links and Buttons</p></th><th
colspan="1" rowspan="1" class="confluenceTh"><p>JSF</p></th><th colspan="1"
rowspan="1" class="confluenceTh"><p>Tapestry</p></th></tr><tr><td colspan="1"
rowspan="1" class="confluenceTd"><p>Navigational link</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><h:link
outcome="nextpage.xhtml"/></p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/PageLink.html"><t:pagelink
page="nextpage"/></a></p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Event-triggering link, without form
submission</p></td><td colspan="1" rowspan="1" clas
s="confluenceTd"><p><em>not available</em></p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/ActionLink.html"><t:actionLink></a>
or <a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/EventLink.html"><t:eventLink></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Form submission
link</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><h:commandLink></p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/LinkSubmit.html"><t:linkSubmit></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Form submission
button</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><h:commandButton></p></td><td co
lspan="1" rowspan="1" class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Submit.html"><t:submit></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Link to Javascript
file</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><h:outputScript></p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><em><script> or use @Import in
component class</em></p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Link to CSS file</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><h:outputStylesheet></p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><em><style> or use @Import in
component class</em></p></td></tr><tr><th colspan="1" rowspan="1"
class="confluenceTh"><p>Grids, Tables and Trees</p></th><th colspan="1"
rowspan="1" class="confluenceTh"><p>JSF</p></th><th colspan="1" rowspan="1"
class="confluenceTh"><p>T
apestry</p></th></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Tabular data in <table></p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><h:datatable></p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Grid.html"><t:grid></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Table used for
layout</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><h:panelGrid> with
<h:panelGroup></p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><em>use standard <table>
tag</em></p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Hierarchical tree</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><em>depends on component library</em></p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/curr
ent/apidocs/org/apache/tapestry5/corelib/components/Tree.html"><t:tree></a></p></td></tr><tr><th
colspan="1" rowspan="1" class="confluenceTh"><p>Form
Tags/Components</p></th><th colspan="1" rowspan="1"
class="confluenceTh"><p>JSF</p></th><th colspan="1" rowspan="1"
class="confluenceTh"><p>Tapestry</p></th></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Form</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><h:form></p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Form.html"><t:form></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Single-line text input
field</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><h:inputText></p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/core
lib/components/TextField.html"><t:textField></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Password field</p></td><td
colspan="1" rowspan="1"
class="confluenceTd"><p><h:inputSecret></p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/PasswordField.html"><t:passwordfield></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Select menu</p></td><td
colspan="1" rowspan="1"
class="confluenceTd"><p><h:selectOneMenu></p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Select.html"><t:select></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Checkbox</p></td><td
colspan="1" rowspan="1"
class="confluenceTd"><p><h:selectBooleanCheckbox></p></td><
td colspan="1" rowspan="1" class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Checkbox.html"><t:checkbox></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Checkbox list</p></td><td
colspan="1" rowspan="1"
class="confluenceTd"><p><h:selectManyCheckbox></p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Checklist.html"><t:checklist></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Radio button list</p></td><td
colspan="1" rowspan="1"
class="confluenceTd"><p><h:selectOneRadio></p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/RadioGroup.html"><t:radioGroup></a>
with <a class="e
xternal-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Radio.html"><t:radio></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Multiple select
menu</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><h:selectManyListbox></p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><em>not available</em> (but see Palette and
Checklist)</p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Hidden field</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><h:inputHidden></p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Hidden.html"><t:hidden></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>textarea tag</p></td><td
colspan="1" rowspan="1"
class="confluenceTd"><p><h:inputTextarea></p></td><td colspan="1" rowspa
n="1" class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/TextArea.html"><t:textArea></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Label tag</p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p><h:outputLabel
for="..."></p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><a
class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Label.html"><t:label
for="..."></a></p></td></tr></tbody></table></div><p>Some important
notes:</p><ul><li>With Tapestry, you don't use the ${...} syntax with
parameters of components. Just use a bare expression within the quotes. For
example: <t:textfield value="myProperty"> instead of <t:textfield
value="${myProperty}">, because in the latter case the expression is
converted to a read-only string before the textfield component gets it.</li></ul
><h2 id="TapestryforJSFUsers-HelloWorldComparison">Hello World
>Comparison</h2><p>Faces templates and Tapestry templates are superficially
>quite similar.</p><div class="sectionColumnWrapper"><div
>class="sectionMacro"><div class="sectionMacroRow"><div
>class="columnMacro"><div class="code panel pdl" style="border-width:
>1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width:
>1px;"><b>JSF template (helloworld.xhtml)</b></div><div class="codeContent
>panelContent pdl">
+ <div id="ConfluenceContent"><p> </p><p>This is a
brief guide for learning Tapestry, designed for those who already know
JavaServer Faces (JSF).</p><p>Because both JSF and Tapestry are component
oriented frameworks designed to serve mostly the same kinds of problems in
similar ways, developers who already know JSF will find it very easy to learn
Tapestry. In fact, Facelets, the default view technology in JSF 2.0, was
created specifically to give JSF a Tapestry-like templating capability, so
Facelets users should feel right at home.</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="tapestry-for-jsf-users.html">Tapestry for
JSF Users</a>
+
+
+ </div>
+ </li><li>
+ <div>
+ <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+
+ <div class="details">
+ <a href="tapestry-tutorial.html">Tapestry Tutorial</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="principles.html">Principles</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="getting-started.html">Getting Started</a>
+
+
+ </div>
+ </li><li>
+ <div>
+ <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+
+ <div class="details">
+ <a href="introduction.html">Introduction</a>
+
+
+ </div>
+ </li></ul>
+</div>
+
+
+<p>Since almost all modern JSF applications use Facelets as their view
technology, we assume the use of Facelets here when discussing JSF
features.</p><p>JSF is a rich, mature web framework specification, and there
are lots of smart people who use it productively. This guide isn't intended as
a pro-versus-con comparison or as advocacy of any kind. Instead, it just
attempts to make transitions between the two frameworks easier, regardless of
the reason for doing so.</p><h2
id="TapestryforJSFUsers-Side-by-sideComparison">Side-by-side
Comparison</h2><p>JSF and Tapestry have a lot of superficial similarities, so
the first steps in that transition are all about relating similar concepts,
terms and components in your mind:</p><div class="table-wrap"><table
class="confluenceTable"><tbody><tr><th colspan="1" rowspan="1"
class="confluenceTh"><p>Concepts & Terminology</p></th><th colspan="1"
rowspan="1" class="confluenceTh"><p>JSF</p></th><th colspan="1" rowspan="1"
class="confluenceTh"><
p>Tapestry</p></th></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Java class associated with a page or
component</p></td><td colspan="1" rowspan="1" class="confluenceTd"><p>"Backing
Bean"</p></td><td colspan="1" rowspan="1" class="confluenceTd"><p>"<a
href="tapestry-for-jsf-users.html">Component Class</a>"</p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Component
attributes/parameters</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>"attributes"</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>"<a
href="tapestry-for-jsf-users.html">parameters</a>"</p></td></tr><tr><th
colspan="1" rowspan="1" class="confluenceTh"><p>Common
Attributes/Parameters</p></th><th colspan="1" rowspan="1"
class="confluenceTh"><p>JSF</p></th><th colspan="1" rowspan="1"
class="confluenceTh"><p>Tapestry</p></th></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>HTML Attribute used for invisible
instrumentation</p></td><td colspan="1" rowspan="1
" class="confluenceTd"><p>jsfc="someComponentType"</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><a
href="tapestry-for-jsf-users.html">t:type="someComponentType"</a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>CSS "class" attribute
name</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>styleClass</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>class</p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Alternating "zebra" striped rows</p></td><td
colspan="1" rowspan="1"
class="confluenceTd"><p>rowclasses="class1,class2"</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p>class="${cycle:class1,class2}" using <a
class="external-link"
href="https://wiki.apache.org/tapestry/Tapestry5HowToAddBindingPrefixCycle">cycle
binding prefix</a>, or with CSS: .rowClass:nth-child(even) {background-color:
#e8e8e8;}</p></td></tr><tr><th colspan="1" rowspan="1"
class="confluenceTh"><p>Output and Messages</p></th><th
colspan="1" rowspan="1" class="confluenceTh"><p>JSF</p></th><th colspan="1"
rowspan="1" class="confluenceTh"><p>Tapestry</p></th></tr><tr><td colspan="1"
rowspan="1" class="confluenceTd"><p>Escaped HTML from property</p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p><h:outputText
value="myBean.myValue"/></p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>${myValue}</p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Raw HTML from property</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p>#{myBean.myValue}</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/OutputRaw.html"><t:outputRaw
value="myValue"/></a></p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Error messages</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><h:message> and <h:messages></p></td><td
colsp
an="1" rowspan="1" class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Error.html"><t:error></a>
and <a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Errors.html"><t:errors></a>
(for forms) or <a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Alerts.html"><t:alerts></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Image display</p></td><td
colspan="1" rowspan="1"
class="confluenceTd"><p><h:graphicImage></p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><em>use standard <img>
tag</em></p></td></tr><tr><th colspan="1" rowspan="1"
class="confluenceTh"><p>Conditionals and Looping</p></th><th colspan="1"
rowspan="1" class="confluenceTh"><p>JSF</p></th><th colspan="1" rowspan="1"
class="confluenceTh"><p>Tapestry
</p></th></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Render-time loop</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><ui:repeat></p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Loop.html"><t:loop></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Compile-time loop</p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p><c:forEach></p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Loop.html"><t:loop></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Conditional</p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p><c:if
test="#{myBean.myValue}"></p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><a class="externa
l-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/If.html"><t:if
test="myValue"></a></p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Conditional</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><ui:fragment
rendered="#{myBean.someCondition}"/>...</ui:fragment></p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/If.html"><t:if
test="someCondition">...</t:if></a></p></td></tr><tr><td colspan="1"
rowspan="1" class="confluenceTd"><p>Switch</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><c:choose><c:when ...
></c:choose></p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>See <a href="tapestry-for-jsf-users.html">Tapestry for
JSF Users</a></p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Server-side c
omment</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><ui:remove></p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><a
href="tapestry-for-jsf-users.html"><t:remove></a></p></td></tr><tr><th
colspan="1" rowspan="1" class="confluenceTh"><p>Links and Buttons</p></th><th
colspan="1" rowspan="1" class="confluenceTh"><p>JSF</p></th><th colspan="1"
rowspan="1" class="confluenceTh"><p>Tapestry</p></th></tr><tr><td colspan="1"
rowspan="1" class="confluenceTd"><p>Navigational link</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><h:link
outcome="nextpage.xhtml"/></p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/PageLink.html"><t:pagelink
page="nextpage"/></a></p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Event-triggering link, without form
submission</p></td><td colspan="1" rowspan="1" cl
ass="confluenceTd"><p><em>not available</em></p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/ActionLink.html"><t:actionLink></a>
or <a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/EventLink.html"><t:eventLink></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Form submission
link</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><h:commandLink></p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/LinkSubmit.html"><t:linkSubmit></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Form submission
button</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><h:commandButton></p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Submit.html"><t:submit></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Link to Javascript
file</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><h:outputScript></p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><em><script> or use @Import in
component class</em></p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Link to CSS file</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><h:outputStylesheet></p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><em><style> or use @Import in
component class</em></p></td></tr><tr><th colspan="1" rowspan="1"
class="confluenceTh"><p>Grids, Tables and Trees</p></th><th colspan="1"
rowspan="1" class="confluenceTh"><p>JSF</p></th><th colspan="1" rowspan="1"
class="confluenceTh"><p
>Tapestry</p></th></tr><tr><td colspan="1" rowspan="1"
>class="confluenceTd"><p>Tabular data in <table></p></td><td colspan="1"
>rowspan="1" class="confluenceTd"><p><h:datatable></p></td><td
>colspan="1" rowspan="1" class="confluenceTd"><p><a class="external-link"
>href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Grid.html"><t:grid></a></p></td></tr><tr><td
> colspan="1" rowspan="1" class="confluenceTd"><p>Table used for
>layout</p></td><td colspan="1" rowspan="1"
>class="confluenceTd"><p><h:panelGrid> with
><h:panelGroup></p></td><td colspan="1" rowspan="1"
>class="confluenceTd"><p><em>use standard <table>
>tag</em></p></td></tr><tr><td colspan="1" rowspan="1"
>class="confluenceTd"><p>Hierarchical tree</p></td><td colspan="1" rowspan="1"
>class="confluenceTd"><p><em>depends on component library</em></p></td><td
>colspan="1" rowspan="1" class="confluenceTd"><p><a class="external-link"
>href="http://tapestry.apache.org/cu
rrent/apidocs/org/apache/tapestry5/corelib/components/Tree.html"><t:tree></a></p></td></tr><tr><th
colspan="1" rowspan="1" class="confluenceTh"><p>Form
Tags/Components</p></th><th colspan="1" rowspan="1"
class="confluenceTh"><p>JSF</p></th><th colspan="1" rowspan="1"
class="confluenceTh"><p>Tapestry</p></th></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Form</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><h:form></p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Form.html"><t:form></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Single-line text input
field</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><h:inputText></p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/co
relib/components/TextField.html"><t:textField></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Password field</p></td><td
colspan="1" rowspan="1"
class="confluenceTd"><p><h:inputSecret></p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/PasswordField.html"><t:passwordfield></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Select menu</p></td><td
colspan="1" rowspan="1"
class="confluenceTd"><p><h:selectOneMenu></p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Select.html"><t:select></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Checkbox</p></td><td
colspan="1" rowspan="1"
class="confluenceTd"><p><h:selectBooleanCheckbox></p></td
><td colspan="1" rowspan="1" class="confluenceTd"><p><a class="external-link"
>href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Checkbox.html"><t:checkbox></a></p></td></tr><tr><td
> colspan="1" rowspan="1" class="confluenceTd"><p>Checkbox list</p></td><td
>colspan="1" rowspan="1"
>class="confluenceTd"><p><h:selectManyCheckbox></p></td><td colspan="1"
>rowspan="1" class="confluenceTd"><p><a class="external-link"
>href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Checklist.html"><t:checklist></a></p></td></tr><tr><td
> colspan="1" rowspan="1" class="confluenceTd"><p>Radio button
>list</p></td><td colspan="1" rowspan="1"
>class="confluenceTd"><p><h:selectOneRadio></p></td><td colspan="1"
>rowspan="1" class="confluenceTd"><p><a class="external-link"
>href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/RadioGroup.html"><t:radioGroup></a>
> with <a class=
"external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Radio.html"><t:radio></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Multiple select
menu</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><h:selectManyListbox></p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><em>not available</em> (but see Palette and
Checklist)</p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Hidden field</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><h:inputHidden></p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Hidden.html"><t:hidden></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>textarea tag</p></td><td
colspan="1" rowspan="1"
class="confluenceTd"><p><h:inputTextarea></p></td><td colspan="1" rows
pan="1" class="confluenceTd"><p><a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/TextArea.html"><t:textArea></a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Label tag</p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p><h:outputLabel
for="..."></p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><a
class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Label.html"><t:label
for="..."></a></p></td></tr></tbody></table></div><p>Some important
notes:</p><ul><li>With Tapestry, you don't use the ${...} syntax with
parameters of components. Just use a bare expression within the quotes. For
example: <t:textfield value="myProperty"> instead of <t:textfield
value="${myProperty}">, because in the latter case the expression is
converted to a read-only string before the textfield component gets it.</li></
ul><h2 id="TapestryforJSFUsers-HelloWorldComparison">Hello World
Comparison</h2><p>Faces templates and Tapestry templates are superficially
quite similar.</p><div class="sectionColumnWrapper"><div
class="sectionMacro"><div class="sectionMacroRow"><div class="columnMacro"><div
class="code panel pdl" style="border-width: 1px;"><div class="codeHeader
panelHeader pdl" style="border-bottom-width: 1px;"><b>JSF template
(helloworld.xhtml)</b></div><div class="codeContent panelContent pdl">
<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"><html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html">
<h:body>
@@ -124,13 +167,13 @@ public class HelloWorldBean {
}
}
</pre>
-</div></div></div></div></div></div><h2
id="TapestryforJSFUsers-Expressionsintemplates">Expressions in
templates</h2><p>JSF uses the Unified Expression Language with the #{...} or
${...} syntax for accessing Backing Bean properties. For its part, Tapestry
uses the ${...} syntax with a similar but intentially limited expression
language called <a href="property-expressions.html">Property Expressions</a>.
Both allow easy access to properties via the usual JavaBean conventions, but
with Tapestry you don't have to specify which class the expression starts at
(because it always starts at the component class corresponding to the
template). Some comparisons:</p><div class="table-wrap"><table
class="confluenceTable"><tbody><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p> </p></td><th colspan="1" rowspan="1"
class="confluenceTh"><p>JSF Syntax</p></th><th colspan="1" rowspan="1"
class="confluenceTh"><p>Tapestry Syntax</p></th></tr><tr><td colspan="1"
rowspan="1" class="confluenc
eTd"><p>Property (calls getEmployeeName() or setEmployeeName())</p></td><td
colspan="1" rowspan="1"
class="confluenceTd"><p>#{employeeBean.employeeName}</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p>${employeeName}</p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Boolean property (calls
isHourly() or setHourly())</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>#{employeeBean.hourly}</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p>${hourly}</p></td></tr><tr><td colspan="1"
rowspan="1" class="confluenceTd"><p>Property chain</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p>#{employeeBean.address.street}</p></td><td
colspan="1" rowspan="1"
class="confluenceTd"><p>${address.street}</p></td></tr><tr><td colspan="1"
rowspan="1" class="confluenceTd"><p>Null-safe property chain</p></td><td
colspan="1" rowspan="1"
class="confluenceTd"><p>#{employeeBean.address.street}</p></td><td colspan="1"
rowspan="1" class="confluenceTd">
<p>${address?.street}</p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>5th element in a List</p></td><td colspan="1"
rowspan="1"
class="confluenceTd"><p>#{employeeBean.employees[5].name}</p></td><td
colspan="1" rowspan="1"
class="confluenceTd"><p>${employees.get(5).name}</p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Negation</p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p>#{!
employeeBean.hourly}</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>${! hourly}</p></td></tr><tr><td colspan="1"
rowspan="1" class="confluenceTd"><p>Arithmetic & relational
operators</p></td><td colspan="1" rowspan="1" class="confluenceTd"><p>+-*/% div
mod</p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><em>not
available</em></p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Relational operators</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p>== != ne < lt > gt <= le >=
ge</p></td><td c
olspan="1" rowspan="1" class="confluenceTd"><p><em>not
available</em></p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Ternary operator</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>#{myBean.foo < 0 ? 'bar' : 'baz'}</p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p><em>not
available</em></p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Method calling</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>#{myBean.employees.size()}</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p>${employees.size()}</p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Iterated Range</p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p><em>not
avaialble</em></p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>${1..10}</p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Iterated Range (calculated)</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><em>not avaialble
</em></p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>${1..groupList.size()}</p></td></tr><tr><td colspan="1"
rowspan="1" class="confluenceTd"><p>List</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><em>not available</em></p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p>${ [ user.name, user.email, user.phone ]
}</p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Map</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><em>not available</em></p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p>${ { 'id':'4039','type':'hourly' }
}</p></td></tr></tbody></table></div><p>Features shown as <em>not
available</em> above are absent by design, because (in both Tapestry and JSF)
it is considered best to keep complex logic in the component class rather than
in the template.</p><h2
id="TapestryforJSFUsers-EventHandling&PageNavigation">Event Handling &
Page Navigation</h2><h3 id="TapestryforJSFUsers-Eventhandling">Event ha
ndling</h3><p>In JSF, you specify the event via the <code>action</code>
parameter (for example, <h:commandButton value="Submit"
action="employeeBean.saveChanges">). For Tapestry, event handler methods are
found by method naming conventions (onSomeEvent() or by method annotations
(@Event), based on a combination of the "t:id" attribute and event name, and
the action name used depends on the component. For example, the
"<t:actionlink>" component in Tapestry emits an "action" event when
clicked, and you handle that event in your "onAction()" method.</p><h2
id="TapestryforJSFUsers-Validation">Validation</h2><p>Tapestry applications can
use JSR 303 Bean Validation annotations that JSF users should be familiar
with:</p><div class="code panel pdl" style="border-width: 1px;"><div
class="codeContent panelContent pdl">
+</div></div></div></div></div></div><h2
id="TapestryforJSFUsers-Expressionsintemplates">Expressions in
templates</h2><p>JSF uses the Unified Expression Language with the #{...} or
${...} syntax for accessing Backing Bean properties. For its part, Tapestry
uses the ${...} syntax with a similar but intentially limited expression
language called <a href="tapestry-for-jsf-users.html">Tapestry for JSF
Users</a>. Both allow easy access to properties via the usual JavaBean
conventions, but with Tapestry you don't have to specify which class the
expression starts at (because it always starts at the component class
corresponding to the template). Some comparisons:</p><div
class="table-wrap"><table class="confluenceTable"><tbody><tr><td colspan="1"
rowspan="1" class="confluenceTd"><p> </p></td><th colspan="1" rowspan="1"
class="confluenceTh"><p>JSF Syntax</p></th><th colspan="1" rowspan="1"
class="confluenceTh"><p>Tapestry Syntax</p></th></tr><tr><td colspan="1"
rowspan="1" class="confl
uenceTd"><p>Property (calls getEmployeeName() or
setEmployeeName())</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>#{employeeBean.employeeName}</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p>${employeeName}</p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Boolean property (calls
isHourly() or setHourly())</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>#{employeeBean.hourly}</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p>${hourly}</p></td></tr><tr><td colspan="1"
rowspan="1" class="confluenceTd"><p>Property chain</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p>#{employeeBean.address.street}</p></td><td
colspan="1" rowspan="1"
class="confluenceTd"><p>${address.street}</p></td></tr><tr><td colspan="1"
rowspan="1" class="confluenceTd"><p>Null-safe property chain</p></td><td
colspan="1" rowspan="1"
class="confluenceTd"><p>#{employeeBean.address.street}</p></td><td colspan="1"
rowspan="1" class="confluence
Td"><p>${address?.street}</p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>5th element in a List</p></td><td colspan="1"
rowspan="1"
class="confluenceTd"><p>#{employeeBean.employees[5].name}</p></td><td
colspan="1" rowspan="1"
class="confluenceTd"><p>${employees.get(5).name}</p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Negation</p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p>#{!
employeeBean.hourly}</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>${! hourly}</p></td></tr><tr><td colspan="1"
rowspan="1" class="confluenceTd"><p>Arithmetic & relational
operators</p></td><td colspan="1" rowspan="1" class="confluenceTd"><p>+-*/% div
mod</p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><em>not
available</em></p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Relational operators</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p>== != ne < lt > gt <= le >=
ge</p></td><
td colspan="1" rowspan="1" class="confluenceTd"><p><em>not
available</em></p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Ternary operator</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>#{myBean.foo < 0 ? 'bar' : 'baz'}</p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p><em>not
available</em></p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Method calling</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>#{myBean.employees.size()}</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p>${employees.size()}</p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>Iterated Range</p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p><em>not
avaialble</em></p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>${1..10}</p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Iterated Range (calculated)</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p><em>not avaia
lble</em></p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>${1..groupList.size()}</p></td></tr><tr><td colspan="1"
rowspan="1" class="confluenceTd"><p>List</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><em>not available</em></p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p>${ [ <a class="external-link"
href="http://user.name" rel="nofollow">user.name</a>, user.email, user.phone ]
}</p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>Map</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><em>not available</em></p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p>${ { 'id':'4039','type':'hourly' }
}</p></td></tr></tbody></table></div><p>Features shown as <em>not
available</em> above are absent by design, because (in both Tapestry and JSF)
it is considered best to keep complex logic in the component class rather than
in the template.</p><h2
id="TapestryforJSFUsers-EventHandling&PageNavigation">Event Handling &
; Page Navigation</h2><h3 id="TapestryforJSFUsers-Eventhandling">Event
handling</h3><p>In JSF, you specify the event via the <code>action</code>
parameter (for example, <h:commandButton value="Submit"
action="employeeBean.saveChanges">). For Tapestry, event handler methods are
found by method naming conventions (onSomeEvent() or by method annotations
(@Event), based on a combination of the "t:id" attribute and event name, and
the action name used depends on the component. For example, the
"<t:actionlink>" component in Tapestry emits an "action" event when
clicked, and you handle that event in your "onAction()" method.</p><h2
id="TapestryforJSFUsers-Validation">Validation</h2><p>Tapestry applications can
use JSR 303 Bean Validation annotations that JSF users should be familiar
with:</p><div class="code panel pdl" style="border-width: 1px;"><div
class="codeContent panelContent pdl">
<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;">public class Employee {
@Validate("required,minlength=2,maxlength=100")
private String lastName;
@NotNull @Email private String email;
</pre>
-</div></div><h3
id="TapestryforJSFUsers-Post-Redirect-GetNavigation">Post-Redirect-Get
Navigation</h3><p>By default, most JSF URLs are "one page behind". That is,
when you click on an <h:commandLink> link or submit a form, the request
goes back to the originating page, and the server returns the contents of the
<strong>next</strong> page – but the URL in the browser shows the
previous page's URL. To fix this in JSF you add the "?faces-redirect=true" to
the URL you return from event handlers, which causes JSF to send a redirect to
the browser to navigate to the next page.</p><p>By contrast, Tapestry
implements this Post-Redirect-Get pattern by default. The URL will always
reflect the page you're seeing, not the page you just came from.</p><p>Note
that by default Tapestry does not save property values across the
Post-Redirect-Get cycle. This means that you have to consider how (and whether)
to persist property values from one page to the next. The usual solution is to
eith
er make the values part of the page's <a href="navigation.html">Activation
Context</a> (which means the values will be appended to the URL) or <a
href="persistent-page-data.html">@Persist the properties</a> the values in the
session.</p><h2 id="TapestryforJSFUsers-CustomandCompositeComponents">Custom
and Composite Components</h2><p>With JSF, creating custom components is an <a
class="external-link"
href="http://jsfcorner.blogspot.com/2011/01/custom-components.html"
rel="nofollow">advanced topic</a>. In fact, many JSF developers have
<em>never</em> created a custom component. In JSF 1.x, creating each custom
component requires a lot of work: creating 3 Java classes (component, component
renderer and component tag), registering the component in an XML file, and
registering the tag in the .tld file. In JSF 2.x <em>composite components</em>
can be created without too much work (if your needs can be met by combining
existing components <em>and</em> you don't need any custom Java), but
you still have to use cumbersome <composite:interface> and
<composite:implementation> tags in your component templates, and you have
to list the composite components in the xml namespace declaration at the top of
the pages where you are using them.</p><p>Creating true custom components in
JSF 2.0 still requires several steps: create a component class (generally
having the @FacesComponent annotation and extending UIComponentBase), create a
renderer class (generally extending Renderer), add a <renderer> section
to the facesconfig file, and create a *-taglib.xml file in the WEB_INF folder
that defines the namespace, tag and component type of the custom
component.</p><p>In contrast, with Tapestry, <a
href="component-classes.html">creating custom components</a> is a
<em>beginner</em> topic: it is expected to be a daily activity for developers,
because it is so easy. In fact, the steps are the same as creating a page. All
you have to do is create a (potentially empty)
Java class in a "components" sub-package, and create a template file
containing (X)HTML markup in the corresponding "components" sub-folder within
your package hierarchy under /src/main/resources. You <em>use</em> a custom
component just like you use any built-in Tapestry component:
<code><t:mycomponent></code>.</p><p>Because they're so easy to create,
Tapestry applications tend to have a lot of custom components and much less
repetition of HTML than most JSF applications.</p><h2
id="TapestryforJSFUsers-OtherReferences">Other References</h2><ul><li><a
class="external-link"
href="http://blog.tapestry5.de/wp-content/uploads/2010/06/JSF-2.0-vs-Tapestry-5.pdf"
rel="nofollow">JavaServer Faces 2.0 vs. Tapestry 5: A Head-to-Head
Comparison</a> slides by Igor Drobiazko, June 2010.</li><li><a
class="external-link"
href="http://docs.oracle.com/javaee/6/tutorial/doc/gkhxa.html"
rel="nofollow">Composite Components: Advanced Topics and Example</a> part of
<em>The Java EE 6 Tutorial</em>
from Oracle</li></ul><p> </p><p></p></div>
+</div></div><h3
id="TapestryforJSFUsers-Post-Redirect-GetNavigation">Post-Redirect-Get
Navigation</h3><p>By default, most JSF URLs are "one page behind". That is,
when you click on an <h:commandLink> link or submit a form, the request
goes back to the originating page, and the server returns the contents of the
<strong>next</strong> page – but the URL in the browser shows the
previous page's URL. To fix this in JSF you add the "?faces-redirect=true" to
the URL you return from event handlers, which causes JSF to send a redirect to
the browser to navigate to the next page.</p><p>By contrast, Tapestry
implements this Post-Redirect-Get pattern by default. The URL will always
reflect the page you're seeing, not the page you just came from.</p><p>Note
that by default Tapestry does not save property values across the
Post-Redirect-Get cycle. This means that you have to consider how (and whether)
to persist property values from one page to the next. The usual solution is to
eith
er make the values part of the page's <a
href="tapestry-for-jsf-users.html">Activation Context</a> (which means the
values will be appended to the URL) or <a
href="tapestry-for-jsf-users.html">@Persist the properties</a> the values in
the session.</p><h2
id="TapestryforJSFUsers-CustomandCompositeComponents">Custom and Composite
Components</h2><p>With JSF, creating custom components is an <a
class="external-link"
href="http://jsfcorner.blogspot.com/2011/01/custom-components.html"
rel="nofollow">advanced topic</a>. In fact, many JSF developers have
<em>never</em> created a custom component. In JSF 1.x, creating each custom
component requires a lot of work: creating 3 Java classes (component, component
renderer and component tag), registering the component in an XML file, and
registering the tag in the .tld file. In JSF 2.x <em>composite components</em>
can be created without too much work (if your needs can be met by combining
existing components <em>and</em> you don't need any cus
tom Java), but you still have to use cumbersome <composite:interface>
and <composite:implementation> tags in your component templates, and you
have to list the composite components in the xml namespace declaration at the
top of the pages where you are using them.</p><p>Creating true custom
components in JSF 2.0 still requires several steps: create a component class
(generally having the @FacesComponent annotation and extending
UIComponentBase), create a renderer class (generally extending Renderer), add a
<renderer> section to the facesconfig file, and create a *-taglib.xml
file in the WEB_INF folder that defines the namespace, tag and component type
of the custom component.</p><p>In contrast, with Tapestry, <a
href="tapestry-for-jsf-users.html">creating custom components</a> is a
<em>beginner</em> topic: it is expected to be a daily activity for developers,
because it is so easy. In fact, the steps are the same as creating a page. All
you have to do is create a (
potentially empty) Java class in a "components" sub-package, and create a
template file containing (X)HTML markup in the corresponding "components"
sub-folder within your package hierarchy under /src/main/resources. You
<em>use</em> a custom component just like you use any built-in Tapestry
component: <code><t:mycomponent></code>.</p><p>Because they're so easy to
create, Tapestry applications tend to have a lot of custom components and much
less repetition of HTML than most JSF applications.</p><h2
id="TapestryforJSFUsers-OtherReferences">Other References</h2><ul><li><a
class="external-link"
href="http://blog.tapestry5.de/wp-content/uploads/2010/06/JSF-2.0-vs-Tapestry-5.pdf"
rel="nofollow">JavaServer Faces 2.0 vs. Tapestry 5: A Head-to-Head
Comparison</a> slides by Igor Drobiazko, June 2010.</li><li><a
class="external-link"
href="http://docs.oracle.com/javaee/6/tutorial/doc/gkhxa.html"
rel="nofollow">Composite Components: Advanced Topics and Example</a> part of
<em>The Java
EE 6 Tutorial</em> from Oracle</li></ul><p> </p><p></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
Sat Feb 3 18:21:36 2018
@@ -27,6 +27,16 @@
</title>
<link type="text/css" rel="stylesheet" href="/resources/space.css" />
+ <link href='/resources/highlighter/styles/shCoreCXF.css'
rel='stylesheet' type='text/css' />
+ <link href='/resources/highlighter/styles/shThemeCXF.css' rel='stylesheet'
type='text/css' />
+ <script src='/resources/highlighter/scripts/shCore.js'
type='text/javascript'></script>
+ <script src='/resources/highlighter/scripts/shBrushJava.js'
type='text/javascript'></script>
+ <script src='/resources/highlighter/scripts/shBrushXml.js'
type='text/javascript'></script>
+ <script src='/resources/highlighter/scripts/shBrushPlain.js'
type='text/javascript'></script>
+ <script>
+ SyntaxHighlighter.defaults['toolbar'] = false;
+ SyntaxHighlighter.all();
+ </script>
<link href="/styles/style.css" rel="stylesheet" type="text/css"/>
@@ -67,7 +77,59 @@
</div>
<div id="content">
- <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
+ <div id="ConfluenceContent"><h2
id="TapestryInversionofControlFAQ-TapestryInversionofControlContainer">Tapestry
Inversion of Control Container</h2><p>Main article: <a
href="tapestry-inversion-of-control-faq.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
{
private boolean shuttingDown;
@@ -94,7 +156,8 @@
});
}
}
-</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>
+</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>
</div>
<div class="clearer"></div>