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 Sat Feb 3 13:21:04 2018 @@ -45,13 +45,26 @@ <div class="wrapper bs"> - <div id="navigation"><div class="nav"><ul class="alternate"><li><a href="index.html">Home</a></li><li><a href="getting-started.html">Getting Started</a></li><li><a href="documentation.html">Documentation</a></li><li><a href="download.html">Download</a></li><li><a href="about.html">About</a></li><li><a class="external-link" href="http://www.apache.org/licenses/LICENSE-2.0">License</a></li><li><a href="community.html">Community</a></li><li><a class="external-link" href="http://www.apache.org/security/">Security</a></li><li><a class="external-link" href="http://www.apache.org/">Apache</a></li><li><a class="external-link" href="http://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li><li><a class="external-link" href="http://www.apache.org/foundation/thanks.html">Thanks</a></li></ul></div></div> + <div id="navigation"><div class="nav"><ul class="alternate"><li><a href="index.html">Home</a></li><li><a href="getting-started.html">Getting Started</a></li><li><a href="documentation.html">Documentation</a></li><li><a href="download.html">Download</a></li><li><a href="about.html">About</a></li><li><a class="external-link" href="http://www.apache.org/licenses/LICENSE-2.0">License</a></li><li><a href="community.html">Community</a></li><li><a class="external-link" href="http://www.apache.org/security/">Security</a></li><li><a class="external-link" href="http://www.apache.org/">Apache</a></li><li><a class="external-link" href="http://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li><li><a class="external-link" href="http://www.apache.org/foundation/thanks.html">Thanks</a></li></ul></div> + +</div> <div id="top"> - <div id="smallbanner"><div class="searchbox" style="float:right;margin: .3em 1em .1em 1em"><span style="color: #999; font-size: 90%">Tapestry docs, issues, wikis & blogs:</span><form enctype="application/x-www-form-urlencoded" method="get" action="http://tapestry.apache.org/search.html"> - <input type="text" name="q"> - <input type="submit" value="Search"> -</form></div><div class="emblem" style="float:left"><p><a href="index.html"><span class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image confluence-external-resource" src="http://tapestry.apache.org/images/tapestry_small.png" data-image-src="http://tapestry.apache.org/images/tapestry_small.png"></span></a></p></div><div class="title" style="float:left; margin: 0 0 0 3em"><h1 id="SmallBanner-PageTitle">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 & 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> @@ -63,7 +76,7 @@ </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><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"> + <div id="ConfluenceContent"><p><span><br clear="none"></span></p><p><span>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 confluence-external-resource" src="https://cwiki-test.apache.org/confluence/download/attachments/23340505/hilo -flow.png?version=2&modificationDate=1286814202000&api=v2" data-image-src="https://cwiki-test.apache.org/confluence/download/attachments/23340505/hilo-flow.png?version=2&modificationDate=1286814202000&api=v2"></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;"><html t:type="layout" title="Hi/Lo Guess" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd"> @@ -83,12 +96,12 @@ public class Index { } </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 <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 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 <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><span class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image confluence-external-resource" src="https://cwiki-test.apache.org/confluence/download/attachments/23340505/hilo-1.png?version=3&modificationDate=1416879474000&api=v2" data-image-src="https://cwiki-test.apache.org/confluence/download/attachments/23340505/hilo-1.png?version=3&modificationDate=1416879474000&api=v2"></span></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 applica tion 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"> <pre class="brush: xml; gutter: false; theme: Default" style="font-size:12px;"> <p> <t:actionlink t:id="start">start guessing</t:actionlink> </p> </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> </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"> +</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 confluence-external-resource image-center" width="500" src="https://cwiki-test.apache.org/confluence/download/attachments/23340505/Application_Exception.png?version=1&modificationDate=1428077959000&api=v2" data-image-src="https://cwiki-test.apache.org/confluence/download/attachments/23340505/Application_Exception.png?version=1&modificationDate=1428077959000&api=v2"></span></p><p> </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="implementing-the-hi-lo-guessing-game.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 co mponent'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="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 @@ -154,7 +167,7 @@ public class Index } } </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"> +</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 confluence-external-resource" src="https://cwiki-test.apache.org/confluence/download/attachments/23340505/guess-template-missing.png?version=2&modificationDate=1416710821000&api=v2" data-image-src="https://cwiki-test.apache.org/confluence/download/attachments/23340505/guess-tem plate-missing.png?version=2&modificationDate=1416710821000&api=v2"></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 panelHeader 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;"><html t:type="layout" title="Guess The Number" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd"> @@ -164,16 +177,16 @@ public class Index </html> </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"> +</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 confluence-external-resource" src="https://cwiki-test.apache.org/confluence/download/attachments/23340505/guess-no-target-prop.png?version=2&modificationDate=1416711075000&api=v2" data-image-src="https://cwiki-test.apache.org/confluence/download/attachments/23340505/guess-no-target-prop.png?version=2&modificationDate=1416711075000&api=v2"></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="cod e 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; </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"> +</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 confluence-external-resource" src="https://cwiki-test.apache.org/confluence/download/attachments/23340505/guess-target-zero.png?version=3&modificationDate=1416879255000&api=v2" data-image-src="https://cwiki-test.apache.org/confluence/download/attachments/23340505/guess-target-zero.png?version=3&modificationDate=1416879255000&api=v2"></span></p><p>What gives? We know it was set to at least 1 ... where did the value go?</p><p>As no ted 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 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><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; </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"> +</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 confluence-external-resource" src="https://cwiki-test.apache.org/confluence/download/attachments/23340505/guess-target.png?version=3&modificationDate=1416879254000&api=v2" data-image-src="https://cwiki-test.apache.org/confluence/download/attachments/23340505/guess-target.png?version=3&modificationDate=1416879254000&api=v2"></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;"><html t:type="layout" title="Guess The Number" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd" xmlns:p="tapestry:parameter"> @@ -225,7 +238,7 @@ public class Guess } </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"> +</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 confluence-external-resource" src="https://cwiki-test.apache.org/confluence/download/attachments/23340505/guess-1.png?version=4&modificationDate=1416879255000&api=v2" data-image-src="https://cwiki-test.apache.org/confluence/ download/attachments/23340505/guess-1.png?version=4&modificationDate=1416879255000&api=v2"></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; @@ -293,7 +306,7 @@ public class GameOver </html> </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> </p><p> </p></div> +</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 confluence-external-resource" src="https://cwiki-test.apache.org/confluence/download/attachments/23340505/gameover.png?version=4&modificationDate=1416879255000&api=v2" data-image-src="https://cwiki-test.apache.org/confluence/download/attachments/23340505/gameover.png?version=4&modificationDate=1416879255000&api=v2"></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="implementing-the-hi-lo-guessing-game.html">Implementing the Hi-Lo Guessing Game</a></p><p></p><p> </p><p> </p></div> </div> <div class="clearer"></div>
Modified: websites/production/tapestry/content/introduction.html ============================================================================== --- websites/production/tapestry/content/introduction.html (original) +++ websites/production/tapestry/content/introduction.html Sat Feb 3 13:21:04 2018 @@ -36,13 +36,26 @@ <div class="wrapper bs"> - <div id="navigation"><div class="nav"><ul class="alternate"><li><a href="index.html">Home</a></li><li><a href="getting-started.html">Getting Started</a></li><li><a href="documentation.html">Documentation</a></li><li><a href="download.html">Download</a></li><li><a href="about.html">About</a></li><li><a class="external-link" href="http://www.apache.org/licenses/LICENSE-2.0">License</a></li><li><a href="community.html">Community</a></li><li><a class="external-link" href="http://www.apache.org/security/">Security</a></li><li><a class="external-link" href="http://www.apache.org/">Apache</a></li><li><a class="external-link" href="http://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li><li><a class="external-link" href="http://www.apache.org/foundation/thanks.html">Thanks</a></li></ul></div></div> + <div id="navigation"><div class="nav"><ul class="alternate"><li><a href="index.html">Home</a></li><li><a href="getting-started.html">Getting Started</a></li><li><a href="documentation.html">Documentation</a></li><li><a href="download.html">Download</a></li><li><a href="about.html">About</a></li><li><a class="external-link" href="http://www.apache.org/licenses/LICENSE-2.0">License</a></li><li><a href="community.html">Community</a></li><li><a class="external-link" href="http://www.apache.org/security/">Security</a></li><li><a class="external-link" href="http://www.apache.org/">Apache</a></li><li><a class="external-link" href="http://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li><li><a class="external-link" href="http://www.apache.org/foundation/thanks.html">Thanks</a></li></ul></div> + +</div> <div id="top"> - <div id="smallbanner"><div class="searchbox" style="float:right;margin: .3em 1em .1em 1em"><span style="color: #999; font-size: 90%">Tapestry docs, issues, wikis & blogs:</span><form enctype="application/x-www-form-urlencoded" method="get" action="http://tapestry.apache.org/search.html"> - <input type="text" name="q"> - <input type="submit" value="Search"> -</form></div><div class="emblem" style="float:left"><p><a href="index.html"><span class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image confluence-external-resource" src="http://tapestry.apache.org/images/tapestry_small.png" data-image-src="http://tapestry.apache.org/images/tapestry_small.png"></span></a></p></div><div class="title" style="float:left; margin: 0 0 0 3em"><h1 id="SmallBanner-PageTitle">Introduction</h1></div></div> + <div id="smallbanner"><div class="searchbox" style="float:right;margin: .3em 1em .1em 1em"><span style="color: #999; font-size: 90%">Tapestry docs, issues, wikis & blogs:</span> +<form enctype="application/x-www-form-urlencoded" method="get" action="http://tapestry.apache.org/search.html"> + <input type="text" name="q"> + <input type="submit" value="Search"> +</form> + +</div> + + +<div class="emblem" style="float:left"><p><a href="index.html"><span class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image confluence-external-resource" src="http://tapestry.apache.org/images/tapestry_small.png" data-image-src="http://tapestry.apache.org/images/tapestry_small.png"></span></a></p></div> + + +<div class="title" style="float:left; margin: 0 0 0 3em"><h1 id="SmallBanner-PageTitle">Introduction</h1></div> + +</div> <div class="clearer"></div> </div> @@ -54,37 +67,67 @@ </div> <div id="content"> - <div id="ConfluenceContent"><div class="aui-label" style="float:right" title="Related Articles"><h3>Related Articles</h3><ul class="content-by-label"><li> - <div> - <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span> - </div> - <div class="details"> - <a href="tapestry-for-jsf-users.html">Tapestry for JSF Users</a> - </div> </li><li> - <div> - <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span> - </div> - <div class="details"> - <a href="tapestry-tutorial.html">Tapestry Tutorial</a> - </div> </li><li> - <div> - <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span> - </div> - <div class="details"> - <a href="principles.html">Principles</a> - </div> </li><li> - <div> - <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span> - </div> - <div class="details"> - <a href="getting-started.html">Getting Started</a> - </div> </li><li> - <div> - <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span> - </div> - <div class="details"> - <a href="introduction.html">Introduction</a> - </div> </li></ul></div><h2 id="Introduction-WhatisApacheTapestry?">What is Apache Tapestry?</h2><p>Apache Tapestry is an open-source framework for creating dynamic, robust, highly scalable web applications in Java. Tapestry complements and builds upon the standard Java Servlet API, and so it works in any servlet container or application server.</p><p>Tapestry divides a web application into a set of pages, each constructed from components. This provides a consistent structure, allowing the Tapestry framework to assume responsibility for key concerns such as URL construction and dispatch, persistent state storage on the client or on the server, user input validation, localization/internationalization, and exception reporting. Developing Tapestry applications involves creating HTML templates using plain HTML, and adding a small java class for each. In Tapestry, you create your application in terms of objects, and the methods and properties of those objects – and specifically no t in terms of URLs and query parameters. Tapestry brings true object oriented development to Java web applications.</p><p>Tapestry is specifically designed to make creating new components very easy, as this is a routine approach when building applications.</p><p>Tapestry is architected to scale from tiny, single-page applications all the way up to massive applications consisting of hundreds of individual pages, developed by large, diverse teams. Tapestry easily integrates with any kind of backend, including JEE, Spring and Hibernate.</p><p>It's more than what you can do with Tapestry ... it's also how you do it! Tapestry is a vastly productive environment. Java developers love it because they can make Java code changes and see them immediately ... no redeploy, no restart! And it's blazingly fast to boot (even when files have changed). Designers love it because Tapestry templates are so close to ordinary HTML, without all the cruft and confusion seen in <a href="tapestry-for-jsf-use rs.html">JavaServer Pages</a>. Managers love it because it makes it easy for large teams to work together productively, and because they know important features (including localization) are baked right in. Once you work in Tapestry there's no going back!</p><p>Tapestry is released under the Apache Software License 2.0.</p><h2 id="Introduction-ThirdPartyLibraries,TutorialsandResources">Third Party Libraries, Tutorials and Resources</h2><p>A number of third party libraries, tutorials and resources are listed on the <a href="modules.html">Modules</a> page.</p><h2 id="Introduction-AboutReleasesandSnapshots">About Releases and Snapshots</h2><p>Most users will want to use the latest stable release of Tapestry, and for that your best bet for new projects is to use the Quickstart Maven archetype to create your initial Tapestry project, as described on the <a href="getting-started.html">Getting Started</a> page. The Quickstart archetype generates a full, working project directory. For upgr ading existing projects, just use the Maven dependency listed on the <a href="download.html">Download</a> page.</p><p>You can also pull down Tapestry modules in the form of binary and source JARs from the <a class="external-link" href="http://search.maven.org/#browse" title="1738327132" rel="nofollow">Maven Central repository</a>.</p><p>Tapestry itself is built using Gradle, which makes it really easy to download the source and build it yourself, either the whole project, or just one single module.</p><p>The use of Maven and Gradle has let us move with great speed, providing preview releases and snapshots.</p><p>Snapshots are intermediate versions of releases, with "-SNAPSHOT" at the end of the version number. Maven notices that -SNAPSHOT suffix and handles the dependency specially. It knows that snapshot releases can change frequently, so it will keep checking (at least once a day, maybe more often) to see if there's an updated version of the snapshot.</p><p>A nightly build proce ss on Tapestry's continuous integration server creates new snapshots every night.</p><p>Snapshots don't go in the Maven central repository (that's reserved for full releases). Instead, they go into the Tapestry snapshots repository at <a class="external-link" href="https://repository.apache.org/content/groups/snapshots/org/apache/tapestry/">https://repository.apache.org/content/groups/snapshots/org/apache/tapestry/</a>.</p><p>To access the snapshot repository, just add <code>-DremoteRepositories=<span class="nolink">http://repository.apache.org/snapshots/</span></code> to the command line when running Maven.</p><p>Documentation on this site sometimes refers to the latest snapshot ... that is, it is often ahead of the last official release, with version-specific differences clearly marked. In some cases, it is written as if the snapshot release is stable. For example, if documentation refers to version 5.4.x and that hasn't been released yet, you can try 5.4.x-SNAPSHOT.</p></div> + <div id="ConfluenceContent"><div class="aui-label" style="float:right" title="Related Articles"> + + + + + + + + +<h3>Related Articles</h3> + +<ul class="content-by-label"><li> + <div> + <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span> </div> + + <div class="details"> + <a href="tapestry-for-jsf-users.html">Tapestry for JSF Users</a> + + + </div> + </li><li> + <div> + <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span> </div> + + <div class="details"> + <a href="tapestry-tutorial.html">Tapestry Tutorial</a> + + + </div> + </li><li> + <div> + <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span> </div> + + <div class="details"> + <a href="principles.html">Principles</a> + + + </div> + </li><li> + <div> + <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span> </div> + + <div class="details"> + <a href="getting-started.html">Getting Started</a> + + + </div> + </li><li> + <div> + <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span> </div> + + <div class="details"> + <a href="introduction.html">Introduction</a> + + + </div> + </li></ul> +</div> + + +<h2 id="Introduction-WhatisApacheTapestry?">What is Apache Tapestry?</h2><p>Apache Tapestry is an open-source framework for creating dynamic, robust, highly scalable web applications in Java. Tapestry complements and builds upon the standard Java Servlet API, and so it works in any servlet container or application server.</p><p>Tapestry divides a web application into a set of pages, each constructed from components. This provides a consistent structure, allowing the Tapestry framework to assume responsibility for key concerns such as URL construction and dispatch, persistent state storage on the client or on the server, user input validation, localization/internationalization, and exception reporting. Developing Tapestry applications involves creating HTML templates using plain HTML, and adding a small java class for each. In Tapestry, you create your application in terms of objects, and the methods and properties of those objects – and specifically not in terms of URLs and qu ery parameters. Tapestry brings true object oriented development to Java web applications.</p><p>Tapestry is specifically designed to make creating new components very easy, as this is a routine approach when building applications.</p><p>Tapestry is architected to scale from tiny, single-page applications all the way up to massive applications consisting of hundreds of individual pages, developed by large, diverse teams. Tapestry easily integrates with any kind of backend, including JEE, Spring and Hibernate.</p><p>It's more than what you can do with Tapestry ... it's also how you do it! Tapestry is a vastly productive environment. Java developers love it because they can make Java code changes and see them immediately ... no redeploy, no restart! And it's blazingly fast to boot (even when files have changed). Designers love it because Tapestry templates are so close to ordinary HTML, without all the cruft and confusion seen in <a href="introduction.html">JavaServer Pages</a>. Mana gers love it because it makes it easy for large teams to work together productively, and because they know important features (including localization) are baked right in. Once you work in Tapestry there's no going back!</p><p>Tapestry is released under the Apache Software License 2.0.</p><h2 id="Introduction-ThirdPartyLibraries,TutorialsandResources">Third Party Libraries, Tutorials and Resources</h2><p>A number of third party libraries, tutorials and resources are listed on the <a href="introduction.html">Introduction</a> page.</p><h2 id="Introduction-AboutReleasesandSnapshots">About Releases and Snapshots</h2><p>Most users will want to use the latest stable release of Tapestry, and for that your best bet for new projects is to use the Quickstart Maven archetype to create your initial Tapestry project, as described on the <a href="introduction.html">Introduction</a> page. The Quickstart archetype generates a full, working project directory. For upgrading existing projects, just u se the Maven dependency listed on the <a href="introduction.html">Introduction</a> page.</p><p>You can also pull down Tapestry modules in the form of binary and source JARs from the <a class="external-link" href="http://search.maven.org/#browse" rel="nofollow" title="1738327132">Maven Central repository</a>.</p><p>Tapestry itself is built using Gradle, which makes it really easy to download the source and build it yourself, either the whole project, or just one single module.</p><p>The use of Maven and Gradle has let us move with great speed, providing preview releases and snapshots.</p><p>Snapshots are intermediate versions of releases, with "-SNAPSHOT" at the end of the version number. Maven notices that -SNAPSHOT suffix and handles the dependency specially. It knows that snapshot releases can change frequently, so it will keep checking (at least once a day, maybe more often) to see if there's an updated version of the snapshot.</p><p>A nightly build process on Tapestry's contin uous integration server creates new snapshots every night.</p><p>Snapshots don't go in the Maven central repository (that's reserved for full releases). Instead, they go into the Tapestry snapshots repository at <a class="external-link" href="https://repository.apache.org/content/groups/snapshots/org/apache/tapestry/">https://repository.apache.org/content/groups/snapshots/org/apache/tapestry/</a>.</p><p>To access the snapshot repository, just add <code>-DremoteRepositories=<span class="nolink"><a class="external-link" href="http://repository.apache.org/snapshots/">http://repository.apache.org/snapshots/</a></span></code> to the command line when running Maven.</p><p>Documentation on this site sometimes refers to the latest snapshot ... that is, it is often ahead of the last official release, with version-specific differences clearly marked. In some cases, it is written as if the snapshot release is stable. For example, if documentation refers to version 5.4.x and that hasn't been released yet, you can try 5.4.x-SNAPSHOT.</p></div> </div> <div class="clearer"></div> Modified: websites/production/tapestry/content/principles.html ============================================================================== --- websites/production/tapestry/content/principles.html (original) +++ websites/production/tapestry/content/principles.html Sat Feb 3 13:21:04 2018 @@ -44,13 +44,26 @@ <div class="wrapper bs"> - <div id="navigation"><div class="nav"><ul class="alternate"><li><a href="index.html">Home</a></li><li><a href="getting-started.html">Getting Started</a></li><li><a href="documentation.html">Documentation</a></li><li><a href="download.html">Download</a></li><li><a href="about.html">About</a></li><li><a class="external-link" href="http://www.apache.org/licenses/LICENSE-2.0">License</a></li><li><a href="community.html">Community</a></li><li><a class="external-link" href="http://www.apache.org/security/">Security</a></li><li><a class="external-link" href="http://www.apache.org/">Apache</a></li><li><a class="external-link" href="http://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li><li><a class="external-link" href="http://www.apache.org/foundation/thanks.html">Thanks</a></li></ul></div></div> + <div id="navigation"><div class="nav"><ul class="alternate"><li><a href="index.html">Home</a></li><li><a href="getting-started.html">Getting Started</a></li><li><a href="documentation.html">Documentation</a></li><li><a href="download.html">Download</a></li><li><a href="about.html">About</a></li><li><a class="external-link" href="http://www.apache.org/licenses/LICENSE-2.0">License</a></li><li><a href="community.html">Community</a></li><li><a class="external-link" href="http://www.apache.org/security/">Security</a></li><li><a class="external-link" href="http://www.apache.org/">Apache</a></li><li><a class="external-link" href="http://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li><li><a class="external-link" href="http://www.apache.org/foundation/thanks.html">Thanks</a></li></ul></div> + +</div> <div id="top"> - <div id="smallbanner"><div class="searchbox" style="float:right;margin: .3em 1em .1em 1em"><span style="color: #999; font-size: 90%">Tapestry docs, issues, wikis & blogs:</span><form enctype="application/x-www-form-urlencoded" method="get" action="http://tapestry.apache.org/search.html"> - <input type="text" name="q"> - <input type="submit" value="Search"> -</form></div><div class="emblem" style="float:left"><p><a href="index.html"><span class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image confluence-external-resource" src="http://tapestry.apache.org/images/tapestry_small.png" data-image-src="http://tapestry.apache.org/images/tapestry_small.png"></span></a></p></div><div class="title" style="float:left; margin: 0 0 0 3em"><h1 id="SmallBanner-PageTitle">Principles</h1></div></div> + <div id="smallbanner"><div class="searchbox" style="float:right;margin: .3em 1em .1em 1em"><span style="color: #999; font-size: 90%">Tapestry docs, issues, wikis & blogs:</span> +<form enctype="application/x-www-form-urlencoded" method="get" action="http://tapestry.apache.org/search.html"> + <input type="text" name="q"> + <input type="submit" value="Search"> +</form> + +</div> + + +<div class="emblem" style="float:left"><p><a href="index.html"><span class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image confluence-external-resource" src="http://tapestry.apache.org/images/tapestry_small.png" data-image-src="http://tapestry.apache.org/images/tapestry_small.png"></span></a></p></div> + + +<div class="title" style="float:left; margin: 0 0 0 3em"><h1 id="SmallBanner-PageTitle">Principles</h1></div> + +</div> <div class="clearer"></div> </div> @@ -62,37 +75,67 @@ </div> <div id="content"> - <div id="ConfluenceContent"><div class="aui-label" style="float:right" title="Related Articles"><h3>Related Articles</h3><ul class="content-by-label"><li> - <div> - <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span> - </div> - <div class="details"> - <a href="tapestry-for-jsf-users.html">Tapestry for JSF Users</a> - </div> </li><li> - <div> - <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span> - </div> - <div class="details"> - <a href="tapestry-tutorial.html">Tapestry Tutorial</a> - </div> </li><li> - <div> - <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span> - </div> - <div class="details"> - <a href="principles.html">Principles</a> - </div> </li><li> - <div> - <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span> - </div> - <div class="details"> - <a href="getting-started.html">Getting Started</a> - </div> </li><li> - <div> - <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span> - </div> - <div class="details"> - <a href="introduction.html">Introduction</a> - </div> </li></ul></div><h1 id="Principles-Principle1–StaticStructure,DynamicBehavior">Principle 1 – Static Structure, Dynamic Behavior</h1><p>The concept of "Dynamic Behavior" should be pretty obvious when you are building a web application; things should look different for different users/situations. But what does it mean that Tapestry has "Static Structure?" Static structure implies that when you build a page in Tapestry you are going to define all of the types of components that are used within that page. Under no circumstance during the rendering or event processing of the page will you be able to dynamically create a new type of component and place that into the component tree.</p><p>At first glance, this seems quite limiting ... other frameworks allow new elements to be created on the fly; it's also a common feature of desktop GUIs such as Swing. But static structure turns out to be not so limiting after all. You <em>can</em> create new elements (you're actually re-rendering existing components with different properties). And you have plenty of options for getting dynamic behavior out of your static structure; from the simple conditional and looping components to the more advanced implementations of Tapestry's BeanEditor or Grid components, Tapestry gives you control over what renders and when, and even where it appears on the page. And starting in Tapestry 5.3 you can even use the <a class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Dynamic.html">Dynamic component</a>, which renders whatever is in an external template file.</p><p>Why did Tapestry choose static structure as a core principle? It's really a matter of meeting the requirements of agility and scalability.</p><h2 id="Principles-Agility">Agility</h2><p>Tapestry is designed to be an agile working environment; "code less, deliver more". To support you writing less code Tapestry does a lot of work on your POJO pages and co mponents when first loading them. It also uses shared instances of page and component classes (shared across multiple threads and requests). Having dynamically modifiable structure would imply that each request has its own instance and, further, that the entire structure would need to be serialized between requests so that it can be restored to handle later requests.</p><p>Tapestry also makes you more agile by speeding up the development cycle with <a href="class-reloading.html">Live Class Reloading</a>. Tapestry monitors the file system for changes to Java page classes, component classes, service implementation classes, HTML templates and component property files, and it hot-swaps the changes into the running application without requiring a restart <em>or losing session data</em>. This provides a very short code-save-view cycle that no other framework can touch.</p><h2 id="Principles-Scalability">Scalability</h2><p>When building large scale systems it is important to consider how your resources are going to be used on each deployed server, and how that information is going to be shared between servers. Static structure means that page instances do not need to be stored inside the HttpSession and simple browsing users do not require extra system resources. This lean use of the HttpSession is key to Tapestry's very high scalability, especially in a clustered configuration. Again, linking an instance of a page to a particular client would require vastly more server-side resources than having a single shared page instance.</p><h1 id="Principles-Principle2–AdaptiveAPI">Principle 2 – Adaptive API</h1><p>A key feature of Tapestry 5 is its adaptive API.</p><p>In traditional Java frameworks (including Struts, <a href="tapestry-for-jsf-users.html">JSF</a> and even the now-ancient Tapestry 4) user code is expected to conform to the framework. You create classes that extend from framework-provided base classes, or implement framework-provided interfaces.</p ><p>This works well until you upgrade to the next release of the framework: >with the new features of the upgrade, you will more often than not experience >breaks in backwards compatibility. Interfaces or base classes will have >changed and your existing code will need to be changed to match.</p><p>In >Tapestry 5, the framework adapts to your code. You have control over the >names of the methods, the parameters they take, and the value that is >returned. This is driven by annotations, which tell Tapestry under what >circumstances your methods are to be invoked.</p><p>For example, you may have >a login form and have a method that gets invoked when the form is >submitted:</p><div class="code panel pdl" style="border-width: 1px;"><div >class="codeContent panelContent pdl"> + <div id="ConfluenceContent"><div class="aui-label" style="float:right" title="Related Articles"> + + + + + + + + +<h3>Related Articles</h3> + +<ul class="content-by-label"><li> + <div> + <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span> </div> + + <div class="details"> + <a href="tapestry-for-jsf-users.html">Tapestry for JSF Users</a> + + + </div> + </li><li> + <div> + <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span> </div> + + <div class="details"> + <a href="tapestry-tutorial.html">Tapestry Tutorial</a> + + + </div> + </li><li> + <div> + <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span> </div> + + <div class="details"> + <a href="principles.html">Principles</a> + + + </div> + </li><li> + <div> + <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span> </div> + + <div class="details"> + <a href="getting-started.html">Getting Started</a> + + + </div> + </li><li> + <div> + <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" title="Page">Page:</span> </div> + + <div class="details"> + <a href="introduction.html">Introduction</a> + + + </div> + </li></ul> +</div> + + +<h1 id="Principles-Principle1–StaticStructure,DynamicBehavior">Principle 1 – Static Structure, Dynamic Behavior</h1><p>The concept of "Dynamic Behavior" should be pretty obvious when you are building a web application; things should look different for different users/situations. But what does it mean that Tapestry has "Static Structure?" Static structure implies that when you build a page in Tapestry you are going to define all of the types of components that are used within that page. Under no circumstance during the rendering or event processing of the page will you be able to dynamically create a new type of component and place that into the component tree.</p><p>At first glance, this seems quite limiting ... other frameworks allow new elements to be created on the fly; it's also a common feature of desktop GUIs such as Swing. But static structure turns out to be not so limiting after all. You <em>can</em> create new elements (you're actually re-rendering existing com ponents with different properties). And you have plenty of options for getting dynamic behavior out of your static structure; from the simple conditional and looping components to the more advanced implementations of Tapestry's BeanEditor or Grid components, Tapestry gives you control over what renders and when, and even where it appears on the page. And starting in Tapestry 5.3 you can even use the <a class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Dynamic.html">Dynamic component</a>, which renders whatever is in an external template file.</p><p>Why did Tapestry choose static structure as a core principle? It's really a matter of meeting the requirements of agility and scalability.</p><h2 id="Principles-Agility">Agility</h2><p>Tapestry is designed to be an agile working environment; "code less, deliver more". To support you writing less code Tapestry does a lot of work on your POJO pages and components when first loadi ng them. It also uses shared instances of page and component classes (shared across multiple threads and requests). Having dynamically modifiable structure would imply that each request has its own instance and, further, that the entire structure would need to be serialized between requests so that it can be restored to handle later requests.</p><p>Tapestry also makes you more agile by speeding up the development cycle with <a href="principles.html">Live Class Reloading</a>. Tapestry monitors the file system for changes to Java page classes, component classes, service implementation classes, HTML templates and component property files, and it hot-swaps the changes into the running application without requiring a restart <em>or losing session data</em>. This provides a very short code-save-view cycle that no other framework can touch.</p><h2 id="Principles-Scalability">Scalability</h2><p>When building large scale systems it is important to consider how your resources are going to be used on each deployed server, and how that information is going to be shared between servers. Static structure means that page instances do not need to be stored inside the HttpSession and simple browsing users do not require extra system resources. This lean use of the HttpSession is key to Tapestry's very high scalability, especially in a clustered configuration. Again, linking an instance of a page to a particular client would require vastly more server-side resources than having a single shared page instance.</p><h1 id="Principles-Principle2–AdaptiveAPI">Principle 2 – Adaptive API</h1><p>A key feature of Tapestry 5 is its adaptive API.</p><p>In traditional Java frameworks (including Struts, <a href="principles.html">JSF</a> and even the now-ancient Tapestry 4) user code is expected to conform to the framework. You create classes that extend from framework-provided base classes, or implement framework-provided interfaces.</p><p>This works well until you upgrade to t he next release of the framework: with the new features of the upgrade, you will more often than not experience breaks in backwards compatibility. Interfaces or base classes will have changed and your existing code will need to be changed to match.</p><p>In Tapestry 5, the framework adapts to your code. You have control over the names of the methods, the parameters they take, and the value that is returned. This is driven by annotations, which tell Tapestry under what circumstances your methods are to be invoked.</p><p>For example, you may have a login form and have a method that gets invoked when the form is submitted:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl"> <pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">public class Login { @Persist
