Modified: 
websites/production/tapestry/content/implementing-the-hi-lo-guessing-game.html
==============================================================================
--- 
websites/production/tapestry/content/implementing-the-hi-lo-guessing-game.html 
(original)
+++ 
websites/production/tapestry/content/implementing-the-hi-lo-guessing-game.html 
Wed Sep 20 12:29:16 2017
@@ -27,6 +27,15 @@
       </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>
+      SyntaxHighlighter.defaults['toolbar'] = false;
+      SyntaxHighlighter.all();
+    </script>
   
   <link href="/styles/style.css" rel="stylesheet" type="text/css"/>
 
@@ -36,26 +45,13 @@
 
   <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 &amp; 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">Implementing the Hi-Lo Guessing Game</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 &amp; 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">Implementing the Hi-Lo Guessing Game</h1></div></div>
       <div class="clearer"></div>
       </div>
 
@@ -67,7 +63,8 @@
       </div>
 
       <div id="content">
-                <div id="ConfluenceContent"><p><span style="line-height: 
1.4285715;"><br clear="none"></span></p><p><span style="line-height: 
1.4285715;">Let's start building a basic Hi-Lo Guessing game.</span></p><p>In 
the game, the computer selects a number between 1 and 10. You try and guess the 
number, clicking links. At the end, the computer tells you how many guesses you 
required to identify the target number. Even a simple example like this will 
demonstrate several important concepts in Tapestry:</p><ul><li>Breaking an 
application into individual pages</li><li>Transferring information from one 
page to another</li><li>Responding to user interactions</li><li>Storing client 
information in the server-side session</li></ul><p>We'll build this little 
application in small pieces, using the kind of iterative development that 
Tapestry makes so easy.</p><p><span 
class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image" 
src="implementing-the-hi-lo-guessing-game.dat
 a/hilo-flow.png"></span></p><p>Our page flow is very simple, consisting of 
three pages: Index (the starting page), Guess and GameOver. The Index page 
introduces the application and includes a link to start guessing. The Guess 
page presents the user with ten links, plus feedback such as "too low" or "too 
high". The GameOver page tells the user how many guesses they took before 
finding the target number.</p><h1 
id="ImplementingtheHi-LoGuessingGame-IndexPage">Index Page</h1><p>Let's get to 
work on the Index page and template. Make Index.tml look like 
this:</p><parameter ac:name="language">xml</parameter><parameter 
ac:name="lang">xml</parameter><parameter 
ac:name="title">Index.tml</parameter><plain-text-body>&lt;html t:type="layout" 
title="Hi/Lo Guess"
+                <div id="ConfluenceContent"><p><span style="line-height: 
1.4285715;"><br clear="none"></span></p><p><span style="line-height: 
1.4285715;">Let's start building a basic Hi-Lo Guessing game.</span></p><p>In 
the game, the computer selects a number between 1 and 10. You try and guess the 
number, clicking links. At the end, the computer tells you how many guesses you 
required to identify the target number. Even a simple example like this will 
demonstrate several important concepts in Tapestry:</p><ul><li>Breaking an 
application into individual pages</li><li>Transferring information from one 
page to another</li><li>Responding to user interactions</li><li>Storing client 
information in the server-side session</li></ul><p>We'll build this little 
application in small pieces, using the kind of iterative development that 
Tapestry makes so easy.</p><p><span 
class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image" 
src="implementing-the-hi-lo-guessing-game.dat
 a/hilo-flow.png"></span></p><p>Our page flow is very simple, consisting of 
three pages: Index (the starting page), Guess and GameOver. The Index page 
introduces the application and includes a link to start guessing. The Guess 
page presents the user with ten links, plus feedback such as "too low" or "too 
high". The GameOver page tells the user how many guesses they took before 
finding the target number.</p><h1 
id="ImplementingtheHi-LoGuessingGame-IndexPage">Index Page</h1><p>Let's get to 
work on the Index page and template. Make Index.tml look like this:</p><div 
class="code panel pdl" style="border-width: 1px;"><div class="codeHeader 
panelHeader pdl" style="border-bottom-width: 1px;"><b>Index.tml</b></div><div 
class="codeContent panelContent pdl">
+<pre class="brush: xml; gutter: false; theme: Default" 
style="font-size:12px;">&lt;html t:type="layout" title="Hi/Lo Guess"
     xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd"&gt;
 
     &lt;p&gt;
@@ -78,15 +75,21 @@
     &lt;/p&gt;
 
 &lt;/html&gt;
-</plain-text-body><p>And edit the corresponding Java class, Index.java, 
removing its body (but you can leave the imports in place for 
now):</p><parameter ac:name="language">java</parameter><parameter 
ac:name="lang">java</parameter><parameter 
ac:name="title">Index.java</parameter><plain-text-body>package 
com.example.tutorial1.pages;
+</pre>
+</div></div><p>And edit the corresponding Java class, Index.java, removing its 
body (but you can leave the imports in place for now):</p><div class="code 
panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" 
style="border-bottom-width: 1px;"><b>Index.java</b></div><div 
class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">package com.example.tutorial1.pages;
 
 public class Index
 {
 }
-</plain-text-body><p>Running the application gives us our start:</p><p><span 
class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image" 
src="implementing-the-hi-lo-guessing-game.data/hilo-1.png"></span></p><p>However,
 clicking the link doesn't do anything yet, as its just a placeholder &lt;a&gt; 
tag, not an actual Tapestry component. Let's think about what should happen 
when the user clicks that link:</p><ul><li>A random target number between 1 and 
10 should be selected</li><li>The number of guesses taken should be reset to 
0</li><li>The user should be sent to the Guess page to make a 
guess</li></ul><p>Our first step is to find out when the user clicks that 
"start guessing" link. In a typical web application framework, we might start 
thinking about URLs and handlers and maybe some sort of XML configuration file. 
But this is Tapestry, so we're going to work with components and methods on our 
classes.</p><p>First, the component. We want to perform an action (selec
 ting the number) before continuing on to the Guess page. The ActionLink 
component is just what we need; it creates a link with a URL that will trigger 
an action event in our code ... but that's getting ahead of ourselves. First 
up, convert the &lt;a&gt; tag to an ActionLink component:</p><parameter 
ac:name="language">xml</parameter><parameter 
ac:name="lang">xml</parameter><parameter ac:name="title">Index.tml 
(partial)</parameter><plain-text-body>    &lt;p&gt;
+</pre>
+</div></div><p>Running the application gives us our start:</p><p><span 
class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image" 
src="implementing-the-hi-lo-guessing-game.data/hilo-1.png"></span></p><p>However,
 clicking the link doesn't do anything yet, as its just a placeholder &lt;a&gt; 
tag, not an actual Tapestry component. Let's think about what should happen 
when the user clicks that link:</p><ul><li>A random target number between 1 and 
10 should be selected</li><li>The number of guesses taken should be reset to 
0</li><li>The user should be sent to the Guess page to make a 
guess</li></ul><p>Our first step is to find out when the user clicks that 
"start guessing" link. In a typical web application framework, we might start 
thinking about URLs and handlers and maybe some sort of XML configuration file. 
But this is Tapestry, so we're going to work with components and methods on our 
classes.</p><p>First, the component. We want to perform an action (selecting t
 he number) before continuing on to the Guess page. The ActionLink component is 
just what we need; it creates a link with a URL that will trigger an action 
event in our code ... but that's getting ahead of ourselves. First up, convert 
the &lt;a&gt; tag to an ActionLink component:</p><div class="code panel pdl" 
style="border-width: 1px;"><div class="codeHeader panelHeader pdl" 
style="border-bottom-width: 1px;"><b>Index.tml (partial)</b></div><div 
class="codeContent panelContent pdl">
+<pre class="brush: xml; gutter: false; theme: Default" 
style="font-size:12px;">    &lt;p&gt;
         &lt;t:actionlink t:id="start"&gt;start guessing&lt;/t:actionlink&gt;
     &lt;/p&gt;
-</plain-text-body><p>If you refresh the browser and hover your mouse over the 
"start guessing" link, you'll see that its URL is now /tutorial1/index.start, 
which identifies the name of the page ("index") and the id of the component 
("start").</p><p>If you click the link now, you'll get an error:</p><p><span 
class="confluence-embedded-file-wrapper image-center-wrapper 
confluence-embedded-manual-size"><img class="confluence-embedded-image 
image-center" width="500" 
src="implementing-the-hi-lo-guessing-game.data/Application_Exception.png"></span></p><p>&#160;</p><p>Tapestry
 is telling us that we need to provide some kind of event handler for that 
event. What does that look like?</p><p>An event handler is a method of the Java 
class with a special name. The name is 
<code>on</code><strong><em>Eventname</em></strong><code>From</code><strong><em>Component-id</em></strong>
 ... here we want a method named <code>onActionFromStart()</code>. How do we 
know that "action" is the right event name? B
 ecause that's what ActionLink does, that's why its named 
<strong><em>Action</em></strong>Link.</p><p>Once again, Tapestry gives us 
options; if you don't like naming conventions, there's an @<a  
class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/OnEvent.html";>OnEvent</a>
 annotation you can place on the method instead, which restores the freedom to 
name the method as you like. Details about this approach are in the <a  
href="component-events.html">Tapestry Users' Guide</a>. We'll be sticking with 
the naming convention approach for the tutorial.</p><p>When handling a 
component event request (the kind of request triggered by the ActionLink 
component's URL), Tapestry will find the component and trigger a component 
event on it. This is the callback our server-side code needs to figure out what 
the user is doing on the client side. Let's start with an empty event 
handler:</p><parameter ac:name="language">java</parameter><parameter ac:nam
 e="lang">java</parameter><parameter 
ac:name="title">Index.java</parameter><plain-text-body>package 
com.example.tutorial1.pages;
+</pre>
+</div></div><p>If you refresh the browser and hover your mouse over the "start 
guessing" link, you'll see that its URL is now /tutorial1/index.start, which 
identifies the name of the page ("index") and the id of the component 
("start").</p><p>If you click the link now, you'll get an error:</p><p><span 
class="confluence-embedded-file-wrapper image-center-wrapper 
confluence-embedded-manual-size"><img class="confluence-embedded-image 
image-center" width="500" 
src="implementing-the-hi-lo-guessing-game.data/Application_Exception.png"></span></p><p>&#160;</p><p>Tapestry
 is telling us that we need to provide some kind of event handler for that 
event. What does that look like?</p><p>An event handler is a method of the Java 
class with a special name. The name is 
<code>on</code><strong><em>Eventname</em></strong><code>From</code><strong><em>Component-id</em></strong>
 ... here we want a method named <code>onActionFromStart()</code>. How do we 
know that "action" is the right event name? Because
  that's what ActionLink does, that's why its named 
<strong><em>Action</em></strong>Link.</p><p>Once again, Tapestry gives us 
options; if you don't like naming conventions, there's an @<a  
class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/OnEvent.html";>OnEvent</a>
 annotation you can place on the method instead, which restores the freedom to 
name the method as you like. Details about this approach are in the <a  
href="component-events.html">Tapestry Users' Guide</a>. We'll be sticking with 
the naming convention approach for the tutorial.</p><p>When handling a 
component event request (the kind of request triggered by the ActionLink 
component's URL), Tapestry will find the component and trigger a component 
event on it. This is the callback our server-side code needs to figure out what 
the user is doing on the client side. Let's start with an empty event 
handler:</p><div class="code panel pdl" style="border-width: 1px;"><div 
class="co
 deHeader panelHeader pdl" style="border-bottom-width: 
1px;"><b>Index.java</b></div><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">package com.example.tutorial1.pages;
 
 public class Index
 {
@@ -95,7 +98,9 @@ public class Index
 
     }
 }
-</plain-text-body><p>In the browser, we can re-try the failed component event 
request by hitting the refresh button ... or we can restart the application. In 
either case, we get the default behavior, which is simply to re-render the 
page.</p><p>Note that the event handler method does not have to be public; it 
can be protected, private, or package private (as in this example). By 
convention, such methods are package private, if for no other reason than it is 
the minimal amount of characters to type.</p><p>Hmm... right now you have to 
trust us that the method got invoked. That's no good ... what's a quick way to 
tell for sure? One way would be have the method throw an exception, but that's 
a bit ugly.</p><p>How about this: add the @<a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Log.html";>Log</a>
 annotation to the method:</p><parameter 
ac:name="language">java</parameter><parameter 
ac:name="lang">java</parameter><parameter ac:
 name="title">Index.java (partial)</parameter><plain-text-body>import 
org.apache.tapestry5.annotations.Log;
+</pre>
+</div></div><p>In the browser, we can re-try the failed component event 
request by hitting the refresh button ... or we can restart the application. In 
either case, we get the default behavior, which is simply to re-render the 
page.</p><p>Note that the event handler method does not have to be public; it 
can be protected, private, or package private (as in this example). By 
convention, such methods are package private, if for no other reason than it is 
the minimal amount of characters to type.</p><p>Hmm... right now you have to 
trust us that the method got invoked. That's no good ... what's a quick way to 
tell for sure? One way would be have the method throw an exception, but that's 
a bit ugly.</p><p>How about this: add the @<a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Log.html";>Log</a>
 annotation to the method:</p><div class="code panel pdl" style="border-width: 
1px;"><div class="codeHeader panelHeader pdl" style="border
 -bottom-width: 1px;"><b>Index.java (partial)</b></div><div class="codeContent 
panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">import org.apache.tapestry5.annotations.Log;
 
 . . .
 
@@ -104,11 +109,15 @@ public class Index
     {
 
     }
-</plain-text-body><p>When you next click the link you should see the following 
in the Eclipse console:</p><plain-text-body>[DEBUG] pages.Index [ENTER] 
onActionFromStart()
+</pre>
+</div></div><p>When you next click the link you should see the following in 
the Eclipse console:</p><div class="preformatted panel" style="border-width: 
1px;"><div class="preformattedContent panelContent">
+<pre>[DEBUG] pages.Index [ENTER] onActionFromStart()
 [DEBUG] pages.Index [ EXIT] onActionFromStart
 [INFO] AppModule.TimingFilter Request time: 3 ms
 [INFO] AppModule.TimingFilter Request time: 5 ms
-</plain-text-body><p>The @Log annotation directs Tapestry to log method entry 
and exit. You'll get to see any parameters passed into the method, and any 
return value from the method ... as well as any exception thrown from within 
the method. It's a powerful debugging tool. This is an example of Tapestry's 
meta-programming power, something we'll use quite a bit of in the 
tutorial.</p><p>Why do we see two requests for one click? Tapestry uses an 
approach based on the <a  class="external-link" 
href="http://en.wikipedia.org/wiki/Post/Redirect/Get"; 
rel="nofollow">Post/Redirect/Get</a> pattern. In fact, Tapestry generally 
performs a redirect after each component event. So the first request was to 
process the action, and the second request was to re-render the Index page. You 
can see this in the browser, because the URL is still "/tutorial1" (the URL for 
rendering the Index page). We'll return to this in a bit.</p><p>We're ready for 
the next step, which involves tying together the Index an
 d Guess pages. Index will select a target number for the user to Guess, then 
"pass the baton" to the Guess page.</p><p>Let's start by thinking about the 
Guess page. It needs a variable to store the target value in, and it needs a 
method that the Index page can invoke, to set up that target 
value.</p><parameter ac:name="language">java</parameter><parameter 
ac:name="title">Guess.java</parameter><plain-text-body>package 
com.example.tutorial1.pages;
+</pre>
+</div></div><p>The @Log annotation directs Tapestry to log method entry and 
exit. You'll get to see any parameters passed into the method, and any return 
value from the method ... as well as any exception thrown from within the 
method. It's a powerful debugging tool. This is an example of Tapestry's 
meta-programming power, something we'll use quite a bit of in the 
tutorial.</p><p>Why do we see two requests for one click? Tapestry uses an 
approach based on the <a  class="external-link" 
href="http://en.wikipedia.org/wiki/Post/Redirect/Get"; 
rel="nofollow">Post/Redirect/Get</a> pattern. In fact, Tapestry generally 
performs a redirect after each component event. So the first request was to 
process the action, and the second request was to re-render the Index page. You 
can see this in the browser, because the URL is still "/tutorial1" (the URL for 
rendering the Index page). We'll return to this in a bit.</p><p>We're ready for 
the next step, which involves tying together the Index and Gues
 s pages. Index will select a target number for the user to Guess, then "pass 
the baton" to the Guess page.</p><p>Let's start by thinking about the Guess 
page. It needs a variable to store the target value in, and it needs a method 
that the Index page can invoke, to set up that target value.</p><div 
class="code panel pdl" style="border-width: 1px;"><div class="codeHeader 
panelHeader pdl" style="border-bottom-width: 1px;"><b>Guess.java</b></div><div 
class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">package com.example.tutorial1.pages;
 
 public class Guess
 {
@@ -119,7 +128,9 @@ public class Guess
         this.target = target;
     }
 }
-</plain-text-body><p>Create that Guess.java file in the same folder as 
Index.java. Next, we can modify Index to invoke the <code>setup()</code> method 
of our new Guess page class:</p><parameter 
ac:name="language">java</parameter><parameter 
ac:name="lang">java</parameter><parameter ac:name="title">Index.java 
(revised)</parameter><plain-text-body>package com.example.tutorial1.pages;
+</pre>
+</div></div><p>Create that Guess.java file in the same folder as Index.java. 
Next, we can modify Index to invoke the <code>setup()</code> method of our new 
Guess page class:</p><div class="code panel pdl" style="border-width: 
1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 
1px;"><b>Index.java (revised)</b></div><div class="codeContent panelContent 
pdl">
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">package com.example.tutorial1.pages;
 
 import java.util.Random;
 
@@ -142,7 +153,9 @@ public class Index
         return guess;
     }
 }
-</plain-text-body><p>The new event handler method now chooses the target 
number, and tells the Guess page about it. Because Tapestry is a managed 
environment, we don't just create an instance of Guess ... it is Tapestry's 
responsibility to manage the life cycle of the Guess page. Instead, we ask 
Tapestry for the Guess page, using the @InjectPage 
annotation.</p><rich-text-body><p>All fields in a Tapestry page or component 
class must be <strong>non-public</strong>.</p></rich-text-body><p>Once we have 
that Guess page instance, we can invoke methods on it normally.</p><p>Returning 
a page instance from an event handler method directs Tapestry to send a 
client-side redirect to the returned page, rather than sending a redirect for 
the active page. Thus once the user clicks the "start guessing" link, they'll 
see the Guess page.</p><rich-text-body><p>When creating your own applications, 
make sure that the objects stored in final variables are thread safe. It seems 
counter-intuitive, but fina
 l variables are shared across many threads. Ordinary instance variables are 
not. Fortunately, the implementation of Random is, in fact, thread 
safe.</p></rich-text-body><p>So ... let's click the link and see what we 
get:</p><p><span class="confluence-embedded-file-wrapper"><img 
class="confluence-embedded-image" 
src="implementing-the-hi-lo-guessing-game.data/guess-template-missing.png"></span></p><p>Ah!
 We didn't create a Guess page template. Tapestry was really expecting us to 
create one, so we better do so.</p><parameter 
ac:name="language">java</parameter><parameter 
ac:name="lang">xml</parameter><parameter 
ac:name="title">src/main/resources/com/example/tutorial/pages/Guess.tml</parameter><plain-text-body>&lt;html
 t:type="layout" title="Guess The Number"
+</pre>
+</div></div><p>The new event handler method now chooses the target number, and 
tells the Guess page about it. Because Tapestry is a managed environment, we 
don't just create an instance of Guess ... it is Tapestry's responsibility to 
manage the life cycle of the Guess page. Instead, we ask Tapestry for the Guess 
page, using the @InjectPage annotation.</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>All fields in a Tapestry page or 
component class must be <strong>non-public</strong>.</p></div></div><p>Once we 
have that Guess page instance, we can invoke methods on it 
normally.</p><p>Returning a page instance from an event handler method directs 
Tapestry to send a client-side redirect to the returned page, rather than 
sending a redirect for the active page. Thus once the user clicks the "start 
guessing" lin
 k, they'll see the Guess page.</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>When creating your own 
applications, make sure that the objects stored in final variables are thread 
safe. It seems counter-intuitive, but final variables are shared across many 
threads. Ordinary instance variables are not. Fortunately, the implementation 
of Random is, in fact, thread safe.</p></div></div><p>So ... let's click the 
link and see what we get:</p><p><span 
class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image" 
src="implementing-the-hi-lo-guessing-game.data/guess-template-missing.png"></span></p><p>Ah!
 We didn't create a Guess page template. Tapestry was really expecting us to 
create one, so we better do so.</p><div class="code panel pdl" 
style="border-width: 1px;"><div class="codeHeader pan
 elHeader pdl" style="border-bottom-width: 
1px;"><b>src/main/resources/com/example/tutorial/pages/Guess.tml</b></div><div 
class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">&lt;html t:type="layout" title="Guess The Number"
     xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd"&gt;
 
     &lt;p&gt;
@@ -150,12 +163,18 @@ public class Index
     &lt;/p&gt;
   
 &lt;/html&gt;
-</plain-text-body><p>Hit the browser's back button, then click the "start 
guessing" link again. We're getting closer:</p><p><span 
class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image" 
src="implementing-the-hi-lo-guessing-game.data/guess-no-target-prop.png"></span></p><p>If
 you scroll down, you'll see the line of the Guess.tml template that has the 
error. We have a field named target, but it is private and there's no 
corresponding property, so Tapestry was unable to access it.</p><p>We just need 
to write the missing JavaBeans accessor methods <code>getTarget()</code> (and 
<code>setTarget()</code> for good measure). Or we could let Tapestry write 
those methods instead:</p><parameter 
ac:name="language">java</parameter><parameter 
ac:name="lang">java</parameter><plain-text-body>    @Property
+</pre>
+</div></div><p>Hit the browser's back button, then click the "start guessing" 
link again. We're getting closer:</p><p><span 
class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image" 
src="implementing-the-hi-lo-guessing-game.data/guess-no-target-prop.png"></span></p><p>If
 you scroll down, you'll see the line of the Guess.tml template that has the 
error. We have a field named target, but it is private and there's no 
corresponding property, so Tapestry was unable to access it.</p><p>We just need 
to write the missing JavaBeans accessor methods <code>getTarget()</code> (and 
<code>setTarget()</code> for good measure). Or we could let Tapestry write 
those methods instead:</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;">    @Property
     private int target;
-</plain-text-body><p>The @<a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Property.html";>Property</a>
 annotation very simply directs Tapestry to write the getter and setter method 
for you. You only need to do this if you are going to reference the field from 
the template.</p><p>We are getting very close but there's one last big oddity 
to handle. Once you refresh the page you'll see that target is 0!</p><p><span 
class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image" 
src="implementing-the-hi-lo-guessing-game.data/guess-target-zero.png"></span></p><p>What
 gives? We know it was set to at least 1 ... where did the value go?</p><p>As 
noted above, Tapestry sends a redirect to the client after handling the event 
request. That means that the rendering of the page happens in an entirely new 
request. Meanwhile, at the end of each request, Tapestry wipes out the value in 
each instance variable. So that means th
 at target <em>was</em> a non-zero number during the component event request 
... but by the time the new page render request comes up from the web browser 
to render the Guess page, the value of the target field has reverted back to 
its default, zero.</p><p>The solution here is to mark which fields have values 
that should persist from one request to the next (and next, and next ...). 
That's what the @<a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Persist.html";>Persist</a>
 annotation is for:</p><parameter ac:name="language">java</parameter><parameter 
ac:name="lang">java</parameter><plain-text-body>    @Property  
+</pre>
+</div></div><p>The @<a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Property.html";>Property</a>
 annotation very simply directs Tapestry to write the getter and setter method 
for you. You only need to do this if you are going to reference the field from 
the template.</p><p>We are getting very close but there's one last big oddity 
to handle. Once you refresh the page you'll see that target is 0!</p><p><span 
class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image" 
src="implementing-the-hi-lo-guessing-game.data/guess-target-zero.png"></span></p><p>What
 gives? We know it was set to at least 1 ... where did the value go?</p><p>As 
noted above, Tapestry sends a redirect to the client after handling the event 
request. That means that the rendering of the page happens in an entirely new 
request. Meanwhile, at the end of each request, Tapestry wipes out the value in 
each instance variable. So that means that tar
 get <em>was</em> a non-zero number during the component event request ... but 
by the time the new page render request comes up from the web browser to render 
the Guess page, the value of the target field has reverted back to its default, 
zero.</p><p>The solution here is to mark which fields have values that should 
persist from one request to the next (and next, and next ...). That's what the 
@<a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Persist.html";>Persist</a>
 annotation is for:</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;">    @Property  
     @Persist
     private int target;
-</plain-text-body><p>This doesn't have anything to do with database 
persistence (that's coming up in a later chapter). It means that the value is 
stored in the HttpSession between requests.</p><p>Go back to the Index page and 
click the link again. Finally, we have a target number:</p><p><span 
class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image" 
src="implementing-the-hi-lo-guessing-game.data/guess-target.png"></span></p><p>That's
 enough for us to get started. Let's build out the Guess page, and get ready to 
let the user make guesses. We'll show the count of guesses, and increment that 
count when they make them. We'll worry about high and low and actually 
selecting the correct value later.</p><p>When building Tapestry pages, you 
sometimes start with the Java code and build the template to match, and 
sometime start with the template and build the Java code to match. Both 
approaches are valid. Here, lets start with the markup in the template, then 
figure out w
 hat we need in the Java code to make it work.</p><parameter 
ac:name="language">xml</parameter><parameter 
ac:name="lang">xml</parameter><parameter ac:name="title">Guess.tml 
(revised)</parameter><plain-text-body>&lt;html t:type="layout" title="Guess The 
Number"
+</pre>
+</div></div><p>This doesn't have anything to do with database persistence 
(that's coming up in a later chapter). It means that the value is stored in the 
HttpSession between requests.</p><p>Go back to the Index page and click the 
link again. Finally, we have a target number:</p><p><span 
class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image" 
src="implementing-the-hi-lo-guessing-game.data/guess-target.png"></span></p><p>That's
 enough for us to get started. Let's build out the Guess page, and get ready to 
let the user make guesses. We'll show the count of guesses, and increment that 
count when they make them. We'll worry about high and low and actually 
selecting the correct value later.</p><p>When building Tapestry pages, you 
sometimes start with the Java code and build the template to match, and 
sometime start with the template and build the Java code to match. Both 
approaches are valid. Here, lets start with the markup in the template, then 
figure out what we
  need in the Java code to make it work.</p><div class="code panel pdl" 
style="border-width: 1px;"><div class="codeHeader panelHeader pdl" 
style="border-bottom-width: 1px;"><b>Guess.tml (revised)</b></div><div 
class="codeContent panelContent pdl">
+<pre class="brush: xml; gutter: false; theme: Default" 
style="font-size:12px;">&lt;html t:type="layout" title="Guess The Number"
     xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd";
     xmlns:p="tapestry:parameter"&gt;
  
@@ -177,7 +196,9 @@ public class Index
     &lt;/ul&gt;
  
 &lt;/html&gt;
-</plain-text-body><p>So it looks like we need a <code>guessCount</code> 
property that starts at 1.</p><p>We're also seeing one new component, the Loop 
component. A Loop component iterates over the values passed to it in its 
<code>source</code> parameter, and renders it body once for each value. It 
updates the property bound to its <code>value</code> parameter before rendering 
its body.</p><p>That special property expression, <code>1..10</code>, generates 
a series of numbers from 1 to 10, inclusive. usually, when you use the Loop 
component, you are iterating over a List or Collection of values, such as the 
results of a database query.</p><p>So, the Loop component is going to set the 
<code>current</code> property to 1, and render its body (the \&lt;li\&gt; tag, 
and the ActionLink component). Then its going to set the <code>current</code> 
property to 2 and render its body again ... all the way up to 10.</p><p>And 
notice what we're doing with the ActionLink component; its no longer enou
 gh to know the user clicked on the ActionLink ... we need to know <em>which 
iteration</em> the user clicked on. The <code>context</code> parameter allows a 
value to be added to the ActionLink's URL, and we can get it back in the event 
handler method.</p><rich-text-body><p>The URL for the ActionLink will be 
<code>/tutorial1/guess.makeguess/3</code>. That's the page name, "Guess", the 
component id, "makeGuess", and the context value, 
"3".</p></rich-text-body><parameter 
ac:name="language">java</parameter><parameter 
ac:name="lang">java</parameter><parameter ac:name="title">Guess.java 
(revised)</parameter><plain-text-body>package com.example.tutorial1.pages;
+</pre>
+</div></div><p>So it looks like we need a <code>guessCount</code> property 
that starts at 1.</p><p>We're also seeing one new component, the Loop 
component. A Loop component iterates over the values passed to it in its 
<code>source</code> parameter, and renders it body once for each value. It 
updates the property bound to its <code>value</code> parameter before rendering 
its body.</p><p>That special property expression, <code>1..10</code>, generates 
a series of numbers from 1 to 10, inclusive. usually, when you use the Loop 
component, you are iterating over a List or Collection of values, such as the 
results of a database query.</p><p>So, the Loop component is going to set the 
<code>current</code> property to 1, and render its body (the \&lt;li\&gt; tag, 
and the ActionLink component). Then its going to set the <code>current</code> 
property to 2 and render its body again ... all the way up to 10.</p><p>And 
notice what we're doing with the ActionLink component; its no longer enough to 
 know the user clicked on the ActionLink ... we need to know <em>which 
iteration</em> the user clicked on. The <code>context</code> parameter allows a 
value to be added to the ActionLink's URL, and we can get it back in the event 
handler method.</p><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>The URL for the ActionLink will be 
<code>/tutorial1/guess.makeguess/3</code>. That's the page name, "Guess", the 
component id, "makeGuess", and the context value, "3".</p></div></div><div 
class="code panel pdl" style="border-width: 1px;"><div class="codeHeader 
panelHeader pdl" style="border-bottom-width: 1px;"><b>Guess.java 
(revised)</b></div><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">package com.example.tutorial1.pages;
 
 import org.apache.tapestry5.annotations.Persist;
 import org.apache.tapestry5.annotations.Property;
@@ -203,13 +224,17 @@ public class Guess
     }
 
 }
-</plain-text-body><p>The revised version of Guess includes two new properties: 
<code>current</code> and <code>guessCount</code>. There's also a handler for 
the action event from the makeGuess ActionLink component; currently it just 
increments the count.</p><p>Notice that the 
<code>onActionFromMakeGuess()</code> method now has a parameter: the context 
value that was encoded into the URL by the ActionLink. When then user clicks 
the link, Tapestry will automatically extract the string from the URL, convert 
it to an int and pass that int value into the event handler method. More 
boilerplate code you don't have to write.</p><p>At this point, the page is 
partially operational:</p><p><span 
class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image" 
src="implementing-the-hi-lo-guessing-game.data/guess-1.png"></span></p><p>Our 
next step is to actually check the value provided by the user against the 
target and provide feedback: either they guessed too high, or too low, or
  just right. If they get it just right, we'll switch to the GameOver page with 
a message such as "You guessed the number 5 in 2 guesses".</p><p>Let's start 
with the Guess page; it now needs a new property to store the message to be 
displayed to the user, and needs a field for the injected GameOver 
page:</p><parameter ac:name="language">java</parameter><parameter 
ac:name="lang">java</parameter><parameter ac:name="title">Guess.java 
(partial)</parameter><plain-text-body>    @Property
+</pre>
+</div></div><p>The revised version of Guess includes two new properties: 
<code>current</code> and <code>guessCount</code>. There's also a handler for 
the action event from the makeGuess ActionLink component; currently it just 
increments the count.</p><p>Notice that the 
<code>onActionFromMakeGuess()</code> method now has a parameter: the context 
value that was encoded into the URL by the ActionLink. When then user clicks 
the link, Tapestry will automatically extract the string from the URL, convert 
it to an int and pass that int value into the event handler method. More 
boilerplate code you don't have to write.</p><p>At this point, the page is 
partially operational:</p><p><span 
class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image" 
src="implementing-the-hi-lo-guessing-game.data/guess-1.png"></span></p><p>Our 
next step is to actually check the value provided by the user against the 
target and provide feedback: either they guessed too high, or too low, or just 
 right. If they get it just right, we'll switch to the GameOver page with a 
message such as "You guessed the number 5 in 2 guesses".</p><p>Let's start with 
the Guess page; it now needs a new property to store the message to be 
displayed to the user, and needs a field for the injected GameOver 
page:</p><div class="code panel pdl" style="border-width: 1px;"><div 
class="codeHeader panelHeader pdl" style="border-bottom-width: 
1px;"><b>Guess.java (partial)</b></div><div class="codeContent panelContent 
pdl">
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">    @Property
     @Persist(PersistenceConstants.FLASH)
     private String message;
 
     @InjectPage
     private GameOver gameOver;
-</plain-text-body><p>First off, we're seeing a variation of the @Persist 
annotation, where a persistence <em>strategy</em> is provided by name. <a  
class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/PersistenceConstants.html#FLASH";>FLASH</a>
 is a built-in strategy that stores the value in the session, but only for one 
request ... it's designed specifically for these kind of feedback messages. If 
you hit F5 in the browser, to refresh, the page will render but the message 
will disappear.</p><p>Next, we need some more logic in the 
<code>onActionFromMakeGuess()</code> event handler method:</p><parameter 
ac:name="language">java</parameter><parameter 
ac:name="lang">java</parameter><parameter ac:name="title">Guess.java 
(partial)</parameter><plain-text-body>    Object onActionFromMakeGuess(int 
value)
+</pre>
+</div></div><p>First off, we're seeing a variation of the @Persist annotation, 
where a persistence <em>strategy</em> is provided by name. <a  
class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/PersistenceConstants.html#FLASH";>FLASH</a>
 is a built-in strategy that stores the value in the session, but only for one 
request ... it's designed specifically for these kind of feedback messages. If 
you hit F5 in the browser, to refresh, the page will render but the message 
will disappear.</p><p>Next, we need some more logic in the 
<code>onActionFromMakeGuess()</code> event handler method:</p><div class="code 
panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" 
style="border-bottom-width: 1px;"><b>Guess.java (partial)</b></div><div 
class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">    Object onActionFromMakeGuess(int value)
     {
         if (value == target)
         {
@@ -224,14 +249,18 @@ public class Guess
 
         return null;
     }
-</plain-text-body><p>Again, very straight-forward. If the value is correct, 
then we configure the GameOver page and return it, causing a redirect to that 
page. Otherwise, we increment the number of guesses, and format the message to 
display to the user.</p><p>In the template, we just need to add some markup to 
display the message:</p><parameter ac:name="language">xml</parameter><parameter 
ac:name="lang">xml</parameter><parameter ac:name="title">Guess.tml 
(partial)</parameter><plain-text-body>    &lt;strong&gt;Guess number 
${guessCount}&lt;/strong&gt;
+</pre>
+</div></div><p>Again, very straight-forward. If the value is correct, then we 
configure the GameOver page and return it, causing a redirect to that page. 
Otherwise, we increment the number of guesses, and format the message to 
display to the user.</p><p>In the template, we just need to add some markup to 
display the message:</p><div class="code panel pdl" style="border-width: 
1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 
1px;"><b>Guess.tml (partial)</b></div><div class="codeContent panelContent pdl">
+<pre class="brush: xml; gutter: false; theme: Default" 
style="font-size:12px;">    &lt;strong&gt;Guess number 
${guessCount}&lt;/strong&gt;
 
     &lt;t:if test="message"&gt;
         &lt;p&gt;
             &lt;strong&gt;${message}&lt;/strong&gt;
         &lt;/p&gt;
     &lt;/t:if&gt;
-</plain-text-body><p>This snippet uses Tapestry's <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/If.html";>If</a>
 component. The If component evaluates its <code>test</code> parameter and, if 
the value evaluates to true, renders its body. The property bound to 
<code>test</code> doesn't have to be a boolean; Tapestry treats 
<code>null</code> as false, it treats zero as false and non-zero as true, it 
treats an empty Collection as false ... and for Strings (such as 
<code>message</code>) it treats a blank string (one that is null, or consists 
only of white space) as false, and a non-blank string is true.</p><p>We can 
wrap up with the "GameOver" page:</p><parameter 
ac:name="language">java</parameter><parameter 
ac:name="title">GameOver.java</parameter><plain-text-body>package 
com.example.tutorial1.pages;
+</pre>
+</div></div><p>This snippet uses Tapestry's <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/If.html";>If</a>
 component. The If component evaluates its <code>test</code> parameter and, if 
the value evaluates to true, renders its body. The property bound to 
<code>test</code> doesn't have to be a boolean; Tapestry treats 
<code>null</code> as false, it treats zero as false and non-zero as true, it 
treats an empty Collection as false ... and for Strings (such as 
<code>message</code>) it treats a blank string (one that is null, or consists 
only of white space) as false, and a non-blank string is true.</p><p>We can 
wrap up with the "GameOver" page:</p><div class="code panel pdl" 
style="border-width: 1px;"><div class="codeHeader panelHeader pdl" 
style="border-bottom-width: 1px;"><b>GameOver.java</b></div><div 
class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">package com.example.tutorial1.pages;
 
 import org.apache.tapestry5.annotations.Persist;
 import org.apache.tapestry5.annotations.Property;
@@ -248,7 +277,9 @@ public class GameOver
         this.guessCount = guessCount;
     }
 }
-</plain-text-body><parameter ac:name="language">xml</parameter><parameter 
ac:name="title">GameOver.tml</parameter><plain-text-body>&lt;html 
t:type="layout" title="Game Over"
+</pre>
+</div></div><div class="code panel pdl" style="border-width: 1px;"><div 
class="codeHeader panelHeader pdl" style="border-bottom-width: 
1px;"><b>GameOver.tml</b></div><div class="codeContent panelContent pdl">
+<pre class="brush: xml; gutter: false; theme: Default" 
style="font-size:12px;">&lt;html t:type="layout" title="Game Over"
     xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd";
     xmlns:p="tapestry:parameter"&gt;
 
@@ -261,7 +292,8 @@ public class GameOver
     &lt;/p&gt;
   
 &lt;/html&gt;
-</plain-text-body><p>The result, when you guess correctly, should be 
this:</p><p><span class="confluence-embedded-file-wrapper"><img 
class="confluence-embedded-image" 
src="implementing-the-hi-lo-guessing-game.data/gameover.png"></span></p><p>That 
wraps up the basics of Tapestry; we've demonstrated the basics of linking pages 
together and passing information from page to page in code as well as 
incorporating data inside URLs.</p><p>There's still more room to refactor this 
toy application; for example, making it possible to start a new game from the 
GameOver page (and doing it in a way that doesn't duplicate code). In addition, 
later we'll see other ways of sharing information between pages that are less 
cumbersome than the setup-and-persist approach shown here.</p><p>Next up: let's 
find out how Tapestry handles HTML forms and user input.</p><p>Next: <a  
href="using-beaneditform-to-create-user-forms.html">Using BeanEditForm To 
Create User Forms</a></p><p></p><p>&#160;</p><p>&#160;</p>
 </div>
+</pre>
+</div></div><p>The result, when you guess correctly, should be 
this:</p><p><span class="confluence-embedded-file-wrapper"><img 
class="confluence-embedded-image" 
src="implementing-the-hi-lo-guessing-game.data/gameover.png"></span></p><p>That 
wraps up the basics of Tapestry; we've demonstrated the basics of linking pages 
together and passing information from page to page in code as well as 
incorporating data inside URLs.</p><p>There's still more room to refactor this 
toy application; for example, making it possible to start a new game from the 
GameOver page (and doing it in a way that doesn't duplicate code). In addition, 
later we'll see other ways of sharing information between pages that are less 
cumbersome than the setup-and-persist approach shown here.</p><p>Next up: let's 
find out how Tapestry handles HTML forms and user input.</p><p>Next: <a  
href="using-beaneditform-to-create-user-forms.html">Using BeanEditForm To 
Create User Forms</a></p><p></p><p>&#160;</p><p>&#160;</p></div>
       </div>
 
       <div class="clearer"></div>

Modified: websites/production/tapestry/content/injection-faq.html
==============================================================================
--- websites/production/tapestry/content/injection-faq.html (original)
+++ websites/production/tapestry/content/injection-faq.html Wed Sep 20 12:29:16 
2017
@@ -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,13 +77,22 @@
       </div>
 
       <div id="content">
-                <div 
id="ConfluenceContent"><plain-text-body>{scrollbar}</plain-text-body><h2 
id="InjectionFAQ-Injection">Injection</h2><p>Main article: <a  
href="injection.html">Injection</a></p><h3 
id="InjectionFAQ-What'sthedifferencebetweenthe@Componentand@InjectComponentannotations?">What's
 the difference between the <code>@Component</code> and 
<code>@InjectComponent</code> annotations?</h3><p>The <code>@Component</code> 
annotation is used to define the <em>type</em> of component, and its parameter 
bindings. When using <code>@Component</code>, the template must not define the 
type, and any parameter bindings are merged in:</p><parameter 
ac:name="controls">true</parameter><parameter 
ac:name="linenumbers">true</parameter><plain-text-body>  &lt;a t:id="home" 
class="nav"&gt;Back to home&lt;/a&gt;
-</plain-text-body><parameter ac:name="controls">true</parameter><parameter 
ac:name="linenumbers">true</parameter><plain-text-body>  
@Component(parameters={ "page=index" })
+                <div id="ConfluenceContent"><h2 
id="InjectionFAQ-Injection">Injection</h2><p>Main article: <a  
href="injection.html">Injection</a></p><h3 
id="InjectionFAQ-What'sthedifferencebetweenthe@Componentand@InjectComponentannotations?">What's
 the difference between the <code>@Component</code> and 
<code>@InjectComponent</code> annotations?</h3><p>The <code>@Component</code> 
annotation is used to define the <em>type</em> of component, and its parameter 
bindings. When using <code>@Component</code>, the template must not define the 
type, and any parameter bindings are merged in:</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;">  &lt;a t:id="home" class="nav"&gt;Back to 
home&lt;/a&gt;
+</pre>
+</div></div><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;">  @Component(parameters={ "page=index" })
   private PageLink home;
-</plain-text-body><p>Here the type of component is defined by the field type. 
The field name is matched against the <code>t:id</code> in the template. The 
<code>page</code> parameter is set in the Java class, and the informal 
<code>class</code> parameter is set in the template. If the tag in the template 
was <code>&lt;t:pagelink&gt;</code>, or if the template tag included the 
attribute <code>t:type="pagelink"</code>, then you would see an 
exception.</p><p>By contrast, <code>@InjectComponent</code> expects the 
component to be already defined, and doesn't allow any configuration of 
it:</p><parameter ac:name="controls">true</parameter><parameter 
ac:name="linenumbers">true</parameter><plain-text-body>  &lt;t:form 
t:id="login"&gt; .... &lt;/t:form&gt;
-</plain-text-body><parameter ac:name="controls">true</parameter><parameter 
ac:name="linenumbers">true</parameter><plain-text-body>  @InjectComponent
+</pre>
+</div></div><p>Here the type of component is defined by the field type. The 
field name is matched against the <code>t:id</code> in the template. The 
<code>page</code> parameter is set in the Java class, and the informal 
<code>class</code> parameter is set in the template. If the tag in the template 
was <code>&lt;t:pagelink&gt;</code>, or if the template tag included the 
attribute <code>t:type="pagelink"</code>, then you would see an 
exception.</p><p>By contrast, <code>@InjectComponent</code> expects the 
component to be already defined, and doesn't allow any configuration of 
it:</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;">  &lt;t:form t:id="login"&gt; .... &lt;/t:form&gt;
+</pre>
+</div></div><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;">  @InjectComponent
   private Form login;
-</plain-text-body><p>Again, we're matching the field name to the component id, 
and you would get an error if the component is not defined in the 
template.</p><h3 
id="InjectionFAQ-What'sthedifferencebetweenthe@InjectPageand@InjectContainerannotations?">What's
 the difference between the <code>@InjectPage</code> and 
<code>@InjectContainer</code> annotations?</h3><p>The <code>@InjectPage</code> 
annotation is used to inject some page in the application into a field of some 
other page. You often see it used from event handler methods:</p><parameter 
ac:name="controls">true</parameter><parameter 
ac:name="linenumbers">true</parameter><plain-text-body>  @InjectPage
+</pre>
+</div></div><p>Again, we're matching the field name to the component id, and 
you would get an error if the component is not defined in the template.</p><h3 
id="InjectionFAQ-What'sthedifferencebetweenthe@InjectPageand@InjectContainerannotations?">What's
 the difference between the <code>@InjectPage</code> and 
<code>@InjectContainer</code> annotations?</h3><p>The <code>@InjectPage</code> 
annotation is used to inject some page in the application into a field of some 
other page. You often see it used from event handler methods:</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;">  @InjectPage
   private ConfirmRegistration confirmRegistration;
 
   Object onSuccessFromRegistrationForm()
@@ -83,21 +102,31 @@
 
     return confirmRegistration;
   }
-</plain-text-body><p>This code pattern is used to configure peristent 
properties of a page before returning it; Tapestry will send a client redirect 
to the page to present the data.</p><p><code>@InjectContainer</code> can be 
used inside a component or a mixin. In a component, it injects the immediate 
container of the component; this is often the top-level page object.</p><p>In a 
mixin, it injects the component to which the mixin is attached.</p><h3 
id="InjectionFAQ-IgetanexceptionbecauseIhavetwoserviceswiththesameinterface,howdoIhandlethis?">I
 get an exception because I have two services with the same interface, how do I 
handle this?</h3><p>It's not uncommon to have two or more services that 
implement the exact same interface. When you inject, you might start by just 
identifying the type of service to inject:</p><parameter 
ac:name="controls">true</parameter><parameter 
ac:name="linenumbers">true</parameter><plain-text-body>       @Inject
+</pre>
+</div></div><p>This code pattern is used to configure peristent properties of 
a page before returning it; Tapestry will send a client redirect to the page to 
present the data.</p><p><code>@InjectContainer</code> can be used inside a 
component or a mixin. In a component, it injects the immediate container of the 
component; this is often the top-level page object.</p><p>In a mixin, it 
injects the component to which the mixin is attached.</p><h3 
id="InjectionFAQ-IgetanexceptionbecauseIhavetwoserviceswiththesameinterface,howdoIhandlethis?">I
 get an exception because I have two services with the same interface, how do I 
handle this?</h3><p>It's not uncommon to have two or more services that 
implement the exact same interface. When you inject, you might start by just 
identifying the type of service to inject:</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;">        @Inject
        private ComponentEventResultProcessor processor;
-</plain-text-body><p>Which results in the error: <strong>Service interface 
org.apache.tapestry5.services.ComponentEventResultProcessor is matched by 3 
services: AjaxComponentEventResultProcessor, ComponentEventResultProcessor, 
ComponentInstanceResultProcessor. Automatic dependency resolution requires that 
exactly one service implement the interface.</strong></p><p>We need more 
information than just the service interface type in order to identify which of 
the three services to inject. One possibility is to inject with the correct 
service id:</p><parameter ac:name="controls">true</parameter><parameter 
ac:name="linenumbers">true</parameter><plain-text-body> 
@InjectService("ComponentEventResultProcessor")
+</pre>
+</div></div><p>Which results in the error: <strong>Service interface 
org.apache.tapestry5.services.ComponentEventResultProcessor is matched by 3 
services: AjaxComponentEventResultProcessor, ComponentEventResultProcessor, 
ComponentInstanceResultProcessor. Automatic dependency resolution requires that 
exactly one service implement the interface.</strong></p><p>We need more 
information than just the service interface type in order to identify which of 
the three services to inject. One possibility is to inject with the correct 
service id:</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;">        @InjectService("ComponentEventResultProcessor")
        private ComponentEventResultProcessor processor;
-</plain-text-body><p>This works ... but it is clumsy. If the service id, 
"ComponentEventResultProcessor", ever changes, this code will break. It's not 
<em>refactoring safe</em>.</p><p>Instead, we should use marker annotations. If 
we look at <code>TapestryModule</code>, where the ComponentEventResultProcessor 
service is defined, we'll see it identifies the necessary 
markers:</p><parameter ac:name="controls">true</parameter><parameter 
ac:name="linenumbers">true</parameter><plain-text-body>    @Marker(
+</pre>
+</div></div><p>This works ... but it is clumsy. If the service id, 
"ComponentEventResultProcessor", ever changes, this code will break. It's not 
<em>refactoring safe</em>.</p><p>Instead, we should use marker annotations. If 
we look at <code>TapestryModule</code>, where the ComponentEventResultProcessor 
service is defined, we'll see it identifies the necessary markers:</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;">    @Marker(
     { Primary.class, Traditional.class })
     public ComponentEventResultProcessor buildComponentEventResultProcessor(
             Map&lt;Class, ComponentEventResultProcessor&gt; configuration)
     {
         return constructComponentEventResultProcessor(configuration);
     }
-</plain-text-body><p>When a service has marker annotations, the annotations 
present at the <em>point of injection</em> (the field, method parameter, or 
constructor parameter) are used to select a matching service. The list of 
services that match by type is then filtered to only include services that have 
all of the marker annotations present at the point of injection.</p><parameter 
ac:name="controls">true</parameter><parameter 
ac:name="linenumbers">true</parameter><plain-text-body>    @Inject
+</pre>
+</div></div><p>When a service has marker annotations, the annotations present 
at the <em>point of injection</em> (the field, method parameter, or constructor 
parameter) are used to select a matching service. The list of services that 
match by type is then filtered to only include services that have all of the 
marker annotations present at the point of injection.</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;">    @Inject
        @Traditional @Primary
        private ComponentEventResultProcessor processor;
-</plain-text-body><p>The two marker annotations, <code>@Traditional</code> and 
<code>@Primary</code>, ensure that only a single service matches.</p><h3 
id="InjectionFAQ-What'sthedifferencebetween@Injectand@Environmental?">What's 
the difference between <code>@Inject</code> and 
<code>@Environmental</code>?</h3><p><code>@Inject</code> is relatively general; 
it can be used to inject resources specific to a page or component (such as 
ComponentResources, Logger, or Messages), or it can inject services or other 
objects obtained from the Tapestry IoC container. Once the page is loaded, the 
values for these injections never change.</p><p><code>@Environmental</code> is 
different; it exposes a request-scoped, dynamically bound 
value:</p><ul><li>"Request scoped": different threads (processing different 
requests) will see different values when reading the 
field.</li><li>"Dynamically bound": the value is explicitly placed into the 
Environment, and can be overridden at any time.</li></ul><p>Enviro
 nmentals are a form of loosely connected communication between an outer 
component (or even a service) and an inner component. Example: the Form 
component places a <code>FormSupport</code> object into the environment. Other 
components, such as TextField, use the <code>FormSupport</code> when rendering 
to perform functions such as allocate unique control names or register 
client-side validations. The TextField doesn't require that the Form component 
be the immediate container component, or even an ancestor: a Form on one page 
may, indirectly, communicate with a TextField on some entirely different page. 
Neither component directly links to the other, the <code>FormSupport</code> is 
the conduit that connects them.</p><p>The term "Environmental" was chosen as 
the value "comes from the environment".</p><h3 
id="InjectionFAQ-Butwait...IseeIusedthe@Injectannotationanditstillworked.Whatgives?">But
 wait ... I see I used the <code>@Inject</code> annotation and it still worked. 
What gives?</h3><
 p>In certain cases, Tapestry exposes a service (which can be injected) that is 
a proxy to the environmental; this is primarily for common environmentals, such 
as <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/javascript/JavaScriptSupport.html";>JavaScriptSupport</a>,
 that may be needed outside of component classes. You can see this in 
TapestryModule:</p><parameter ac:name="">Java</parameter><parameter 
ac:name="title">TapestryModule.java (partial)</parameter><plain-text-body>    
/**
+</pre>
+</div></div><p>The two marker annotations, <code>@Traditional</code> and 
<code>@Primary</code>, ensure that only a single service matches.</p><h3 
id="InjectionFAQ-What'sthedifferencebetween@Injectand@Environmental?">What's 
the difference between <code>@Inject</code> and 
<code>@Environmental</code>?</h3><p><code>@Inject</code> is relatively general; 
it can be used to inject resources specific to a page or component (such as 
ComponentResources, Logger, or Messages), or it can inject services or other 
objects obtained from the Tapestry IoC container. Once the page is loaded, the 
values for these injections never change.</p><p><code>@Environmental</code> is 
different; it exposes a request-scoped, dynamically bound 
value:</p><ul><li>"Request scoped": different threads (processing different 
requests) will see different values when reading the 
field.</li><li>"Dynamically bound": the value is explicitly placed into the 
Environment, and can be overridden at any time.</li></ul><p>Environmenta
 ls are a form of loosely connected communication between an outer component 
(or even a service) and an inner component. Example: the Form component places 
a <code>FormSupport</code> object into the environment. Other components, such 
as TextField, use the <code>FormSupport</code> when rendering to perform 
functions such as allocate unique control names or register client-side 
validations. The TextField doesn't require that the Form component be the 
immediate container component, or even an ancestor: a Form on one page may, 
indirectly, communicate with a TextField on some entirely different page. 
Neither component directly links to the other, the <code>FormSupport</code> is 
the conduit that connects them.</p><p>The term "Environmental" was chosen as 
the value "comes from the environment".</p><h3 
id="InjectionFAQ-Butwait...IseeIusedthe@Injectannotationanditstillworked.Whatgives?">But
 wait ... I see I used the <code>@Inject</code> annotation and it still worked. 
What gives?</h3><p>In c
 ertain cases, Tapestry exposes a service (which can be injected) that is a 
proxy to the environmental; this is primarily for common environmentals, such 
as <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/javascript/JavaScriptSupport.html";>JavaScriptSupport</a>,
 that may be needed outside of component classes. You can see this in 
TapestryModule:</p><div class="code panel pdl" style="border-width: 1px;"><div 
class="codeHeader panelHeader pdl" style="border-bottom-width: 
1px;"><b>TapestryModule.java (partial)</b></div><div class="codeContent 
panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">    /**
      * Builds a proxy to the current {@link JavaScriptSupport} inside this 
thread's {@link Environment}.
      * 
      * @since 5.2.0
@@ -106,11 +135,14 @@
     {
         return environmentalBuilder.build(JavaScriptSupport.class);
     }
-</plain-text-body><p>This kind of logic is based on the <a  
class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/EnvironmentalShadowBuilder.html";>EnvironmentalShadowBuilder</a>
 service.</p><h3 
id="InjectionFAQ-Ok,butRequestisasingletonservice,notanenvironmental,andIcaninjectthat.IsTapestryreallythreadsafe?">Ok,
 but Request is a singleton service, not an environmental, and I can inject 
that. Is Tapestry really thread safe?</h3><p>Yes, of course Tapestry is thread 
safe. The Request service is another special case, as seen in 
TapestryModule:</p><parameter ac:name="">Java</parameter><parameter 
ac:name="title">TapestryModule.java (partial)</parameter><plain-text-body>    
public Request buildRequest()
+</pre>
+</div></div><p>This kind of logic is based on the <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/EnvironmentalShadowBuilder.html";>EnvironmentalShadowBuilder</a>
 service.</p><h3 
id="InjectionFAQ-Ok,butRequestisasingletonservice,notanenvironmental,andIcaninjectthat.IsTapestryreallythreadsafe?">Ok,
 but Request is a singleton service, not an environmental, and I can inject 
that. Is Tapestry really thread safe?</h3><p>Yes, of course Tapestry is thread 
safe. The Request service is another special case, as seen in 
TapestryModule:</p><div class="code panel pdl" style="border-width: 1px;"><div 
class="codeHeader panelHeader pdl" style="border-bottom-width: 
1px;"><b>TapestryModule.java (partial)</b></div><div class="codeContent 
panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">    public Request buildRequest()
     {
         return shadowBuilder.build(requestGlobals, "request", Request.class);
     }
-</plain-text-body><p><a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/RequestGlobals.html";>RequestGlobals</a>
 is a per-thread service. The Request service is a global singleton created by 
the <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/services/PropertyShadowBuilder.html";>PropertyShadowBuilder</a>
 service, but is just a proxy. It has no internal state; invoking a method on 
the Request service just turns around and extracts the Request object from the 
per-thread RequestGlobals and invokes the same method there.</p><h3 
id="InjectionFAQ-Iuse@Injectonafieldtoinjectaservice,butthefieldisstillnull,whathappened?">I
 use <code>@Inject</code> on a field to inject a service, but the field is 
still null, what happened?</h3><p>This can happen when you use the wrong 
<code>@Inject</code> annotation; for example, com.google.inject.Inject instead 
of org.apache.tapestry5.ioc.annotations.Inj
 ect. This can occur when you have TestNG on the classpath, for example, and 
your IDE is too helpful. Double check your imports when things seem 
weird.</p><p>Also remember that <code>@Inject</code> on fields works for 
components and for service implementations or other objects that Tapestry 
instantiates, but not on arbitrary objects (that are created via Java's new 
keyword).</p><plain-text-body>{scrollbar}</plain-text-body></div>
+</pre>
+</div></div><p><a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/RequestGlobals.html";>RequestGlobals</a>
 is a per-thread service. The Request service is a global singleton created by 
the <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/services/PropertyShadowBuilder.html";>PropertyShadowBuilder</a>
 service, but is just a proxy. It has no internal state; invoking a method on 
the Request service just turns around and extracts the Request object from the 
per-thread RequestGlobals and invokes the same method there.</p><h3 
id="InjectionFAQ-Iuse@Injectonafieldtoinjectaservice,butthefieldisstillnull,whathappened?">I
 use <code>@Inject</code> on a field to inject a service, but the field is 
still null, what happened?</h3><p>This can happen when you use the wrong 
<code>@Inject</code> annotation; for example, com.google.inject.Inject instead 
of org.apache.tapestry5.ioc.annotations.Inject. T
 his can occur when you have TestNG on the classpath, for example, and your IDE 
is too helpful. Double check your imports when things seem weird.</p><p>Also 
remember that <code>@Inject</code> on fields works for components and for 
service implementations or other objects that Tapestry instantiates, but not on 
arbitrary objects (that are created via Java's new keyword).</p></div>
       </div>
 
       <div class="clearer"></div>


Reply via email to