tapestry-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From build...@apache.org
Subject svn commit: r932579 - in /websites/production/tapestry/content: cache/main.pageCache using-tapestry-with-hibernate.data/index-grid-v1.png using-tapestry-with-hibernate.html
Date Sat, 13 Dec 2014 14:19:35 GMT
Author: buildbot
Date: Sat Dec 13 14:19:35 2014
New Revision: 932579

Log:
Production update by buildbot for tapestry

Modified:
    websites/production/tapestry/content/cache/main.pageCache
    websites/production/tapestry/content/using-tapestry-with-hibernate.data/index-grid-v1.png
    websites/production/tapestry/content/using-tapestry-with-hibernate.html

Modified: websites/production/tapestry/content/cache/main.pageCache
==============================================================================
Binary files - no diff available.

Modified: websites/production/tapestry/content/using-tapestry-with-hibernate.data/index-grid-v1.png
==============================================================================
Binary files - no diff available.

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 Dec 13 14:19:35
2014
@@ -84,14 +84,14 @@ table.ScrollbarTable td.ScrollbarNextIco
         </dependency>
 
         <dependency>
-            <groupId>hsqldb</groupId>
+            <groupId>org.hsqldb</groupId>
             <artifactId>hsqldb</artifactId>
-            <version>1.8.0.7</version>
+            <version>2.3.2</version>
         </dependency>
         ...
     </dependencies>
 ]]></script>
-</div></div><p>The tapestry-hibernate library includes, as transitive dependencies,
Hibernate and tapestry-core. This means that you can simply replace "tapestry-core" with "tapestry-hibernate"
inside the &lt;artifactId&gt; element.</p><p>After changing the POM and
saving, Maven should automatically download the new dependencies.</p><h3 id="UsingTapestryWithHibernate-HibernateConfiguration">Hibernate
Configuration</h3><p>Hibernate has a master configuration file used to store connection
and other data.</p><div class="code panel pdl" style="border-width: 1px;"><div
class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>src/main/resources/hibernate.cfg.xml</b></div><div
class="codeContent panelContent pdl">
+</div></div><p>The tapestry-hibernate library includes, as transitive dependencies,
Hibernate and tapestry-core. This means that you can simply replace "tapestry-core" with "tapestry-hibernate"
inside the &lt;artifactId&gt; element.</p><p>After changing the POM and
saving, Maven should automatically download the JARs for the new dependencies.</p><h3
id="UsingTapestryWithHibernate-HibernateConfiguration">Hibernate Configuration</h3><p>Hibernate
needs a master configuration file, hibernate.cfg.xml, used to store connection and other data.
Create this in your src/main/resources folder:</p><div class="code panel pdl" style="border-width:
1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>src/main/resources/hibernate.cfg.xml</b></div><div
class="codeContent panelContent pdl">
 <script class="theme: Default; brush: xml; gutter: false" type="syntaxhighlighter"><![CDATA[&lt;!DOCTYPE
hibernate-configuration PUBLIC
         &quot;-//Hibernate/Hibernate Configuration DTD 3.0//EN&quot;
         &quot;http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd&quot;&gt;
@@ -108,7 +108,7 @@ table.ScrollbarTable td.ScrollbarNextIco
     &lt;/session-factory&gt;
 &lt;/hibernate-configuration&gt;
 ]]></script>
-</div></div><p>Most of the configuration is to identify the JDBC driver
and connection URL.</p><p>Note the connection URL. We are instructing HSQLDB to
store its database files within our project's target directory. We are also instructing HSQLDB
to flush any data to these files at shutdown. This means that data will persist across different
invocations of this project, but if the target directory is destroyed (e.g., via "mvn clean"),
then all the database contents will be lost.</p><p>In addition, we are configuring
Hibernate to <em>update</em> the database schema; when Hibernate initializes it
will create or even modify tables to match the entities. Finally, we are configuring Hibernate
to output any SQL it executes, which is very useful when initially building an application.</p><p>But
what entities? Normally, the available entities are listed inside hibernate.cfg.xml, but that's
not necessary with Tapestry; in another example of convention over configuration, Tapestry
locates all
  entity classes inside the entities package and adds them to the configuration. Currently,
that is just the Address entity.</p><h2 id="UsingTapestryWithHibernate-AddingHibernateAnnotations">Adding
Hibernate Annotations</h2><p>For an entity class to be used with Hibernate, some
Hibernate annotations must be added to the class.</p><p>Below is the updated Address
class, with the Hibernate annotations (as well as the Tapestry ones).</p><div class="code
panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width:
1px;"><b>src/main/java/com/example/tutorial/entities/Address.java</b></div><div
class="codeContent panelContent pdl">
+</div></div><p>Most of the configuration is to identify the JDBC driver
and connection URL.</p><p>Note the connection URL. We are instructing HSQLDB to
store its database files within our project's target directory. We are also instructing HSQLDB
to flush any data to these files at shutdown. This means that data will persist across different
invocations of this project, but if the target directory is destroyed (e.g., via "mvn clean"),
then all the database contents will be lost.</p><p>In addition, we are configuring
Hibernate to <em>update</em> the database schema; when Hibernate initializes it
will create or even modify tables to match the entities. Finally, we are configuring Hibernate
to output any SQL it executes, which is very useful when initially building an application.</p><p>But
what entities? Normally, the available entities are listed inside hibernate.cfg.xml, but that's
not necessary with Tapestry; in another example of convention over configuration, Tapestry
locates all
  entity classes inside the entities package ("com.example.tutorial.entities" in our case)
and adds them to the configuration. Currently, that is just the Address entity.</p><h2
id="UsingTapestryWithHibernate-AddingHibernateAnnotations">Adding Hibernate Annotations</h2><p>For
an entity class to be used with Hibernate, some Hibernate annotations must be added to the
class.</p><p>Below is the updated Address class, with the Hibernate annotations
(as well as the Tapestry ones).</p><div class="code panel pdl" style="border-width:
1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>src/main/java/com/example/tutorial/entities/Address.java</b></div><div
class="codeContent panelContent pdl">
 <script class="theme: Default; brush: java; gutter: false" type="syntaxhighlighter"><![CDATA[package
com.example.tutorial.entities;
 
 import javax.persistence.Entity;
@@ -155,7 +155,7 @@ public class Address
   public String phone;
 }
 ]]></script>
-</div></div><p>The Tapestry annotations, @NonVisual and @Validate, may
be placed on the setter or getter method or on the field (as we have done here). As with the
Hibernate annotations, putting the annotation on the field requires that the field name match
the corresponding property name.</p><ul><li><strong>@NonVisual</strong>
&#8211; indicates a field, such as a primary key, that should not be made visible to the
user.</li><li><strong>@Validate</strong> &#8211; identifies the
validations associated with a field.</li></ul><h2 id="UsingTapestryWithHibernate-UpdatingtheDatabase">Updating
the Database</h2><p>So we have a database up and running, and Hibernate is configured
to connect to it. Let's make use of that to store our Address object in the database.</p><p>What
we need is to provide some code to be executed when the form is submitted. When a Tapestry
form is submitted, there is a whole series of events that get fired. The event we are interested
in is the "success" event, which
  comes late in the process, after all the values have been pulled out of the request and
applied to the page properties, and after all server-side validations have occured.</p><p>The
success event is only fired if there are no validation errors.</p><p>Our event
handler must do two things:</p><ul><li>Use the Hibernate Session object
to persist the new Address object.</li><li>Commit the transaction to force the
data to be written to the database.</li></ul><div class="code panel pdl" style="border-width:
1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>src/main/java/com/example/tutorial/pages/address/CreateAddress.java</b></div><div
class="codeContent panelContent pdl">
+</div></div><p>The Tapestry annotations, @NonVisual and @Validate, may
be placed on the setter or getter method or on the field (as we have done here). As with the
Hibernate annotations, putting the annotation on the field requires that the field name match
the corresponding property name.</p><ul><li><strong>@NonVisual</strong>
&#8211; indicates a field, such as a primary key, that should not be made visible to the
user.</li><li><strong>@Validate</strong> &#8211; identifies the
validations associated with a field.</li></ul><p>At this point you should
stop and restart your application.</p><h2 id="UsingTapestryWithHibernate-UpdatingtheDatabase">Updating
the Database</h2><p>So we have a database set up, and Hibernate is configured
to connect to it. Let's make use of that to store our Address object in the database.</p><p>What
we need is to provide some code to be executed when the form is submitted. When a Tapestry
form is submitted, there is a whole series of events that get fired. Th
 e event we are interested in is the "success" event, which comes late in the process, after
all the values have been pulled out of the request and applied to the page properties, and
after all server-side validations have occurred.</p><p>The success event is only
fired if there are no validation errors.</p><p>Our event handler must do two things:</p><ul><li>Use
the Hibernate Session object to persist the new Address object.</li><li>Commit
the transaction to force the data to be written to the database.</li></ul><p>Let's
update our CreateAddress.java class:</p><div class="code panel pdl" style="border-width:
1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>src/main/java/com/example/tutorial/pages/address/CreateAddress.java</b></div><div
class="codeContent panelContent pdl">
 <script class="theme: Default; brush: java; gutter: false" type="syntaxhighlighter"><![CDATA[package
com.example.tutorial.pages.address;
 
 import com.example.tutorial.entities.Address;
@@ -186,17 +186,25 @@ public class CreateAddress
     }
 }
 ]]></script>
-</div></div><p>The <a shape="rect" 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. 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
shape="rect" class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/hibernate/annota
 tions/CommitAfter.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><img class="confluence-embedded-image confluence-content-image-border"
src="https://cwiki.apache.org/confluence/download/attachments/23340507/index-grid-v1.pn
 g?version=1&amp;modificationDate=1286814603000&amp;api=v2" data-image-src="/confluence/download/attachments/23340507/index-grid-v1.png?version=1&amp;modificationDate=1286814603000&amp;api=v2"></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
shape="rect" 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:</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">
-<script class="theme: Default; brush: xml; gutter: false" type="syntaxhighlighter"><![CDATA[
 &lt;t:grid source=&quot;addresses&quot;/&gt;
-]]></script>
-</div></div><p>And all we have to do is supply the addresses property in
the Java code:</p><div class="code panel pdl" style="border-width: 1px;"><div
class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>src/main/java/com/example/tutorial/pages/Index.java
(partial)</b></div><div class="codeContent panelContent pdl">
-<script class="theme: Default; brush: java; gutter: false" type="syntaxhighlighter"><![CDATA[
   @Inject
+</div></div><p>The <a shape="rect" 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 shape="rect" class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/hiber
 nate/annotations/CommitAfter.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><img class="confluence-embedded-image confluence-content-image-border"
src="https://cwiki.apache.org/confluence/download/attachments/23340507/index
 -grid-v1.png?version=3&amp;modificationDate=1418479523098&amp;api=v2" data-image-src="/confluence/download/attachments/23340507/index-grid-v1.png?version=3&amp;modificationDate=1418479523098&amp;api=v2"></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
shape="rect" 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="b
 order-bottom-width: 1px;"><b>src/main/webapp/Index.tml (partial)</b></div><div
class="codeContent panelContent pdl">
+<script class="theme: Default; brush: xml; gutter: false" type="syntaxhighlighter"><![CDATA[
 &lt;t:grid source=&quot;addresses&quot;
+         reorder=&quot;honorific,firstName,lastName,street1,street2,city,state,zip,email,phone&quot;/&gt;
+]]></script>
+</div></div><p>Note that the Grid component accepts the same "reorder"
parameter that we used with the BeanEditForm.</p><p>Now all we have to do is supply
the addresses property in the Java code. Here's how Index.java should look now:</p><div
class="code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader
pdl" style="border-bottom-width: 1px;"><b>src/main/java/com/example/tutorial/pages/Index.java</b></div><div
class="codeContent panelContent pdl">
+<script class="theme: Default; brush: java; gutter: false" type="syntaxhighlighter"><![CDATA[package
com.example.tutorial.pages;
+import java.util.List;
+import org.apache.tapestry5.ioc.annotations.Inject;
+import org.hibernate.Session;
+import com.example.tutorial.entities.Address;
+public class Index
+{
+    @Inject
     private Session session;
-
     public List&lt;Address&gt; getAddresses()
     {
         return session.createCriteria(Address.class).list();
     }
+}
 ]]></script>
 </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 shape="rect" href="documentation.html">Tapestry 5 Documentation page</a>
page, including the <a shape="rect" href="getting-started.html">Getting Started</a>
and <a shape="rect" href="frequently-asked-questions.html">FAQ</a> pages and the
<a shape="rect" href="cookbook.html">Cookbook Recipies</a>. Be sure to peruse
the <a shape="rect" href="user-guide.html">Us
 er Guide</a>, which provides comprehensive details on nearly every Tapestry topic.</p><style
type="text/css">/*<![CDATA[*/
 table.ScrollbarTable  {border: none;padding: 3px;width: 100%;padding: 3px;margin: 0px;background-color:
#f0f0f0}



Mime
View raw message