Modified: 
websites/production/tapestry/content/using-beaneditform-to-create-user-forms.html
==============================================================================
--- 
websites/production/tapestry/content/using-beaneditform-to-create-user-forms.html
 (original)
+++ 
websites/production/tapestry/content/using-beaneditform-to-create-user-forms.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 &amp; blogs:</span><form 
enctype="application/x-www-form-urlencoded" method="get" 
action="http://tapestry.apache.org/search.html";> 
- <input type="text" name="q"> 
- <input type="submit" value="Search"> 
-</form></div><div class="emblem" style="float:left"><p><a  
href="index.html"><span class="confluence-embedded-file-wrapper"><img 
class="confluence-embedded-image confluence-external-resource" 
src="http://tapestry.apache.org/images/tapestry_small.png"; 
data-image-src="http://tapestry.apache.org/images/tapestry_small.png";></span></a></p></div><div
 class="title" style="float:left; margin: 0 0 0 3em"><h1 
id="SmallBanner-PageTitle">Using BeanEditForm To Create User 
Forms</h1></div></div>
+            <div id="smallbanner"><div class="searchbox" 
style="float:right;margin: .3em 1em .1em 1em"><span style="color: #999; 
font-size: 90%">Tapestry docs, issues, wikis &amp; blogs:</span>
+<form enctype="application/x-www-form-urlencoded" method="get" 
action="http://tapestry.apache.org/search.html";>
+  <input type="text" name="q">
+  <input type="submit" value="Search">
+</form>
+
+</div>
+
+
+<div class="emblem" style="float:left"><p><a  href="index.html"><span 
class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image 
confluence-external-resource" 
src="http://tapestry.apache.org/images/tapestry_small.png"; 
data-image-src="http://tapestry.apache.org/images/tapestry_small.png";></span></a></p></div>
+
+
+<div class="title" style="float:left; margin: 0 0 0 3em"><h1 
id="SmallBanner-PageTitle">Using BeanEditForm To Create User Forms</h1></div>
+
+</div>
       <div class="clearer"></div>
       </div>
 
@@ -113,7 +126,7 @@ public class CreateAddress
 
 }
 </pre>
-</div></div><p>So ... why is the class named "CreateAddress" and not simply 
"Create"? Actually, we could have named it "Create", and the application would 
still work, but the longer <em>class</em> name is equally valid. Tapestry 
noticed the redundancy in the class name 
(com.example.tutorial1.pages.<code><em>address</em></code>.Create<em>Address</em>)
 and just stripped out the redundant suffix.</p><p><span style="line-height: 
1.4285715;">Tapestry actually creates a bunch of aliases for you pages; any of 
these aliases are valid and can appear in URLs or in the page parameter of 
PageLink. &#160;You can see the list in the console:</span></p><div class="code 
panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+</div></div><p>So ... why is the class named "CreateAddress" and not simply 
"Create"? Actually, we could have named it "Create", and the application would 
still work, but the longer <em>class</em> name is equally valid. Tapestry 
noticed the redundancy in the class name 
(com.example.tutorial1.pages.<code><em>address</em></code>.Create<em>Address</em>)
 and just stripped out the redundant suffix.</p><p><span>Tapestry actually 
creates a bunch of aliases for you pages; any of these aliases are valid and 
can appear in URLs or in the page parameter of PageLink. &#160;You can see the 
list in the console:</span></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;">[INFO] TapestryModule.ComponentClassResolver Available 
pages (12):
               (blank): com.example.tutorial1.pages.Index
    ComponentLibraries: org.apache.tapestry5.corelib.pages.ComponentLibraries
@@ -129,27 +142,27 @@ PropertyDisplayBlocks: org.apache.tapest
           T5Dashboard: org.apache.tapestry5.corelib.pages.T5Dashboard
        address/Create: com.example.tutorial1.pages.address.CreateAddress
 address/CreateAddress: com.example.tutorial1.pages.address.CreateAddress</pre>
-</div></div><p><span style="line-height: 1.4285715;">Tapestry users the 
shortest alias when constructing URLs.</span></p><p><span style="line-height: 
1.4285715;">Eventually, your application will probably have more entities: 
perhaps you'll have a "user/Create" page and a "payment/Create" page and an 
"account/Create" page. You </span><em style="line-height: 
1.4285715;">could</em><span style="line-height: 1.4285715;"> have a bunch of 
different classes all named Create spread across a number of different 
packages. That's legal Java, but it isn't ideal. You may find yourself 
accidentally editing the Java code for creating an Account when you really want 
to be editing the code for creating a Payment.</span></p><p>Tapestry is 
encouraging you to use a more descriptive name: Create<em>Address</em>, not 
just Create, but it isn't making you pay the cost (in terms of longer, uglier 
URLs). The URL to access the page will still be <a  class="external-link" 
href="http://localhost:8080/tutorial1/a
 ddress/create" 
rel="nofollow">http://localhost:8080/tutorial1/address/create</a>.</p><p>And 
remember, regardless of the name that Tapestry assigns to your page, the 
template file is named like the Java class itself: CreateAddress.tml.</p><div 
class="confluence-information-macro 
confluence-information-macro-information"><span class="aui-icon aui-icon-small 
aui-iconfont-info confluence-information-macro-icon"></span><div 
class="confluence-information-macro-body"><p>Index pages work in folders as 
well. A class named com.example.tutorial1.pages.address.AddressIndex would be 
given the name "address/Index". However, Tapestry has special rules for pages 
named "Index" and the rendered URL would be <a  class="external-link" 
href="http://localhost:8080/tutorial1/address/"; 
rel="nofollow">http://localhost:8080/tutorial1/address/</a>. In other words, 
you can place Index pages in any folder and Tapestry will build a short URL for 
that page ... and you <em>don't</em> have to keep naming the classe
 s Index (it's confusing to have many classes with the same name, even across 
multiple packages); instead, you can name each index page after the package 
that contains it. Tapestry users a smart <em>convention</em> to keep it all 
straight and generate short, to the point URLs.</p></div></div><h1 
id="UsingBeanEditFormToCreateUserForms-UsingtheBeanEditFormComponent">Using the 
BeanEditForm Component</h1><p>Time to start putting together the logic for this 
form. Tapestry has a specific component for client-side Forms: the <a  
class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Form.html";>Form</a>
 component, as well as components for form controls, such as <a  
class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Checkbox.html";>Checkbox</a>
 and <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/TextField.html";>T
 extField</a>. We'll cover those in a bit more detail later .. instead, we're 
again going to let Tapestry do the heavy lifting for us, via the <a  
class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/BeanEditForm.html";>BeanEditForm</a>
 component.</p><p>Add the following to the CreateAddress template (replacing 
the "coming soon ..." message):</p><div class="code panel pdl" 
style="border-width: 1px;"><div class="codeHeader panelHeader pdl" 
style="border-bottom-width: 1px;"><b>CreateAddress.tml (partial)</b></div><div 
class="codeContent panelContent pdl">
+</div></div><p><span>Tapestry users the shortest alias when constructing 
URLs.</span></p><p><span>Eventually, your application will probably have more 
entities: perhaps you'll have a "user/Create" page and a "payment/Create" page 
and an "account/Create" page. You </span><em>could</em><span> have a bunch of 
different classes all named Create spread across a number of different 
packages. That's legal Java, but it isn't ideal. You may find yourself 
accidentally editing the Java code for creating an Account when you really want 
to be editing the code for creating a Payment.</span></p><p>Tapestry is 
encouraging you to use a more descriptive name: Create<em>Address</em>, not 
just Create, but it isn't making you pay the cost (in terms of longer, uglier 
URLs). The URL to access the page will still be <a  class="external-link" 
href="http://localhost:8080/tutorial1/address/create"; 
rel="nofollow">http://localhost:8080/tutorial1/address/create</a>.</p><p>And 
remember, regardless of the name tha
 t Tapestry assigns to your page, the template file is named like the Java 
class itself: CreateAddress.tml.</p><div class="confluence-information-macro 
confluence-information-macro-information"><span class="aui-icon aui-icon-small 
aui-iconfont-info confluence-information-macro-icon"></span><div 
class="confluence-information-macro-body"><p>Index pages work in folders as 
well. A class named com.example.tutorial1.pages.address.AddressIndex would be 
given the name "address/Index". However, Tapestry has special rules for pages 
named "Index" and the rendered URL would be <a  class="external-link" 
href="http://localhost:8080/tutorial1/address/"; 
rel="nofollow">http://localhost:8080/tutorial1/address/</a>. In other words, 
you can place Index pages in any folder and Tapestry will build a short URL for 
that page ... and you <em>don't</em> have to keep naming the classes Index 
(it's confusing to have many classes with the same name, even across multiple 
packages); instead, you can name each inde
 x page after the package that contains it. Tapestry users a smart 
<em>convention</em> to keep it all straight and generate short, to the point 
URLs.</p></div></div><h1 
id="UsingBeanEditFormToCreateUserForms-UsingtheBeanEditFormComponent">Using the 
BeanEditForm Component</h1><p>Time to start putting together the logic for this 
form. Tapestry has a specific component for client-side Forms: the <a  
class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Form.html";>Form</a>
 component, as well as components for form controls, such as <a  
class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Checkbox.html";>Checkbox</a>
 and <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/TextField.html";>TextField</a>.
 We'll cover those in a bit more detail later .. instead, we're again going to 
let Tapestry do the heavy lifting fo
 r us, via the <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/BeanEditForm.html";>BeanEditForm</a>
 component.</p><p>Add the following to the CreateAddress template (replacing 
the "coming soon ..." message):</p><div class="code panel pdl" 
style="border-width: 1px;"><div class="codeHeader panelHeader pdl" 
style="border-bottom-width: 1px;"><b>CreateAddress.tml (partial)</b></div><div 
class="codeContent panelContent pdl">
 <pre class="brush: xml; gutter: false; theme: Default" 
style="font-size:12px;">    &lt;t:beaneditform object="address"/&gt;
 </pre>
 </div></div><p>And match that up with a property in the CreateAddress 
class:</p><div class="code panel pdl" style="border-width: 1px;"><div 
class="codeHeader panelHeader pdl" style="border-bottom-width: 
1px;"><b>CreateAddress.java (partial)</b></div><div class="codeContent 
panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">    @Property
     private Address address;
 </pre>
-</div></div><p>When you refresh the page, you may see a warning like the 
following at the top of the page:</p><p><span 
class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image" 
src="using-beaneditform-to-create-user-forms.data/hmac-warning.png"></span></p><p>If
 you see that, it means you need to invent an HMAC passphrase for your app. 
Just edit your AppModule.java class (in your services package), adding a couple 
of lines to the contributeApplicationDefaults method like the 
following:</p><div class="code panel pdl" style="border-width: 1px;"><div 
class="codeContent panelContent pdl">
+</div></div><p>When you refresh the page, you may see a warning like the 
following at the top of the page:</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/23340431/hmac-warning.png?version=2&amp;modificationDate=1416883285000&amp;api=v2";
 
data-image-src="https://cwiki-test.apache.org/confluence/download/attachments/23340431/hmac-warning.png?version=2&amp;modificationDate=1416883285000&amp;api=v2";></span></p><p>If
 you see that, it means you need to invent an HMAC passphrase for your app. 
Just edit your AppModule.java class (in your services package), adding a couple 
of lines to the contributeApplicationDefaults method like the 
following:</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;">        // Set the HMAC pass phrase to secure object 
data serialized to client
         configuration.add(SymbolConstants.HMAC_PASSPHRASE, "");</pre>
-</div></div><p>but, instead of an empty string, insert a long, <strong>random 
string of characters</strong> (like a very long and complex password, at least 
30 characters) that you keep private.</p><p>After you do that, stop the app and 
restart it, and click on the Create new address link again, and you'll see 
something like this:</p><p><span class="confluence-embedded-file-wrapper"><img 
class="confluence-embedded-image" 
src="using-beaneditform-to-create-user-forms.data/create-address-initial.png"></span></p><p>Tapestry
 has done quite a bit of work here. It has created a form that includes a field 
for each property. Further, it has seen that the honorific property is an 
enumerated type, and presented that as a drop-down list.</p><p>In addition, 
Tapestry has converted the property names ("city", "email", "firstName") to 
user presentable labels ("City", "Email", "First Name"). In fact, these are 
&lt;label&gt; elements, so clicking a label with the mouse will move the input 
cursor into
  the corresponding field.</p><p>This is an awesome start; it's a presentable 
interface, quite nice in fact for a few minute's work. But it's far from 
perfect; let's get started with some customizations.</p><h1 
id="UsingBeanEditFormToCreateUserForms-ChangingFieldOrder">Changing Field 
Order</h1><p>The BeanEditForm must guess at the right order to present the 
fields; for public fields, they end up in alphabetical order. For standard 
JavaBeans properties, the BeanEditForm default is in the order in which the 
getter methods are defined in the class (it uses line number information, if 
available).</p><p>A better order for these fields is the order in which they 
are defined in the Address 
class:</p><ul><li>honorific</li><li>firstName</li><li>lastName</li><li>street1</li><li>street2</li><li>city</li><li>state</li><li>zip</li><li>email</li><li>phone</li></ul><p>We
 can accomplish this by using the <code>reorder</code> parameter of the 
BeanEditForm component, which is a comma separated list of
  property (or public field) names:</p><div class="code panel pdl" 
style="border-width: 1px;"><div class="codeHeader panelHeader pdl" 
style="border-bottom-width: 1px;"><b>CreateAddress.tml (partial)</b></div><div 
class="codeContent panelContent pdl">
+</div></div><p>but, instead of an empty string, insert a long, <strong>random 
string of characters</strong> (like a very long and complex password, at least 
30 characters) that you keep private.</p><p>After you do that, stop the app and 
restart it, and click on the Create new address link again, and you'll see 
something like 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/23340431/create-address-initial.png?version=2&amp;modificationDate=1416884366000&amp;api=v2";
 
data-image-src="https://cwiki-test.apache.org/confluence/download/attachments/23340431/create-address-initial.png?version=2&amp;modificationDate=1416884366000&amp;api=v2";></span></p><p>Tapestry
 has done quite a bit of work here. It has created a form that includes a field 
for each property. Further, it has seen that the honorific property is an 
enumerated type, and presented that 
 as a drop-down list.</p><p>In addition, Tapestry has converted the property 
names ("city", "email", "firstName") to user presentable labels ("City", 
"Email", "First Name"). In fact, these are &lt;label&gt; elements, so clicking 
a label with the mouse will move the input cursor into the corresponding 
field.</p><p>This is an awesome start; it's a presentable interface, quite nice 
in fact for a few minute's work. But it's far from perfect; let's get started 
with some customizations.</p><h1 
id="UsingBeanEditFormToCreateUserForms-ChangingFieldOrder">Changing Field 
Order</h1><p>The BeanEditForm must guess at the right order to present the 
fields; for public fields, they end up in alphabetical order. For standard 
JavaBeans properties, the BeanEditForm default is in the order in which the 
getter methods are defined in the class (it uses line number information, if 
available).</p><p>A better order for these fields is the order in which they 
are defined in the Address class:</p><ul><li>honori
 
fic</li><li>firstName</li><li>lastName</li><li>street1</li><li>street2</li><li>city</li><li>state</li><li>zip</li><li>email</li><li>phone</li></ul><p>We
 can accomplish this by using the <code>reorder</code> parameter of the 
BeanEditForm component, which is a comma separated list of property (or public 
field) names:</p><div class="code panel pdl" style="border-width: 1px;"><div 
class="codeHeader panelHeader pdl" style="border-bottom-width: 
1px;"><b>CreateAddress.tml (partial)</b></div><div class="codeContent 
panelContent pdl">
 <pre class="brush: xml; gutter: false; theme: Default" 
style="font-size:12px;">    &lt;t:beaneditform object="address"
         
reorder="honorific,firstName,lastName,street1,street2,city,state,zip,email,phone"
 /&gt;
 </pre>
-</div></div><p><span class="confluence-embedded-file-wrapper"><img 
class="confluence-embedded-image" 
src="using-beaneditform-to-create-user-forms.data/create-address-reordered.png"></span></p><h3
 id="UsingBeanEditFormToCreateUserForms-Customizinglabels">Customizing 
labels</h3><p>Tapestry makes it pretty easy to customize the labels used on the 
fields. It's just a matter of creating a <em>message catalog</em> for the 
page.</p><p>In Tapestry, every page and component may have its own message 
catalog. This is a standard Java properties file, and it is named the same as 
the page or component class, with a ".properties" extension. A message catalog 
consists of a series of lines, each line is a message key and a message value 
separated with an equals sign.</p><p>All it takes is to create a message entry 
with a particular name: the name of the property suffixed with "-label". As 
elsewhere, Tapestry is forgiving of case.</p><div class="preformatted panel" 
style="border-width: 1px;"><div cla
 ss="preformattedHeader panelHeader" style="border-bottom-width: 
1px;"><b>src/main/resources/com/example/tutorial/pages/address/CreateAddress.properties</b></div><div
 class="preformattedContent panelContent">
+</div></div><p><span class="confluence-embedded-file-wrapper"><img 
class="confluence-embedded-image confluence-external-resource" 
src="https://cwiki-test.apache.org/confluence/download/attachments/23340431/create-address-reordered.png?version=2&amp;modificationDate=1416884592000&amp;api=v2";
 
data-image-src="https://cwiki-test.apache.org/confluence/download/attachments/23340431/create-address-reordered.png?version=2&amp;modificationDate=1416884592000&amp;api=v2";></span></p><h3
 id="UsingBeanEditFormToCreateUserForms-Customizinglabels">Customizing 
labels</h3><p>Tapestry makes it pretty easy to customize the labels used on the 
fields. It's just a matter of creating a <em>message catalog</em> for the 
page.</p><p>In Tapestry, every page and component may have its own message 
catalog. This is a standard Java properties file, and it is named the same as 
the page or component class, with a ".properties" extension. A message catalog 
consists of a series of lines, each line is a message key and
  a message value separated with an equals sign.</p><p>All it takes is to 
create a message entry with a particular name: the name of the property 
suffixed with "-label". As elsewhere, Tapestry is forgiving of case.</p><div 
class="preformatted panel" style="border-width: 1px;"><div 
class="preformattedHeader panelHeader" style="border-bottom-width: 
1px;"><b>src/main/resources/com/example/tutorial/pages/address/CreateAddress.properties</b></div><div
 class="preformattedContent panelContent">
 <pre>street1-label=Street 1
 street2-label=Street 2
 email-label=E-Mail
 zip-label=Zip Code
 phone-label=Phone Number</pre>
-</div></div><p>Since this is a <em>new</em> file (and not a change to an 
existing file), you may have to restart Jetty to force Tapestry to pick up the 
change.</p><p><span class="confluence-embedded-file-wrapper"><img 
class="confluence-embedded-image confluence-content-image-border" 
src="using-beaneditform-to-create-user-forms.data/address-v3.png"></span></p><p>We
 can also customize the options in the drop down list. All we have to do is add 
some more entries to the message catalog matching the enum names to the desired 
labels. Update CreateAddress.properties and add:</p><div class="preformatted 
panel" style="border-width: 1px;"><div class="preformattedContent panelContent">
+</div></div><p>Since this is a <em>new</em> file (and not a change to an 
existing file), you may have to restart Jetty to force Tapestry to pick up the 
change.</p><p><span class="confluence-embedded-file-wrapper"><img 
class="confluence-embedded-image confluence-external-resource 
confluence-content-image-border" 
src="https://cwiki-test.apache.org/confluence/download/attachments/23340431/address-v3.png?version=2&amp;modificationDate=1417055915000&amp;api=v2";
 
data-image-src="https://cwiki-test.apache.org/confluence/download/attachments/23340431/address-v3.png?version=2&amp;modificationDate=1417055915000&amp;api=v2";></span></p><p>We
 can also customize the options in the drop down list. All we have to do is add 
some more entries to the message catalog matching the enum names to the desired 
labels. Update CreateAddress.properties and add:</p><div class="preformatted 
panel" style="border-width: 1px;"><div class="preformattedContent panelContent">
 <pre>MR=Mr.
 MRS=Mrs.
 DR=Dr.
@@ -158,7 +171,7 @@ DR=Dr.
 <pre class="brush: xml; gutter: false; theme: Default" 
style="font-size:12px;">    &lt;t:beaneditform submitlabel="Create Address" 
object="address"
         
reorder="honorific,firstName,lastName,street1,street2,city,state,zip,email,phone"/&gt;
 </pre>
-</div></div><p>The default for the submitlabel parameter is "Create/Update", 
but here we're overriding that default to a specific value.</p><p>The final 
result shows the reformatting and relabelling:</p><p><span 
class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image 
confluence-content-image-border" 
src="using-beaneditform-to-create-user-forms.data/address-v5.png"></span><br 
clear="none">Before continuing on to validation, a side note about message 
catalogs. Message catalogs are not just for re-labeling fields and options; 
we'll see in later chapters how message catalogs are used in the context of 
localization and internationalization.</p><p>Instead of putting the label for 
the submit button directly inside the template, we're going to provide a 
reference to the label; the actual label will go in the message 
catalog.</p><p>In Tapestry, when binding a parameter, the value you provide may 
include a prefix. The prefix guides Tapestry in how to interpret the rest 
 of the the parameter value ... is it the name of a property? The id of a 
component? A message key? Most parameters have a default prefix, usually 
"prop:", that is used when you fail to provide one (this helps to make the 
templates as terse as possible).</p><p>Here we want to reference a message from 
the catalog, so we use the "message:" prefix:</p><div class="code panel pdl" 
style="border-width: 1px;"><div class="codeContent panelContent pdl">
+</div></div><p>The default for the submitlabel parameter is "Create/Update", 
but here we're overriding that default to a specific value.</p><p>The final 
result shows the reformatting and relabelling:</p><p><span 
class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image 
confluence-external-resource confluence-content-image-border" 
src="https://cwiki-test.apache.org/confluence/download/attachments/23340431/address-v5.png?version=2&amp;modificationDate=1417055915000&amp;api=v2";
 
data-image-src="https://cwiki-test.apache.org/confluence/download/attachments/23340431/address-v5.png?version=2&amp;modificationDate=1417055915000&amp;api=v2";></span><br
 clear="none">Before continuing on to validation, a side note about message 
catalogs. Message catalogs are not just for re-labeling fields and options; 
we'll see in later chapters how message catalogs are used in the context of 
localization and internationalization.</p><p>Instead of putting the label for 
the submit button dir
 ectly inside the template, we're going to provide a reference to the label; 
the actual label will go in the message catalog.</p><p>In Tapestry, when 
binding a parameter, the value you provide may include a prefix. The prefix 
guides Tapestry in how to interpret the rest of the the parameter value ... is 
it the name of a property? The id of a component? A message key? Most 
parameters have a default prefix, usually "prop:", that is used when you fail 
to provide one (this helps to make the templates as terse as 
possible).</p><p>Here we want to reference a message from the catalog, so we 
use the "message:" prefix:</p><div class="code panel pdl" style="border-width: 
1px;"><div class="codeContent panelContent pdl">
 <pre class="brush: xml; gutter: false; theme: Default" 
style="font-size:12px;">    &lt;t:beaneditform object="address" 
submitlabel="message:submit-label"
         
reorder="honorific,firstName,lastName,street1,street2,city,state,zip,email,phone"
 /&gt;
 </pre>
@@ -169,14 +182,14 @@ DR=Dr.
 <pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">    @Validate("required")
     public String firstName;
 </pre>
-</div></div><p>What is that string, "required"? That's how you specify the 
desired validation. It is a series of names that identify what type of 
validation is desired. A number of validators are built in, such as "required", 
"minLength" and "maxLength". As elsewhere, Tapestry is case 
insensitive.</p><p>You can apply multiple validations, by separating the 
validator names with commas. Some validators can be configured (with an equals 
sign). Thus you might say "required,minLength=5" for a field that must be 
specified, and must be at least five characters long.</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>You can easily get confused when 
you make a change to an entity class, such as adding the @Validate annotation, 
and <em>not</em> see the result in the browser. Only component classes, and 
(most) classe
 s in the Tapestry services layer, are live-reloaded. Data and entity objects 
are not reloaded, so this is one area where you need to stop and restart Jetty 
to see the change.</p></div></div><p>Restart the application, and refresh your 
browser, then hit the Create Address button.</p><p><span 
class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image 
confluence-content-image-border" 
src="using-beaneditform-to-create-user-forms.data/address-v6.png"></span></p><p>This
 is a shot just after hitting the Create Address button; all the fields have 
been validated and errors displayed. Each field in error has been highlighted 
in red and had an error message added. Further, the label for each of the 
fields has also been highlighted in red, to even more clearly identify what's 
in error. The cursor has also been moved to the first field that's in error. 
And <em>all</em> of this is taking place on the client side, without any 
communication with the application.</p><p>Once all t
 he errors are corrected, and the form does submit, all validations are 
performed on the server side as well (just in case the client has JavaScript 
disabled).</p><p>So ... how about some more interesting validation than just 
"required or not". Tapestry has built in support for validating based on field 
length and several variations of field value, including regular expressions. 
Zip codes are pretty easy to express as a regular expression.</p><div 
class="code panel pdl" style="border-width: 1px;"><div class="codeContent 
panelContent pdl">
+</div></div><p>What is that string, "required"? That's how you specify the 
desired validation. It is a series of names that identify what type of 
validation is desired. A number of validators are built in, such as "required", 
"minLength" and "maxLength". As elsewhere, Tapestry is case 
insensitive.</p><p>You can apply multiple validations, by separating the 
validator names with commas. Some validators can be configured (with an equals 
sign). Thus you might say "required,minLength=5" for a field that must be 
specified, and must be at least five characters long.</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>You can easily get confused when 
you make a change to an entity class, such as adding the @Validate annotation, 
and <em>not</em> see the result in the browser. Only component classes, and 
(most) classe
 s in the Tapestry services layer, are live-reloaded. Data and entity objects 
are not reloaded, so this is one area where you need to stop and restart Jetty 
to see the change.</p></div></div><p>Restart the application, and refresh your 
browser, then hit the Create Address button.</p><p><span 
class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image 
confluence-external-resource confluence-content-image-border" 
src="https://cwiki-test.apache.org/confluence/download/attachments/23340431/address-v6.png?version=3&amp;modificationDate=1417056607000&amp;api=v2";
 
data-image-src="https://cwiki-test.apache.org/confluence/download/attachments/23340431/address-v6.png?version=3&amp;modificationDate=1417056607000&amp;api=v2";></span></p><p>This
 is a shot just after hitting the Create Address button; all the fields have 
been validated and errors displayed. Each field in error has been highlighted 
in red and had an error message added. Further, the label for each of the 
fields has
  also been highlighted in red, to even more clearly identify what's in error. 
The cursor has also been moved to the first field that's in error. And 
<em>all</em> of this is taking place on the client side, without any 
communication with the application.</p><p>Once all the errors are corrected, 
and the form does submit, all validations are performed on the server side as 
well (just in case the client has JavaScript disabled).</p><p>So ... how about 
some more interesting validation than just "required or not". Tapestry has 
built in support for validating based on field length and several variations of 
field value, including regular expressions. Zip codes are pretty easy to 
express as a regular expression.</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;">    @Validate("required,regexp=^\\d{5}(-\\d{4})?$")
     public String zip;
 </pre>
-</div></div><p>Let's give it a try; restart the application and enter an "abc" 
for the zip code.</p><p><span class="confluence-embedded-file-wrapper"><img 
class="confluence-embedded-image confluence-content-image-border" 
src="using-beaneditform-to-create-user-forms.data/address-v7.png"></span><br 
clear="none">This is what you'll see after typing "abc" and clicking the Create 
Address button.</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>Modern browsers will automatically 
validate a regexp field when the form is submitted, as shown above. Older 
browsers do not have that automatic support, but will still validate input, 
using the same decorations as for the required fields in the previous 
screenshot.</p></div></div><p>In any case, that's the right validation 
behavior, but it's the wrong message. Your users
  are not going to know or care about regular expressions.</p><p>Fortunately, 
it's easy to customize validation messages. All we need to know is the name of 
the property ("zip") and the name of the validator ("regexp"). We can then put 
an entry into the CreateAddress message catalog:</p><div class="preformatted 
panel" style="border-width: 1px;"><div class="preformattedContent panelContent">
+</div></div><p>Let's give it a try; restart the application and enter an "abc" 
for the zip code.</p><p><span class="confluence-embedded-file-wrapper"><img 
class="confluence-embedded-image confluence-external-resource 
confluence-content-image-border" 
src="https://cwiki-test.apache.org/confluence/download/attachments/23340431/address-v7.png?version=2&amp;modificationDate=1417056608000&amp;api=v2";
 
data-image-src="https://cwiki-test.apache.org/confluence/download/attachments/23340431/address-v7.png?version=2&amp;modificationDate=1417056608000&amp;api=v2";></span><br
 clear="none">This is what you'll see after typing "abc" and clicking the 
Create Address button.</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>Modern browsers will automatically 
validate a regexp field when the form is submitted, as shown above. O
 lder browsers do not have that automatic support, but will still validate 
input, using the same decorations as for the required fields in the previous 
screenshot.</p></div></div><p>In any case, that's the right validation 
behavior, but it's the wrong message. Your users are not going to know or care 
about regular expressions.</p><p>Fortunately, it's easy to customize validation 
messages. All we need to know is the name of the property ("zip") and the name 
of the validator ("regexp"). We can then put an entry into the CreateAddress 
message catalog:</p><div class="preformatted panel" style="border-width: 
1px;"><div class="preformattedContent panelContent">
 <pre>zip-regexp-message=Zip Codes are five or nine digits.  Example: 02134 or 
90125-1655.
 </pre>
-</div></div><p>Refresh the page and submit again:</p><p><span 
class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image 
confluence-content-image-border" 
src="using-beaneditform-to-create-user-forms.data/address-v8.png"></span></p><p>This
 trick isn't limited to just the regexp validator, it works equally well with 
<em>any</em> validator.</p><p>Let's go one step further. Turns out, we can move 
the regexp pattern to the message catalog as well. If you only provide the name 
of the validator in the @Validate annotation, Tapestry will search the 
containing page's message catalog of the constraint value, as well as the 
validation message. The constraint value for the regexp validator is the 
regular expression to match against.</p><div class="code panel pdl" 
style="border-width: 1px;"><div class="codeContent panelContent pdl">
+</div></div><p>Refresh the page and submit again:</p><p><span 
class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image 
confluence-external-resource confluence-content-image-border" 
src="https://cwiki-test.apache.org/confluence/download/attachments/23340431/address-v8.png?version=2&amp;modificationDate=1417056608000&amp;api=v2";
 
data-image-src="https://cwiki-test.apache.org/confluence/download/attachments/23340431/address-v8.png?version=2&amp;modificationDate=1417056608000&amp;api=v2";></span></p><p>This
 trick isn't limited to just the regexp validator, it works equally well with 
<em>any</em> validator.</p><p>Let's go one step further. Turns out, we can move 
the regexp pattern to the message catalog as well. If you only provide the name 
of the validator in the @Validate annotation, Tapestry will search the 
containing page's message catalog of the constraint value, as well as the 
validation message. The constraint value for the regexp validator is the 
regular expre
 ssion to match against.</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;">    @Validate("required,regexp")
     public String zip;
 </pre>
@@ -184,7 +197,7 @@ DR=Dr.
 <pre>zip-regexp=^\\d{5}(-\\d{4})?$
 zip-regexp-message=Zip Codes are five or nine digits.  Example: 02134 or 
90125-1655.
 </pre>
-</div></div><p>After a restart you'll see the ... the same behavior. But when 
we start creating more complicated regular expressions, it'll be much, much 
nicer to put them in the message catalog rather than inside the annotation 
value. And inside the message catalog, you can change and tweak the regular 
expressions without having to restart the application each time.</p><p>We could 
go a bit further here, adding more regular expression validation for phone 
numbers and e-mail addresses. We're also far from done in terms of further 
customizations of the BeanEditForm component.</p><p>By now you are likely 
curious about what happens <em>after</em> the form submits successfully 
(without validation errors), so that's what we'll focus on next.</p><p>Next: <a 
 href="using-tapestry-with-hibernate.html">Using Tapestry With 
Hibernate</a></p><p>&#160;</p><p></p></div>
+</div></div><p>After a restart you'll see the ... the same behavior. But when 
we start creating more complicated regular expressions, it'll be much, much 
nicer to put them in the message catalog rather than inside the annotation 
value. And inside the message catalog, you can change and tweak the regular 
expressions without having to restart the application each time.</p><p>We could 
go a bit further here, adding more regular expression validation for phone 
numbers and e-mail addresses. We're also far from done in terms of further 
customizations of the BeanEditForm component.</p><p>By now you are likely 
curious about what happens <em>after</em> the form submits successfully 
(without validation errors), so that's what we'll focus on next.</p><p>Next: <a 
 href="using-beaneditform-to-create-user-forms.html">Using BeanEditForm To 
Create User Forms</a></p><p>&#160;</p><p></p></div>
       </div>
 
       <div class="clearer"></div>

Modified: 
websites/production/tapestry/content/using-tapestry-with-hibernate.html
==============================================================================
--- websites/production/tapestry/content/using-tapestry-with-hibernate.html 
(original)
+++ websites/production/tapestry/content/using-tapestry-with-hibernate.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 &amp; blogs:</span><form 
enctype="application/x-www-form-urlencoded" method="get" 
action="http://tapestry.apache.org/search.html";> 
- <input type="text" name="q"> 
- <input type="submit" value="Search"> 
-</form></div><div class="emblem" style="float:left"><p><a  
href="index.html"><span class="confluence-embedded-file-wrapper"><img 
class="confluence-embedded-image confluence-external-resource" 
src="http://tapestry.apache.org/images/tapestry_small.png"; 
data-image-src="http://tapestry.apache.org/images/tapestry_small.png";></span></a></p></div><div
 class="title" style="float:left; margin: 0 0 0 3em"><h1 
id="SmallBanner-PageTitle">Using Tapestry With Hibernate</h1></div></div>
+            <div id="smallbanner"><div class="searchbox" 
style="float:right;margin: .3em 1em .1em 1em"><span style="color: #999; 
font-size: 90%">Tapestry docs, issues, wikis &amp; blogs:</span>
+<form enctype="application/x-www-form-urlencoded" method="get" 
action="http://tapestry.apache.org/search.html";>
+  <input type="text" name="q">
+  <input type="submit" value="Search">
+</form>
+
+</div>
+
+
+<div class="emblem" style="float:left"><p><a  href="index.html"><span 
class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image 
confluence-external-resource" 
src="http://tapestry.apache.org/images/tapestry_small.png"; 
data-image-src="http://tapestry.apache.org/images/tapestry_small.png";></span></a></p></div>
+
+
+<div class="title" style="float:left; margin: 0 0 0 3em"><h1 
id="SmallBanner-PageTitle">Using Tapestry With Hibernate</h1></div>
+
+</div>
       <div class="clearer"></div>
       </div>
 
@@ -175,7 +188,7 @@ public class CreateAddress
     }
 }
 </pre>
-</div></div><p>The <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/annotations/Inject.html";>Inject</a>
 annotation tells Tapestry to inject a service into the annotated field; 
Tapestry includes a sophisticated Inversion of Control container (similar in 
many ways to Spring) that is very good at locating available services by type, 
rather than by a string id. In any case, the Hibernate Session object is 
exposed as a Tapestry IoC service, ready to be injected (this is one of the 
things provided by the tapestry-hibernate module).</p><p>Tapestry automatically 
starts a transaction as necessary; however that transaction will be 
<em>aborted</em> at the end of the request by default. If we make changes to 
persistent objects, such as adding a new Address object, then it is necessary 
to commit the transaction.</p><p>The <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/hibernate/annotations/CommitA
 fter.html">CommitAfter</a> annotation can be applied to any component method; 
if the method completes normally, the transaction will be committed (and a new 
transaction started to replace the committed transaction).</p><p>After 
persisting the new address, we return to the main Index page of the 
application.</p><p><em>Note: In real applications, it is rare to have pages and 
components directly use the Hibernate Session. It is generally a better 
approach to define your own Data Access Object layer to perform common update 
operations and queries.</em></p><h2 
id="UsingTapestryWithHibernate-ShowingAddresses">Showing Addresses</h2><p>As a 
little preview of what's next, let's display all the Addresses entered by the 
user on the Index page of the application. After you enter a few names, it will 
look something like:</p><p><span class="confluence-embedded-file-wrapper"><img 
class="confluence-embedded-image confluence-content-image-border" 
src="using-tapestry-with-hibernate.data/index-grid-v1
 .png"></span></p><h2 
id="UsingTapestryWithHibernate-AddingtheGridtotheIndexpage">Adding the Grid to 
the Index page</h2><p>So, how is this implemented? Primarily, its accomplished 
by the <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Grid.html";>Grid</a>
 component.</p><p>The Grid component is based on the same concepts as the 
BeanEditForm component; it can pull apart a bean into columns. The columns are 
sortable, and when there are more entries than will fit on a single page, page 
navigation is automatically added.</p><p>A minimal Grid is very easy to add to 
the template. Just add this near the bottom of Index.tml:</p><div class="code 
panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" 
style="border-bottom-width: 1px;"><b>src/main/webapp/Index.tml 
(partial)</b></div><div class="codeContent panelContent pdl">
+</div></div><p>The <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/annotations/Inject.html";>Inject</a>
 annotation tells Tapestry to inject a service into the annotated field; 
Tapestry includes a sophisticated Inversion of Control container (similar in 
many ways to Spring) that is very good at locating available services by type, 
rather than by a string id. In any case, the Hibernate Session object is 
exposed as a Tapestry IoC service, ready to be injected (this is one of the 
things provided by the tapestry-hibernate module).</p><p>Tapestry automatically 
starts a transaction as necessary; however that transaction will be 
<em>aborted</em> at the end of the request by default. If we make changes to 
persistent objects, such as adding a new Address object, then it is necessary 
to commit the transaction.</p><p>The <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/hibernate/annotations/CommitA
 fter.html">CommitAfter</a> annotation can be applied to any component method; 
if the method completes normally, the transaction will be committed (and a new 
transaction started to replace the committed transaction).</p><p>After 
persisting the new address, we return to the main Index page of the 
application.</p><p><em>Note: In real applications, it is rare to have pages and 
components directly use the Hibernate Session. It is generally a better 
approach to define your own Data Access Object layer to perform common update 
operations and queries.</em></p><h2 
id="UsingTapestryWithHibernate-ShowingAddresses">Showing Addresses</h2><p>As a 
little preview of what's next, let's display all the Addresses entered by the 
user on the Index page of the application. After you enter a few names, it will 
look something like:</p><p><span class="confluence-embedded-file-wrapper"><img 
class="confluence-embedded-image confluence-external-resource 
confluence-content-image-border" src="https://cwiki-test.
 
apache.org/confluence/download/attachments/23340507/index-grid-v1.png?version=4&amp;modificationDate=1418482289000&amp;api=v2"
 
data-image-src="https://cwiki-test.apache.org/confluence/download/attachments/23340507/index-grid-v1.png?version=4&amp;modificationDate=1418482289000&amp;api=v2";></span></p><h2
 id="UsingTapestryWithHibernate-AddingtheGridtotheIndexpage">Adding the Grid to 
the Index page</h2><p>So, how is this implemented? Primarily, its accomplished 
by the <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Grid.html";>Grid</a>
 component.</p><p>The Grid component is based on the same concepts as the 
BeanEditForm component; it can pull apart a bean into columns. The columns are 
sortable, and when there are more entries than will fit on a single page, page 
navigation is automatically added.</p><p>A minimal Grid is very easy to add to 
the template. Just add this near the bottom of Index.tml:</p><div class="code 
panel
  pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" 
style="border-bottom-width: 1px;"><b>src/main/webapp/Index.tml 
(partial)</b></div><div class="codeContent panelContent pdl">
 <pre class="brush: xml; gutter: false; theme: Default" 
style="font-size:12px;">  &lt;t:grid source="addresses"
          
include="honorific,firstName,lastName,street1,city,state,zip,phone"/&gt;
 </pre>
@@ -195,7 +208,7 @@ public class Index
     }
 }
 </pre>
-</div></div><p>Here, we're using the Hibernate Session object to find all 
Address objects in the database. Any sorting that takes place will be done in 
memory. This is fine for now (with only a handful of Address objects in the 
database). Later we'll see how to optimize this for very large result 
sets.</p><h2 id="UsingTapestryWithHibernate-What'sNext?">What's Next?</h2><p>We 
have lots more to talk about: more components, more customizations, built-in 
Ajax support, more common design and implementation patterns, and even writing 
your own components (which is easy!).</p><p>Check out the many Tapestry 
resources available on the <a  href="documentation.html">Documentation</a> 
page, including the <a  href="getting-started.html">Getting Started</a> and <a  
href="frequently-asked-questions.html">FAQ</a> pages and the <a  
href="cookbook.html">Cookbook</a>. Be sure to peruse the <a  
href="user-guide.html">User Guide</a>, which provides comprehensive details on 
nearly every Tapestry topic. Fi
 nally, be sure to visit (and bookmark) <a  class="external-link" 
href="http://jumpstart.doublenegative.com.au/jumpstart7/"; 
rel="nofollow">Tapestry JumpStart</a>, which provides a nearly exhaustive set 
of tutorials.</p><p>&#160;</p><p></p></div>
+</div></div><p>Here, we're using the Hibernate Session object to find all 
Address objects in the database. Any sorting that takes place will be done in 
memory. This is fine for now (with only a handful of Address objects in the 
database). Later we'll see how to optimize this for very large result 
sets.</p><h2 id="UsingTapestryWithHibernate-What'sNext?">What's Next?</h2><p>We 
have lots more to talk about: more components, more customizations, built-in 
Ajax support, more common design and implementation patterns, and even writing 
your own components (which is easy!).</p><p>Check out the many Tapestry 
resources available on the <a  href="using-tapestry-with-hibernate.html">Using 
Tapestry With Hibernate</a> page, including the <a  
href="using-tapestry-with-hibernate.html">Using Tapestry With Hibernate</a> and 
<a  href="using-tapestry-with-hibernate.html">FAQ</a> pages and the <a  
href="using-tapestry-with-hibernate.html">Using Tapestry With Hibernate</a>. Be 
sure to peruse the <a  href=
 "using-tapestry-with-hibernate.html">Using Tapestry With Hibernate</a>, which 
provides comprehensive details on nearly every Tapestry topic. Finally, be sure 
to visit (and bookmark) <a  class="external-link" 
href="http://jumpstart.doublenegative.com.au/jumpstart7/"; 
rel="nofollow">Tapestry JumpStart</a>, which provides a nearly exhaustive set 
of tutorials.</p><p>&#160;</p><p></p></div>
       </div>
 
       <div class="clearer"></div>


Reply via email to