tapestry-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From conflue...@apache.org
Subject [CONF] Apache Tapestry > Integrating with JPA
Date Fri, 05 Aug 2011 01:18:00 GMT
<html>
<head>
    <base href="https://cwiki.apache.org/confluence">
            <link rel="stylesheet" href="/confluence/s/2042/9/12/_/styles/combined.css?spaceKey=TAPESTRY&amp;forWysiwyg=true" type="text/css">
    </head>
<body style="background: white;" bgcolor="white" class="email-body">
<div id="pageContent">
<div id="notificationFormat">
<div class="wiki-content">
<div class="email">
    <h2><a href="https://cwiki.apache.org/confluence/display/TAPESTRY/Integrating+with+JPA">Integrating with JPA</a></h2>
    <h4>Page <b>edited</b> by             <a href="https://cwiki.apache.org/confluence/display/~bobharner">Bob Harner</a>
    </h4>
        <div id="versionComment">
        <b>Comment:</b>
        Lots of minor formatting &amp; wording tweaks, removed &nbsp; etc., no intended change of meaning.<br />
    </div>
        <br/>
                         <h4>Changes (47)</h4>
                                 
    
<div id="page-diffs">
                    <table class="diff" cellpadding="0" cellspacing="0">
    
            <tr><td class="diff-unchanged" >{since:since=5.3} <br> <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">Starting from release 5.3, Tapestry provides a built-in JPA integration which supersedes [Tynamo&#39;s JPA integration|http://tynamo.org/tapestry-jpa+guide]. <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">Starting with Tapestry 5.3, Tapestry provides built-in integration with the Java Persistence API (JPA). This module supersedes [Tynamo&#39;s JPA integration|http://tynamo.org/tapestry-jpa+guide]. <br></td></tr>
            <tr><td class="diff-unchanged" > <br>*Contents* <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >&lt;persistence xmlns=&quot;http://java.sun.com/xml/ns/persistence&quot; <br>             version=&quot;2.0&quot;&gt; <br></td></tr>
            <tr><td class="diff-changed-lines" >&lt;persistence-unit name=&quot;DemoUnit&quot; <span class="diff-added-words"style="background-color: #dfd;">transaction-type=&quot;RESOURCE_LOCAL&quot;&gt;</span> <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">                     transaction-type=&quot;RESOURCE_LOCAL&quot;&gt; <br></td></tr>
            <tr><td class="diff-unchanged" >       &lt;properties&gt; <br>          &lt;property name=&quot;javax.persistence.jdbc.driver&quot; <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" > <br>&lt;/persistence&gt;{code} <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">By default, the persistence&amp;nbsp;descriptor is named _persistence.xml_&amp;nbsp;and is expected to be located on the classpath in the _META-INF_ directory.&amp;nbsp;If you want to place the&amp;nbsp;_persistence.xml_&amp;nbsp;file in an other directory or name it arbitrarily, you can make a contribution to the&amp;nbsp;_SymbolProvider_&amp;nbsp;service, as shown in the following example. This is a quite useful feature if you want to use a different persistence descriptor for tests. <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;"> <br>By default, the persistence descriptor is named _persistence.xml_ and is expected to be located on the classpath in the _META-INF_ directory. If you want to place the _persistence.xml_ file in another directory or name it differently, you can make a contribution to the _SymbolProvider_ service, as shown in the following example. This is a quite useful feature if you want to use a different persistence descriptor for tests. <br> <br></td></tr>
            <tr><td class="diff-unchanged" >{code}public class AppModule { <br> <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >h2. XML-less JPA configuration <br> <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">Configuring&amp;nbsp;JPA with Tapestry is much more simple than defined in the JPA specification. Tapestry allows you to configure the [EntityManagerFactory|http://download.oracle.com/javaee/6/api/javax/persistence/EntityManagerFactory.html] programmatically without writing XML configuration files. Imagine you want to use&amp;nbsp;JDBC connections managed by the container and provided through JNDI. The resulting persistence descriptor might look like the following one. <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">With Tapestry, configuring JPA is much simpler than as described in the JPA specification. Tapestry allows you to configure the [EntityManagerFactory|http://download.oracle.com/javaee/6/api/javax/persistence/EntityManagerFactory.html] programmatically, without writing any XML. Imagine you want to use JDBC connections managed by the container and provided through JNDI. The resulting persistence descriptor might look like this: <br> <br></td></tr>
            <tr><td class="diff-unchanged" >{code:lang=xml}&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt; <br>&lt;persistence xmlns=&quot;http://java.sun.com/xml/ns/persistence&quot; <br>             version=&quot;2.0&quot;&gt; <br></td></tr>
            <tr><td class="diff-changed-lines" >&lt;persistence-unit name=&quot;JTAUnit&quot; <span class="diff-added-words"style="background-color: #dfd;">transaction-type=&quot;RESOURCE_LOCAL&quot;&gt;</span> <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">                     transaction-type=&quot;RESOURCE_LOCAL&quot;&gt; <br></td></tr>
            <tr><td class="diff-unchanged" > <br>      &lt;non-jta-data-source&gt; <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" > <br>      &lt;properties&gt; <br></td></tr>
            <tr><td class="diff-changed-lines" >&lt;property name=&quot;eclipselink.ddl-generation&quot; <span class="diff-added-words"style="background-color: #dfd;">value=&quot;create-tables&quot;/&gt;</span> <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">                   value=&quot;create-tables&quot;/&gt; <br></td></tr>
            <tr><td class="diff-changed-lines" >&lt;property name=&quot;eclipselink.logging.level&quot; <span class="diff-added-words"style="background-color: #dfd;">value=&quot;fine&quot;/&gt;</span> <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">                   value=&quot;fine&quot;/&gt; <br></td></tr>
            <tr><td class="diff-unchanged" >      &lt;/properties&gt; <br>   &lt;/persistence-unit&gt; <br> <br>&lt;/persistence&gt;{code} <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">Now let&#39;s see how to provide the same configuration without to write any single line of XML. The following example demonstrates&amp;nbsp;an equivalent JPA configuration. <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;"> <br>Now let&#39;s see how to provide the same configuration _without_ XML. The following demonstrates an equivalent JPA configuration. <br> <br></td></tr>
            <tr><td class="diff-unchanged" >{code}public class AppModule { <br> <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" > <br>            unitInfo.nonJtaDataSource(&quot;jdbc/JPATest&quot;) <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">               .addProperty(&quot;eclipselink.ddl-generation&quot;, <br>                            &quot;create-tables&quot;) <br>               .addProperty(&quot;eclipselink.logging.level&quot;, <br>                            &quot;fine&quot;); <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">               .addProperty(&quot;eclipselink.ddl-generation&quot;, &quot;create-tables&quot;) <br>               .addProperty(&quot;eclipselink.logging.level&quot;, &quot;fine&quot;); <br></td></tr>
            <tr><td class="diff-unchanged" >         } <br>     }; <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >}{code} <br> <br></td></tr>
            <tr><td class="diff-changed-lines" >In the example above you can see a contribution to the _EntityManagerSource_ service. This service is responsible for <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">creating&amp;nbsp;[EntityManagerFactory|http://download.oracle.com/javaee/6/api/javax/persistence/EntityManagerFactory.html]&amp;nbsp;to</span> <span class="diff-added-words"style="background-color: #dfd;">creating the [EntityManagerFactory|http://download.oracle.com/javaee/6/api/javax/persistence/EntityManagerFactory.html] to</span> be used to create [EntityManager|http://download.oracle.com/javaee/6/api/javax/persistence/EntityManager.html]. When the service is initialized, it parses the _persistence.xml_ file, if available. For any persistence unit defined in the XML descriptor <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">an&amp;nbsp;_TapestryPersistenceUnitInfo_</span> <span class="diff-added-words"style="background-color: #dfd;">a _TapestryPersistenceUnitInfo_ object</span> is created. <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">The&amp;nbsp;_TapestryPersistenceUnitInfo_</span> <span class="diff-added-words"style="background-color: #dfd;">The _TapestryPersistenceUnitInfo_</span> interface is a mutable extension of <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">the&amp;nbsp;[PersistenceUnitInfo|http://download.oracle.com/javaee/6/api/javax/persistence/spi/PersistenceUnitInfo.html]</span> <span class="diff-added-words"style="background-color: #dfd;">the [PersistenceUnitInfo|http://download.oracle.com/javaee/6/api/javax/persistence/spi/PersistenceUnitInfo.html]</span> interface (defined in the JPA specification) that allows you to configure a persistence unit programmatically. <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">After parsing persistence descriptor, EntityManagerSource service applies its configuration to create further persistence units and/or update the existing. The service’s configuration is a map in which persistence unit names are associated with&amp;nbsp;_PersistenceUnitConfigurer_&amp;nbsp;instances.&amp;nbsp;A&amp;nbsp;PersistenceUnitConfigurer is used to configure a persistence unit programmatically that has been&amp;nbsp;associated with it. In the example above you can see a contribution providing a PersistenceUnitConfigurer for the&amp;nbsp;unit named _JTAUnit_.&amp;nbsp; <br>{info}Note that the TapestryPersistenceUnitInfo instance passed to the PersistenceUnitConfigurer is either empty or my contain the persistence unit metadata read from the persistence.xml file.&amp;nbsp;What happens if you contribute a&amp;nbsp;PersistenceUnitConfigurer for a persistence unit that has not been defined in the&amp;nbsp;_persistence.xml_&amp;nbsp;file? In this case Tapestry assumes that you want to configure the persistence unit programmatically and just creates a fresh _TapestryPersistenceUnitInfo_ and passes it to the&amp;nbsp;_PersistenceUnitConfigurer_.{info} <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">After parsing the persistence descriptor, the EntityManagerSource service applies its configuration to create further persistence units and/or update the existing ones. The service’s configuration is a map in which persistence unit names are associated with _PersistenceUnitConfigurer_ instances. A PersistenceUnitConfigurer is used to configure a persistence unit programmatically that has been associated with it. In the example above you can see a contribution providing a PersistenceUnitConfigurer for the unit named _JTAUnit_. <br> <br>{info}Note that the TapestryPersistenceUnitInfo instance passed to the PersistenceUnitConfigurer is either empty or my contain the persistence unit metadata read from the persistence.xml file. What happens if you contribute a PersistenceUnitConfigurer for a persistence unit that has not been defined in the persistence.xml file? In this case Tapestry assumes that you want to configure the persistence unit programmatically and just creates a fresh _TapestryPersistenceUnitInfo_ object and passes it to the _PersistenceUnitConfigurer_.{info} <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-changed-lines" >h2. Automatically adding managed <span class="diff-changed-words">classes<span class="diff-deleted-chars"style="color:#999;background-color:#fdd;text-decoration:line-through;">&amp;nbsp;</span></span> <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-changed-lines" >If only a single persistence unit is defined, Tapestry scans <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">the&amp;nbsp;&amp;nbsp;_application-root-package.entities_&amp;nbsp;package.</span> <span class="diff-added-words"style="background-color: #dfd;">the  _application-root-package.entities_ package.</span> The classes in that package are automatically added as managed classes to the defined persistence unit. <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-changed-lines" >If you have additional packages containing entities, you may contribute them to <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">the&amp;nbsp;_JpaEntityPackageManager_&amp;nbsp;service</span> <span class="diff-added-words"style="background-color: #dfd;">the _JpaEntityPackageManager_ service</span> configuration. <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;"> <br></td></tr>
            <tr><td class="diff-unchanged" >{code}public class AppModule { <br> <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >h1. Injecting the EntityManager <br> <br></td></tr>
            <tr><td class="diff-changed-lines" >The created entity managers can be injected into page, component and other services. <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">&amp;nbsp;</span> <br></td></tr>
            <tr><td class="diff-unchanged" > <br>h2. Injecting the EntityManager into page and component classes <br> <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">Depending on whether more than one persistence unit has been defined, the way to inject&amp;nbsp;{color:#539126}\[{color}{color:#539126}EntityManager{color}\|http://download.oracle.com/javaee/6/api/javax/persistence/EntityManager.html\]&amp;nbsp;varies slightly.&amp;nbsp;Let’s start with a simple scenario, where only a single persistence unit is defined. In this case, an&amp;nbsp;_[EntityManager|http://download.oracle.com/javaee/6/api/javax/persistence/EntityManager.html]_&amp;nbsp;can be injected using the&amp;nbsp;_@Inject_&amp;nbsp;annotation. <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">Depending on whether more than one persistence unit has been defined, the way to inject [EntityManager|http://download.oracle.com/javaee/6/api/javax/persistence/EntityManager.html] varies slightly. Let’s start with a simple scenario, where only a single persistence unit is defined. In this case, an EntityManager can be injected using the @Inject annotation. <br></td></tr>
            <tr><td class="diff-unchanged" > <br>{code}public class CreateAddress { <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >   } <br>}{code} <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">Alternatively, you can use the&amp;nbsp;_[@PersistenceContext|http://download.oracle.com/javaee/6/api/javax/persistence/PersistenceContext.html]_&amp;nbsp;annotation to get the&amp;nbsp;_[EntityManager|http://download.oracle.com/javaee/6/api/javax/persistence/EntityManager.html]_\_&amp;nbsp;_injected into a page or component, as shown in the following example. <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;"> <br>Alternatively, you can use the @[PersistenceContext|http://download.oracle.com/javaee/6/api/javax/persistence/PersistenceContext.html] annotation to get the EntityManager injected into a page or component, as shown in the following example. <br> <br></td></tr>
            <tr><td class="diff-unchanged" >{code}public class CreateAddress { <br> <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >   } <br>}{code} <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;"> <br></td></tr>
            <tr><td class="diff-changed-lines" >If you have multiple instances of persistence-unit defined in the same application, you need to explicitly tell Tapestry which persistence unit you want to get injected. This is what <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">the&amp;nbsp;_@PersistenceContext_&amp;nbsp;annotation’ s&amp;nbsp;_name_&amp;nbsp;attribute</span> <span class="diff-added-words"style="background-color: #dfd;">the @PersistenceContext annotation’s _name_ attribute</span> is used for? <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">&amp;nbsp;The</span> <span class="diff-added-words"style="background-color: #dfd;"> The</span> following example demonstrates how to inject the persistence unit named <span class="diff-changed-words">_DemoUnit_.<span class="diff-deleted-chars"style="color:#999;background-color:#fdd;text-decoration:line-through;">&amp;nbsp;</span></span> <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;"> <br></td></tr>
            <tr><td class="diff-unchanged" >{code}public class CreateAddress { <br> <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >h2. Injecting EntityManager into services <br> <br></td></tr>
            <tr><td class="diff-changed-lines" >While component injection occurs only on fields, the injection in the IoC layer may be triggered by <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">a&amp;nbsp;</span> <span class="diff-added-words"style="background-color: #dfd;">a </span> field or a constructor. The following example demonstrates field injection, when a single persistence unit is defined in the persistence descriptor. <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;"> <br></td></tr>
            <tr><td class="diff-unchanged" >{code}public class UserDAOImpl implements UserDAO { <br>   @Inject <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >   ... <br>}{code} <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;"> <br></td></tr>
            <tr><td class="diff-changed-lines" >If multiple persistence units are defined in the same application, you need to disambiguate the unit to inject. This is done <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">by placing the&amp;nbsp;_[@PersistenceContext|http://download.oracle.com/javaee/6/api/javax/persistence/PersistenceContext.html]_&amp;nbsp;annotation,</span> <span class="diff-added-words"style="background-color: #dfd;">with the [@PersistenceContext|http://download.oracle.com/javaee/6/api/javax/persistence/PersistenceContext.html] annotation,</span> as shown in the following <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">example.&amp;nbsp;Because&amp;nbsp;_[@PersistenceContext|http://download.oracle.com/javaee/6/api/javax/persistence/PersistenceContext.html]_&amp;nbsp;annotation</span> <span class="diff-added-words"style="background-color: #dfd;">example. Because @PersistenceContext</span> must not be placed on constructor parameters, you can’t use constructor injection and must switch to field injection. <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;"> <br></td></tr>
            <tr><td class="diff-unchanged" >{code}public class UserDAOImpl implements UserDAO { <br>   @Inject <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >h1. Transaction management <br> <br></td></tr>
            <tr><td class="diff-changed-lines" >As you <span class="diff-added-words"style="background-color: #dfd;">may</span> already know from the Hibernate integration library, Tapestry automatically manages transactions for you. The JPA integration library defines <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">the&amp;nbsp;_@CommitAfter&amp;nbsp;_annotation,</span> <span class="diff-added-words"style="background-color: #dfd;">the @CommitAfter annotation,</span> which acts as the correspondent annotation from the Hibernate integration library. Let’s explore <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">the&amp;nbsp;_UserDAO_&amp;nbsp;interface</span> <span class="diff-added-words"style="background-color: #dfd;">the _UserDAO_ interface</span> to see the annotation in action. <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;"> <br></td></tr>
            <tr><td class="diff-unchanged" >{code}public interface UserDAO { <br> <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >   void delete(User... users); <br>}{code} <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;"> <br></td></tr>
            <tr><td class="diff-changed-lines" >As you can see, the annotation may be placed on service method in order to mark that method as transactional. Any method marked <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">with&amp;nbsp;_@CommitAfter_&amp;nbsp;annotation</span> <span class="diff-added-words"style="background-color: #dfd;">with the @CommitAfter annotation</span> will have a transaction started before, and committed <span class="diff-changed-words">after<span class="diff-added-chars"style="background-color: #dfd;">,</span></span> it is called. Runtime exceptions thrown by by a transactional method will abort the transaction. Checked exceptions are ignored and the transaction will be committed anyway. <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;"> <br></td></tr>
            <tr><td class="diff-changed-lines" >{warning}Note that [EntityTransaction|http://download.oracle.com/javaee/6/api/javax/persistence/EntityTransaction.html] interface does not support two phase <span class="diff-changed-words">commit<span class="diff-added-chars"style="background-color: #dfd;">s</span>.</span> Committing transactions of multiple EntityManagers in the same request might result in data consistency issues. That’s why @CommitAfter annotation must be accompanied by the <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">[@PersistenceContex|http://download.oracle.com/javaee/6/api/javax/persistence/PersistenceContext.html]t</span> <span class="diff-added-words"style="background-color: #dfd;">@PersistenceContext</span> annotation if multiple persistence unit are defined in an application. This way you can only commit the transaction of a single persistence unit. You should be very carefully, if you are committing multiple transactions manually in the same request.{warning} <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;"> <br></td></tr>
            <tr><td class="diff-changed-lines" >After placing <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">the&amp;nbsp;_@CommitAfter_&amp;nbsp;annotation</span> <span class="diff-added-words"style="background-color: #dfd;">the @CommitAfter annotation</span> on methods, you need to tell Tapestry to advise those methods. This is accomplished by adding the transaction advice, as shown in the following example. <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;"> <br></td></tr>
            <tr><td class="diff-unchanged" >{code}public class AppModule { <br> <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
    
            </table>
    </div>                            <h4>Full Content</h4>
                    <div class="notificationGreySide">
        

<div class='panelMacro'><table class='infoMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="/confluence/images/icons/emoticons/information.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td><b>Added in 5.3</b><br /></td></tr></table></div>
<div style="border-right: 20px solid #D8E4F1;border-left: 20px solid #D8E4F1;"></div>

<p>Starting with Tapestry 5.3, Tapestry provides built-in integration with the Java Persistence API (JPA). This module supersedes <a href="http://tynamo.org/tapestry-jpa+guide" class="external-link" rel="nofollow">Tynamo's JPA integration</a>.</p>

<p><b>Contents</b></p>
<div>
<ul>
    <li><a href='#IntegratingwithJPA-ConfiguringJPA'>Configuring JPA</a></li>
<ul>
    <li><a href='#IntegratingwithJPA-XMLlessJPAconfiguration'>XML-less JPA configuration</a></li>
    <li><a href='#IntegratingwithJPA-Automaticallyaddingmanagedclasses'>Automatically adding managed classes</a></li>
</ul>
    <li><a href='#IntegratingwithJPA-InjectingtheEntityManager'>Injecting the EntityManager</a></li>
<ul>
    <li><a href='#IntegratingwithJPA-InjectingtheEntityManagerintopageandcomponentclasses'>Injecting the EntityManager into page and component classes</a></li>
    <li><a href='#IntegratingwithJPA-InjectingEntityManagerintoservices'>Injecting EntityManager into services</a></li>
</ul>
    <li><a href='#IntegratingwithJPA-Transactionmanagement'>Transaction management</a></li>
</ul></div>

<h1><a name="IntegratingwithJPA-ConfiguringJPA"></a>Configuring JPA</h1>

<p>The persistence.xml file is the standard configuration file in JPA used to define the persistence units. Tapestry reads this file to create the <a href="http://download.oracle.com/javaee/6/api/javax/persistence/EntityManagerFactory.html" class="external-link" rel="nofollow">EntityManagerFactory</a>. The following example demonstrates a persistence.xml file.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml"><span class="code-tag">&lt;?xml version=<span class="code-quote">"1.0"</span> encoding=<span class="code-quote">"UTF-8"</span>?&gt;</span>
&lt;persistence xmlns=<span class="code-quote">"http://java.sun.com/xml/ns/persistence"</span>
             version=<span class="code-quote">"2.0"</span>&gt;
   <span class="code-tag">&lt;persistence-unit name=<span class="code-quote">"DemoUnit"</span> transaction-type=<span class="code-quote">"RESOURCE_LOCAL"</span>&gt;</span>
       <span class="code-tag">&lt;properties&gt;</span>
          &lt;property name=<span class="code-quote">"javax.persistence.jdbc.driver"</span>
                    value=<span class="code-quote">"org.h2.Driver"</span> /&gt;
          &lt;property name=<span class="code-quote">"javax.persistence.jdbc.url"</span>
                    value=<span class="code-quote">"jdbc:h2:mem:test"</span> /&gt;
          &lt;property name=<span class="code-quote">"javax.persistence.jdbc.username"</span>
                    value=<span class="code-quote">"sa"</span> /&gt;
          &lt;property name=<span class="code-quote">"eclipselink.ddl-generation"</span>
                    value=<span class="code-quote">"create-tables"</span>/&gt;
          &lt;property name=<span class="code-quote">"eclipselink.logging.level"</span>
                    value=<span class="code-quote">"fine"</span>/&gt;
      <span class="code-tag">&lt;/properties&gt;</span>
   <span class="code-tag">&lt;/persistence-unit&gt;</span>

<span class="code-tag">&lt;/persistence&gt;</span></pre>
</div></div>

<p>By default, the persistence descriptor is named <em>persistence.xml</em> and is expected to be located on the classpath in the <em>META-INF</em> directory. If you want to place the <em>persistence.xml</em> file in another directory or name it differently, you can make a contribution to the <em>SymbolProvider</em> service, as shown in the following example. This is a quite useful feature if you want to use a different persistence descriptor for tests.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java"><span class="code-keyword">public</span> class AppModule {

    @Contribute(SymbolProvider.class)
    @FactoryDefaults
    <span class="code-keyword">public</span> <span class="code-keyword">static</span> void provideFactoryDefaults(<span class="code-keyword">final</span> MappedConfiguration&lt;<span class="code-object">String</span>, <span class="code-object">String</span>&gt; configuration) {
        configuration.add(JpaSymbols.PERSISTENCE_DESCRIPTOR, <span class="code-quote">"/org/example/persistence.xml"</span>);
    }

}</pre>
</div></div>

<h2><a name="IntegratingwithJPA-XMLlessJPAconfiguration"></a>XML-less JPA configuration</h2>

<p>With Tapestry, configuring JPA is much simpler than as described in the JPA specification. Tapestry allows you to configure the <a href="http://download.oracle.com/javaee/6/api/javax/persistence/EntityManagerFactory.html" class="external-link" rel="nofollow">EntityManagerFactory</a> programmatically, without writing any XML. Imagine you want to use JDBC connections managed by the container and provided through JNDI. The resulting persistence descriptor might look like this:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml"><span class="code-tag">&lt;?xml version=<span class="code-quote">"1.0"</span> encoding=<span class="code-quote">"UTF-8"</span>?&gt;</span>
&lt;persistence xmlns=<span class="code-quote">"http://java.sun.com/xml/ns/persistence"</span>
             version=<span class="code-quote">"2.0"</span>&gt;
   <span class="code-tag">&lt;persistence-unit name=<span class="code-quote">"JTAUnit"</span> transaction-type=<span class="code-quote">"RESOURCE_LOCAL"</span>&gt;</span>

      <span class="code-tag">&lt;non-jta-data-source&gt;</span>
         jdbc/JPATest
      <span class="code-tag">&lt;/non-jta-data-source&gt;</span>

      <span class="code-tag">&lt;properties&gt;</span>
         <span class="code-tag">&lt;property name=<span class="code-quote">"eclipselink.ddl-generation"</span> value=<span class="code-quote">"create-tables"</span>/&gt;</span>
         <span class="code-tag">&lt;property name=<span class="code-quote">"eclipselink.logging.level"</span> value=<span class="code-quote">"fine"</span>/&gt;</span>
      <span class="code-tag">&lt;/properties&gt;</span>
   <span class="code-tag">&lt;/persistence-unit&gt;</span>

<span class="code-tag">&lt;/persistence&gt;</span></pre>
</div></div>

<p>Now let's see how to provide the same configuration <em>without</em> XML. The following demonstrates an equivalent JPA configuration.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java"><span class="code-keyword">public</span> class AppModule {

   @Contribute(EntityManagerSource.class)
   <span class="code-keyword">public</span> <span class="code-keyword">static</span> void configurePersistenceUnitInfos(MappedConfiguration&lt;<span class="code-object">String</span>,PersistenceUnitConfigurer&gt; cfg) {

      PersistenceUnitConfigurer configurer = <span class="code-keyword">new</span> PersistenceUnitConfigurer() {

         <span class="code-keyword">public</span> void configure(TapestryPersistenceUnitInfo unitInfo) {

            unitInfo.nonJtaDataSource(<span class="code-quote">"jdbc/JPATest"</span>)
               .addProperty(<span class="code-quote">"eclipselink.ddl-generation"</span>, <span class="code-quote">"create-tables"</span>)
               .addProperty(<span class="code-quote">"eclipselink.logging.level"</span>, <span class="code-quote">"fine"</span>);
         }
     };

     cfg.add(<span class="code-quote">"JTAUnit"</span>, configurer);
   }
}</pre>
</div></div>

<p>In the example above you can see a contribution to the <em>EntityManagerSource</em> service. This service is responsible for creating the <a href="http://download.oracle.com/javaee/6/api/javax/persistence/EntityManagerFactory.html" class="external-link" rel="nofollow">EntityManagerFactory</a> to be used to create <a href="http://download.oracle.com/javaee/6/api/javax/persistence/EntityManager.html" class="external-link" rel="nofollow">EntityManager</a>. When the service is initialized, it parses the <em>persistence.xml</em> file, if available. For any persistence unit defined in the XML descriptor a <em>TapestryPersistenceUnitInfo</em> object is created. The <em>TapestryPersistenceUnitInfo</em> interface is a mutable extension of the <a href="http://download.oracle.com/javaee/6/api/javax/persistence/spi/PersistenceUnitInfo.html" class="external-link" rel="nofollow">PersistenceUnitInfo</a> interface (defined in the JPA specification) that allows you to configure a persistence unit programmatically.</p>

<p>After parsing the persistence descriptor, the EntityManagerSource service applies its configuration to create further persistence units and/or update the existing ones. The service’s configuration is a map in which persistence unit names are associated with <em>PersistenceUnitConfigurer</em> instances. A PersistenceUnitConfigurer is used to configure a persistence unit programmatically that has been associated with it. In the example above you can see a contribution providing a PersistenceUnitConfigurer for the unit named <em>JTAUnit</em>.</p>

<div class='panelMacro'><table class='infoMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="/confluence/images/icons/emoticons/information.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>Note that the TapestryPersistenceUnitInfo instance passed to the PersistenceUnitConfigurer is either empty or my contain the persistence unit metadata read from the persistence.xml file. What happens if you contribute a PersistenceUnitConfigurer for a persistence unit that has not been defined in the persistence.xml file? In this case Tapestry assumes that you want to configure the persistence unit programmatically and just creates a fresh <em>TapestryPersistenceUnitInfo</em> object and passes it to the <em>PersistenceUnitConfigurer</em>.</td></tr></table></div>

<h2><a name="IntegratingwithJPA-Automaticallyaddingmanagedclasses"></a>Automatically adding managed classes </h2>

<p>If only a single persistence unit is defined, Tapestry scans the  <em>application-root-package.entities</em> package. The classes in that package are automatically added as managed classes to the defined persistence unit.</p>

<p>If you have additional packages containing entities, you may contribute them to the <em>JpaEntityPackageManager</em> service configuration.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java"><span class="code-keyword">public</span> class AppModule {

   @Contribute(JpaEntityPackageManager.class)
   <span class="code-keyword">public</span> <span class="code-keyword">static</span> void providePackages(Configuration&lt;<span class="code-object">String</span>&gt; configuration) {

      configuration.add(<span class="code-quote">"org.example.myapp.domain"</span>);
      configuration.add(<span class="code-quote">"com.acme.model"</span>);
   }
}</pre>
</div></div>
<p>As you can see, you may add as many packages as you wish.</p>

<h1><a name="IntegratingwithJPA-InjectingtheEntityManager"></a>Injecting the EntityManager</h1>

<p>The created entity managers can be injected into page, component and other services.  </p>

<h2><a name="IntegratingwithJPA-InjectingtheEntityManagerintopageandcomponentclasses"></a>Injecting the EntityManager into page and component classes</h2>

<p>Depending on whether more than one persistence unit has been defined, the way to inject <a href="http://download.oracle.com/javaee/6/api/javax/persistence/EntityManager.html" class="external-link" rel="nofollow">EntityManager</a> varies slightly. Let’s start with a simple scenario, where only a single persistence unit is defined. In this case, an EntityManager can be injected using the @Inject annotation.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java"><span class="code-keyword">public</span> class CreateAddress {

   @Inject
   <span class="code-keyword">private</span> EntityManager entityManager;

   @Property
   <span class="code-keyword">private</span> Address address;

   @CommitAfter
   void onSuccess() {
      entityManager.persist(address);
   }
}</pre>
</div></div>

<p>Alternatively, you can use the @<a href="http://download.oracle.com/javaee/6/api/javax/persistence/PersistenceContext.html" class="external-link" rel="nofollow">PersistenceContext</a> annotation to get the EntityManager injected into a page or component, as shown in the following example.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java"><span class="code-keyword">public</span> class CreateAddress {

   @PersistenceContext
   <span class="code-keyword">private</span> EntityManager entityManager;

   @Property
   <span class="code-keyword">private</span> Address address;

   @CommitAfter
   void onSuccess() {
      entityManager.persist(address);
   }
}</pre>
</div></div>

<p>If you have multiple instances of persistence-unit defined in the same application, you need to explicitly tell Tapestry which persistence unit you want to get injected. This is what the @PersistenceContext annotation’s <em>name</em> attribute is used for?  The following example demonstrates how to inject the persistence unit named <em>DemoUnit</em>. </p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java"><span class="code-keyword">public</span> class CreateAddress {

   @PersistenceContext(unitName = <span class="code-quote">"DemoUnit"</span>)
   <span class="code-keyword">private</span> EntityManager entityManager;

   @Property
   <span class="code-keyword">private</span> Address address;

   @CommitAfter
   @PersistenceContext(unitName = <span class="code-quote">"DemoUnit"</span>)
   void onSuccess() {
      entityManager.persist(address);
   }
}</pre>
</div></div>

<h2><a name="IntegratingwithJPA-InjectingEntityManagerintoservices"></a>Injecting EntityManager into services</h2>

<p>While component injection occurs only on fields, the injection in the IoC layer may be triggered by a  field or a constructor. The following example demonstrates field injection, when a single persistence unit is defined in the persistence descriptor.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java"><span class="code-keyword">public</span> class UserDAOImpl <span class="code-keyword">implements</span> UserDAO {
   @Inject
   <span class="code-keyword">private</span> EntityManager entityManager;

   ...
}</pre>
</div></div>

<p>The constructor injection is demonstrated in the following example.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java"><span class="code-keyword">public</span> class UserDAOImpl <span class="code-keyword">implements</span> UserDAO {

   <span class="code-keyword">private</span> EntityManager entityManager;

   <span class="code-keyword">public</span> UserDAOImpl(EntityManager entityManager) {
      <span class="code-keyword">this</span>.entityManager = entityManager;
   }

   ...
}</pre>
</div></div>

<p>If multiple persistence units are defined in the same application, you need to disambiguate the unit to inject. This is done with the <a href="http://download.oracle.com/javaee/6/api/javax/persistence/PersistenceContext.html" class="external-link" rel="nofollow">@PersistenceContext</a> annotation, as shown in the following example. Because @PersistenceContext must not be placed on constructor parameters, you can’t use constructor injection and must switch to field injection.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java"><span class="code-keyword">public</span> class UserDAOImpl <span class="code-keyword">implements</span> UserDAO {
   @Inject
   @PersistenceContext(unitName = <span class="code-quote">"DemoUnit"</span>)
   <span class="code-keyword">private</span> EntityManager entityManager;

   ...
}</pre>
</div></div>

<h1><a name="IntegratingwithJPA-Transactionmanagement"></a>Transaction management</h1>

<p>As you may already know from the Hibernate integration library, Tapestry automatically manages transactions for you. The JPA integration library defines the @CommitAfter annotation, which acts as the correspondent annotation from the Hibernate integration library. Let’s explore the <em>UserDAO</em> interface to see the annotation in action.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java"><span class="code-keyword">public</span> <span class="code-keyword">interface</span> UserDAO {

   @CommitAfter
   @PersistenceContext(unitName = <span class="code-quote">"DemoUnit"</span>)
   void add(User user);

   List&lt;User&gt; findAll();

   @CommitAfter
   @PersistenceContext(unitName = <span class="code-quote">"DemoUnit"</span>)
   void delete(User... users);
}</pre>
</div></div>

<p>As you can see, the annotation may be placed on service method in order to mark that method as transactional. Any method marked with the @CommitAfter annotation will have a transaction started before, and committed after, it is called. Runtime exceptions thrown by by a transactional method will abort the transaction. Checked exceptions are ignored and the transaction will be committed anyway.</p>

<div class='panelMacro'><table class='warningMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="/confluence/images/icons/emoticons/forbidden.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>Note that <a href="http://download.oracle.com/javaee/6/api/javax/persistence/EntityTransaction.html" class="external-link" rel="nofollow">EntityTransaction</a> interface does not support two phase commits. Committing transactions of multiple EntityManagers in the same request might result in data consistency issues. That’s why @CommitAfter annotation must be accompanied by the @PersistenceContext annotation if multiple persistence unit are defined in an application. This way you can only commit the transaction of a single persistence unit. You should be very carefully, if you are committing multiple transactions manually in the same request.</td></tr></table></div>

<p>After placing the @CommitAfter annotation on methods, you need to tell Tapestry to advise those methods. This is accomplished by adding the transaction advice, as shown in the following example.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java"><span class="code-keyword">public</span> class AppModule {

   @Match(<span class="code-quote">"*DAO"</span>)
   <span class="code-keyword">public</span> <span class="code-keyword">static</span> void adviseTransactionally(
         JpaTransactionAdvisor advisor,
         MethodAdviceReceiver receiver) {

      advisor.addTransactionCommitAdvice(receiver);
   }
}</pre>
</div></div>
    </div>
        <div id="commentsSection" class="wiki-content pageSection">
        <div style="float: right;">
            <a href="https://cwiki.apache.org/confluence/users/viewnotifications.action" class="grey">Change Notification Preferences</a>
        </div>
        <a href="https://cwiki.apache.org/confluence/display/TAPESTRY/Integrating+with+JPA">View Online</a>
        |
        <a href="https://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=27361807&revisedVersion=7&originalVersion=6">View Changes</a>
            </div>
</div>
</div>
</div>
</div>
</body>
</html>

Mime
View raw message