Author: buildbot
Date: Sun Nov 23 03:20:37 2014
New Revision: 930175
Log:
Production update by buildbot for tapestry
Modified:
websites/production/tapestry/content/cache/main.pageCache
websites/production/tapestry/content/implementing-the-hi-lo-guessing-game.data/guess-no-target-prop.png
websites/production/tapestry/content/implementing-the-hi-lo-guessing-game.data/guess-target-zero.png
websites/production/tapestry/content/implementing-the-hi-lo-guessing-game.data/guess-target.png
websites/production/tapestry/content/implementing-the-hi-lo-guessing-game.data/guess-template-missing.png
websites/production/tapestry/content/implementing-the-hi-lo-guessing-game.data/hilo-index-missing-action-error.png
websites/production/tapestry/content/implementing-the-hi-lo-guessing-game.html
Modified: websites/production/tapestry/content/cache/main.pageCache
==============================================================================
Binary files - no diff available.
Modified:
websites/production/tapestry/content/implementing-the-hi-lo-guessing-game.data/guess-no-target-prop.png
==============================================================================
Binary files - no diff available.
Modified:
websites/production/tapestry/content/implementing-the-hi-lo-guessing-game.data/guess-target-zero.png
==============================================================================
Binary files - no diff available.
Modified:
websites/production/tapestry/content/implementing-the-hi-lo-guessing-game.data/guess-target.png
==============================================================================
Binary files - no diff available.
Modified:
websites/production/tapestry/content/implementing-the-hi-lo-guessing-game.data/guess-template-missing.png
==============================================================================
Binary files - no diff available.
Modified:
websites/production/tapestry/content/implementing-the-hi-lo-guessing-game.data/hilo-index-missing-action-error.png
==============================================================================
Binary files - no diff available.
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
Sun Nov 23 03:20:37 2014
@@ -92,12 +92,12 @@ table.ScrollbarTable td.ScrollbarNextIco
{
}
]]></script>
-</div></div><p>Running the application gives us our start:</p><p><img
class="confluence-embedded-image" width="700"
src="https://cwiki.apache.org/confluence/download/attachments/23340505/hilo-1.png?version=2&modificationDate=1416709010700&api=v2"
data-image-src="/confluence/download/attachments/23340505/hilo-1.png?version=2&modificationDate=1416709010700&api=v2"></p><p>However,
clicking the link doesn't do anything yet, as its just a placeholder
\<a\> 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 configuratio
n 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 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 \<a\> 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">
+</div></div><p>Running the application gives us our start:</p><p><img
class="confluence-embedded-image" width="700"
src="https://cwiki.apache.org/confluence/download/attachments/23340505/hilo-1.png?version=2&modificationDate=1416709010700&api=v2"
data-image-src="/confluence/download/attachments/23340505/hilo-1.png?version=2&modificationDate=1416709010700&api=v2"></p><p>However,
clicking the link doesn't do anything yet, as its just a placeholder <a>
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 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 <a> 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">
<script class="theme: Default; brush: xml; gutter: false"
type="syntaxhighlighter"><![CDATA[ <p>
<t:actionlink t:id="start">start
guessing</t:actionlink>
</p>
]]></script>
-</div></div><p>If you refresh the browser, you'll see that the URL for the
"start guessing" link 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, you'll get an error:</p><p><img class="confluence-embedded-image"
width="700"
src="https://cwiki.apache.org/confluence/download/attachments/23340505/hilo-index-missing-action-error.png?version=1&modificationDate=1290112782000&api=v2"
data-image-src="/confluence/download/attachments/23340505/hilo-index-missing-action-error.png?version=1&modificationDate=1290112782000&api=v2"></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><em>event-name</em><code>From</code><em>component-id</em> ...
here we want a method named <code>onActionFromStart()</code>. How do we kn
ow that "action" is the right event name? Because that's what ActionLink does,
that's why its named _Action_Link.</p><p>Once again, Tapestry gives us options;
if you don't like naming conventions, there's an @<a shape="rect"
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
shape="rect" 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 pan
el 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">
+</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><img
class="confluence-embedded-image" width="700"
src="https://cwiki.apache.org/confluence/download/attachments/23340505/hilo-index-missing-action-error.png?version=3&modificationDate=1416709525392&api=v2"
data-image-src="/confluence/download/attachments/23340505/hilo-index-missing-action-error.png?version=3&modificationDate=1416709525392&api=v2"></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 shape="rect"
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
shape="rect" 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 o
n the client side. Let's start with an empty event handler:</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">
<script class="theme: Default; brush: java; gutter: false"
type="syntaxhighlighter"><![CDATA[package com.example.tutorial.pages;
public class Index
@@ -108,7 +108,7 @@ public class Index
}
}
]]></script>
-</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 me 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 shape="rect"
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" s
tyle="border-bottom-width: 1px;"><b>Index.java (partial)</b></div><div
class="codeContent panelContent pdl">
+</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 shape="rect"
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" s
tyle="border-bottom-width: 1px;"><b>Index.java (partial)</b></div><div
class="codeContent panelContent pdl">
<script class="theme: Default; brush: java; gutter: false"
type="syntaxhighlighter"><![CDATA[ import org.apache.tapestry5.annotations.Log;
. . .
@@ -125,7 +125,7 @@ public class Index
[INFO] AppModule.TimingFilter Request time: 3 ms
[INFO] AppModule.TimingFilter Request time: 5 ms
</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 shape="rect" class="external-link"
href="http://en.wikipedia.org/wiki/Post/Redirect/Get" >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 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 setup 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">
+</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 shape="rect" class="external-link"
href="http://en.wikipedia.org/wiki/Post/Redirect/Get" >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 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><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">
<script class="theme: Default; brush: java; gutter: false"
type="syntaxhighlighter"><![CDATA[package com.example.tutorial.pages;
public class Guess
@@ -138,7 +138,7 @@ public class Guess
}
}
]]></script>
-</div></div><p>With that in mind, we can modify Index to invoke this new
<code>setup()</code> method:</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">
+</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">
<script class="theme: Default; brush: java; gutter: false"
type="syntaxhighlighter"><![CDATA[package com.example.tutorial.pages;
import java.util.Random;
@@ -176,7 +176,7 @@ public class Index
<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><img
class="confluence-embedded-image" width="700"
src="https://cwiki.apache.org/confluence/download/attachments/23340505/guess-template-missing.png?version=1&modificationDate=1290115417000&api=v2"
data-image-src="/confluence/download/attachments/23340505/guess-template-missing.png?version=1&modificationDate=1290115417000&api=v2"></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 panelHeader pdl"
style="border-bottom-width:
1px;"><b>src/main/resources/com/example/tutorial/pages/Guess.tml</b></div><div
class="codeContent panelContent pdl">
+<p>So ... let's click the link and see what we get:</p><p><img
class="confluence-embedded-image" width="700"
src="https://cwiki.apache.org/confluence/download/attachments/23340505/guess-template-missing.png?version=2&modificationDate=1416710821339&api=v2"
data-image-src="/confluence/download/attachments/23340505/guess-template-missing.png?version=2&modificationDate=1416710821339&api=v2"></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 panelHeader pdl"
style="border-bottom-width:
1px;"><b>src/main/resources/com/example/tutorial/pages/Guess.tml</b></div><div
class="codeContent panelContent pdl">
<script class="theme: Default; brush: java; gutter: false"
type="syntaxhighlighter"><![CDATA[<html t:type="layout"
title="Guess The Number"
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd">
@@ -186,16 +186,16 @@ public class Index
</html>
]]></script>
-</div></div><p>Hit the browser's back button, then click the "start guessing"
link again. We're getting closer:</p><p><img class="confluence-embedded-image"
width="700"
src="https://cwiki.apache.org/confluence/download/attachments/23340505/guess-no-target-prop.png?version=1&modificationDate=1290115655000&api=v2"
data-image-src="/confluence/download/attachments/23340505/guess-no-target-prop.png?version=1&modificationDate=1290115655000&api=v2"></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">
+</div></div><p>Hit the browser's back button, then click the "start guessing"
link again. We're getting closer:</p><p><img class="confluence-embedded-image"
width="700"
src="https://cwiki.apache.org/confluence/download/attachments/23340505/guess-no-target-prop.png?version=2&modificationDate=1416711075694&api=v2"
data-image-src="/confluence/download/attachments/23340505/guess-no-target-prop.png?version=2&modificationDate=1416711075694&api=v2"></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">
<script class="theme: Default; brush: java; gutter: false"
type="syntaxhighlighter"><![CDATA[ @Property
private int target;
]]></script>
-</div></div><p>The @<a shape="rect" 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><img
class="confluence-embedded-image" width="700"
src="https://cwiki.apache.org/confluence/download/attachments/23340505/guess-target-zero.png?version=1&modificationDate=1290115961000&api=v2"
data-image-src="/confluence/download/attachments/23340505/guess-target-zero.png?version=1&modificationDate=1290115961000&api=v2"></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 mea
ns 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 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 shape="rect"
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">
+</div></div><p>The @<a shape="rect" 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><img
class="confluence-embedded-image" width="700"
src="https://cwiki.apache.org/confluence/download/attachments/23340505/guess-target-zero.png?version=2&modificationDate=1416711323804&api=v2"
data-image-src="/confluence/download/attachments/23340505/guess-target-zero.png?version=2&modificationDate=1416711323804&api=v2"></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 mea
ns 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 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 shape="rect"
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">
<script class="theme: Default; brush: java; gutter: false"
type="syntaxhighlighter"><![CDATA[ @Property
@Persist
private int target;
]]></script>
-</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><img
class="confluence-embedded-image" width="700"
src="https://cwiki.apache.org/confluence/download/attachments/23340505/guess-target.png?version=1&modificationDate=1290116253000&api=v2"
data-image-src="/confluence/download/attachments/23340505/guess-target.png?version=1&modificationDate=1290116253000&api=v2"></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, a
nd 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">
+</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><img
class="confluence-embedded-image" width="700"
src="https://cwiki.apache.org/confluence/download/attachments/23340505/guess-target.png?version=2&modificationDate=1416711521970&api=v2"
data-image-src="/confluence/download/attachments/23340505/guess-target.png?version=2&modificationDate=1416711521970&api=v2"></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, a
nd 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">
<script class="theme: Default; brush: xml; gutter: false"
type="syntaxhighlighter"><![CDATA[<html t:type="layout"
title="Guess The Number"
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd"
xmlns:p="tapestry:parameter">