{"id":1102,"date":"2010-11-26T20:25:11","date_gmt":"2010-11-26T20:25:11","guid":{"rendered":"http:\/\/salientsoft.co.uk\/?p=1102"},"modified":"2012-01-27T09:32:22","modified_gmt":"2012-01-27T09:32:22","slug":"using-container-managed-jpa-2-0-with-cdiejb-3-1glassfish-3","status":"publish","type":"post","link":"https:\/\/salientsoft.co.uk\/?p=1102","title":{"rendered":"Using container managed JPA 2.0 with CDI\/EJB 3.1\/Glassfish 3"},"content":{"rendered":"<p><u><strong>Update<\/strong><\/u><\/p>\n<ul>\n<li>One issue to be aware of, which is not immediately obvious, is when populating a database from scripts. If the <em>version<\/em> column is left null (Eclipselink leaves it as nullable by default), then the null value causes an immediate OptimisticLockException to be thrown. This is because EclipseLink expects and checks for a zero as the initial value for a new record. If EclipseLink itself persists the record, then it writes a zero. <\/li>\n<li>One good idea to resolve this would be to enforce version columns to be non null with a zero default \u2013 although it must be said that it would be helpful if EclipsLink did this automatically in response to the @Version annotation.<\/li>\n<li>Population scripts should therefore set version to zero, unless it is set non null with a default of zero in JPA \u2013 this latter solution is cleaner and would be automatic for me because I create version columns in a mapped superclass used by all Entities. I have yet to test this out however.<\/li>\n<\/ul>\n<p>&#160;<\/p>\n<p><strong><u>Original Post<\/u><\/strong><\/p>\n<p>This follows on from a <a href=\"http:\/\/salientsoft.co.uk\/?p=22\"><strong>previous post<\/strong><\/a> relating to JPA 1.0\/Glassfish 2.1, and contains a few notes and pointers relating to JPA 2.0 under Glassfish 3 with CDI\/Weld.<\/p>\n<p>Firstly, when using an EJB from a client, use CDI injection (@Inject) rather than the @EJB annotation, as CDI gives many additional benefits such as type safety.<\/p>\n<p>In an EJB:-<\/p>\n<ul>\n<li>You are using container managed transactions, and so simply have to inject an entity manager rather than create one from an entity manager factory. <\/li>\n<li>The container managed entity manager can be injected with a simple @PersistenceContext annotation \u2013 the persistence unit name may be defaulted and is discovered automatically. <\/li>\n<li>The container is responsible for entity manager lifetime\/closing. Calling e.g. <em>em.close<\/em> at the end of a bean method is illegal and will make Glassfish angry. <em>You do not want to make Glassfish angry<\/em> \u2013 you end up with many long stack traces in the log which on the surface do not appear to relate to this trivial problem! <\/li>\n<\/ul>\n<p>A major issue with container managed transactions is how to use optimistic locking and detect and handle optimistic lock exceptions correctly. This is detailed in <a title=\"http:\/\/books.google.com\/books?id=j84hdeHH2PYC&amp;lpg=PP1&amp;dq=Pro%20JPA%202&amp;pg=PA355#v=onepage&amp;q&amp;f=false\" href=\"http:\/\/books.google.com\/books?id=j84hdeHH2PYC&amp;lpg=PP1&amp;dq=Pro%20JPA%202&amp;pg=PA355#v=onepage&amp;q&amp;f=false\"><strong>Pro JPA 2, pages 355-357<\/strong><\/a> (you can preview this in Google Books). The main problem is that in a server environment, the <em>OptimisticLockException<\/em> will simply be logged by the container which then throws an <em>EJBException<\/em>. Trying to catch an <em>OptimisticLockException<\/em> in the calling client is therefore doomed to failure \u2013 it will probably never be caught!<\/p>\n<p>The solution is to call <em>flush() <\/em>on the entity manger (e.g. <em>em.flush())<\/em> just before you are ready to complete the method. This forces a write to the database, locking resources at the end of the method so that the effects on concurrency are minimised. This allows us to handle an optimistic failure while we are still in control, without the container swallowing the exception. The <em>ChangeCollisionException<\/em> might contain the object which caused the exception, but it is not guarranteed to. If there were multiple objects in the transaction, we could have invoked <em>getEntity() <\/em>on the caught exception to see whether the offending object was included.<\/p>\n<p>If we do get an exception from the <em>flush() <\/em>call, we can throw a domain specific application exception which the caller can recognise, i.e. convert an <em>OptimisticLockException<\/em> to our own <em>ChangeCollisionException<\/em>, avoiding coupling the caller to the internal semantics of JPA transactions. It is also desirable to factor out the code which calls <em>flush() <\/em>into our own method, e.g. <em>flushChanges()<\/em> to avoid the need for every method which needs to flush having to catch the optimistic lock exception and then throw our domain specific one \u2013 we can centralise the exception conversion in our own single method.<\/p>\n<p>We must annotate the <em>ChangeCollisionException<\/em> class with <em>@ApplicationException<\/em>, which is an EJB container annotation, to indicate to the container that the exception is not really a system level one but should be thrown back to the client as-is. Normally defining an application exception will cause the container not to roll back the transaction, but this is an EJB 3 container notion. The persistence provider that threw the <em>OptimisticLockException<\/em>&#160; (in this case Eclipselink) does not know about the special semantics of designated application exceptions and, seeing a runtime exception, will go ahead and mark the transaction for rollback. The client can now receive and handle the <em>ChangeCollisionException<\/em> and do something about it.<\/p>\n<p>Here is an example of our exception class with the required annotation:-<\/p>\n<p style=\"padding-left: 30px\">@ApplicationException   <br \/>public class ChangeCollisionException extends RunTimeException {    <br \/>&#160;&#160; public ChangeCollisionException() {super(); }    <br \/>}<\/p>\n<p>Here are code fragment examples from a stateless session bean showing the entity manager injection, and a client JSF model bean showing the CDI injection of the stateless session bean. Note that with EJB 3.1 it is not necessary to declare local or remote interfaces for an EJB as business interfaces are not a requirement. However, I always use an interface as it allows for example a mock version of a service layer to be easily swapped in for testing. CDI supports this conveniently via <em>alternatives<\/em>, whereby a mock version of a bean can be switched in via a setting in <em>beans.xml<\/em> for testing.<\/p>\n<p style=\"padding-left: 30px\">@Stateless   <br \/>public class SentryServiceImpl implements SentryServiceLocal {<\/p>\n<p style=\"padding-left: 30px\">&#160;&#160;&#160; @PersistenceContext   <br \/>&#160;&#160;&#160; private EntityManager em;    <br \/>\u2026    <br \/>}<\/p>\n<p style=\"padding-left: 30px\">@Named   <br \/>@Dependent    <br \/>public class ModelBeanImpl implements ModelBean, Serializable {    <br \/>&#160;&#160;&#160; private static final long serialVersionUID = -366401344661990776L;    <br \/>&#160;&#160;&#160; private @Inject SentryServiceLocal sentryService;    <br \/>\u2026&#160; <br \/>}<\/p>\n<p>With container managed JPA and\/or Glassfish your <em>persistence.xml<\/em>&#160; can also be simplified, as you can define your data source in Glassfish rather than explicitly in <em>persistence.xml<\/em>, as described <a href=\"http:\/\/salientsoft.co.uk\/?p=22\"><strong>here<\/strong><\/a>.<\/p>\n<p>Note that when defining a data source directly in <em>persistence.xml,<\/em>&#160; some property names have been standardized for JPA 2.0, so have changed from e.g. <em>eclipselink.jdbc.user <\/em>to <em>javax.persistence.jdbcuser. <\/em>The following properties in persistence.xml are now standard:-<\/p>\n<p style=\"padding-left: 30px\">&lt;property name=&quot;javax.persistence.jdbc.url&quot; value=&quot;jdbc:oracle:thin:@localhost:1521:xe&quot;\/&gt;   <br \/>&lt;property name=&quot;javax.persistence.jdbc.user&quot; value=&quot;sentry&quot;\/&gt;    <br \/>&lt;property name=&quot;javax.persistence.jdbc.password&quot; value=&quot;sentry&quot;\/&gt;    <br \/>&lt;property name=&quot;javax.persistence.jdbc.driver&quot; value=&quot;oracle.jdbc.OracleDriver&quot;\/&gt;<\/p>\n<p>An example <em>persistence.xml<\/em> used under JPA 2.0 follows:-<\/p>\n<p style=\"padding-left: 30px\">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;   <br \/>&lt;persistence version=&quot;2.0&quot;    <br \/>xmlns=&quot;<a href=\"http:\/\/java.sun.com\/xml\/ns\/persistence&quot;\">http:\/\/java.sun.com\/xml\/ns\/persistence&quot;<\/a>    <br \/>&#160; xmlns:xsi=&quot;<a href=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance&quot;\">http:\/\/www.w3.org\/2001\/XMLSchema-instance&quot;<\/a>    <br \/>&#160; xsi:schemaLocation=&quot;<a href=\"http:\/\/java.sun.com\/xml\/ns\/persistence\">http:\/\/java.sun.com\/xml\/ns\/persistence<\/a> <a href=\"http:\/\/java.sun.com\/xml\/ns\/persistence\/persistence_2_0.xsd&quot;\">http:\/\/java.sun.com\/xml\/ns\/persistence\/persistence_2_0.xsd&quot;<\/a>&gt;<\/p>\n<p style=\"padding-left: 30px\">&#160;&#160;&#160; &lt;persistence-unit name=&quot;SentryPrototype&quot; transaction-type=&quot;JTA&quot;&gt;   <br \/>&#160;&#160;&#160;&#160;&#160; &lt;provider&gt;org.eclipse.persistence.jpa.PersistenceProvider&lt;\/provider&gt;    <br \/>&#160;&#160;&#160;&#160;&#160; &lt;jta-data-source&gt;jdbc\/SentryPool&lt;\/jta-data-source&gt;    <br \/>&#160;&#160;&#160;&#160;&#160; &lt;properties&gt;    <br \/>&#160;&#160;&#160;&#160;&#160;&#160; &lt;property name=&quot;eclipselink.logging.level&quot; value=&quot;INFO&quot; \/&gt;    <br \/>&#160;&#160;&#160;&#160;&#160;&#160; &lt;property name=&quot;eclipselink.target-database&quot; value=&quot;Oracle&quot; \/&gt;&#160;&#160;&#160;&#160;&#160;&#160; <br \/>&#160;&#160;&#160;&#160;&#160;&#160; &lt;property name=&quot;eclipselink.ddl-generation.output-mode&quot; value=&quot;database&quot; \/&gt;&#160;&#160;&#160;&#160;&#160;&#160; <br \/>&#160;&#160;&#160;&#160;&#160; &lt;\/properties&gt;    <br \/>&#160;&#160;&#160;&#160; &lt;\/persistence-unit&gt;    <br \/>&lt;\/persistence&gt;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Update One issue to be aware of, which is not immediately obvious, is when populating a database from scripts. If the version column is left null (Eclipselink leaves it as nullable by default), then the null value causes an immediate OptimisticLockException to be thrown. This is because EclipseLink expects and checks for a zero as [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[8],"tags":[110,18,10,40,182,16,15],"_links":{"self":[{"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/1102"}],"collection":[{"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1102"}],"version-history":[{"count":10,"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/1102\/revisions"}],"predecessor-version":[{"id":1105,"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/1102\/revisions\/1105"}],"wp:attachment":[{"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1102"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1102"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1102"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}