You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@deltaspike.apache.org by gp...@apache.org on 2014/04/11 17:43:41 UTC

svn commit: r1586690 - /deltaspike/site/trunk/content/jpa.mdtext

Author: gpetracek
Date: Fri Apr 11 15:43:41 2014
New Revision: 1586690

URL: http://svn.apache.org/r1586690
Log:
updated content

Modified:
    deltaspike/site/trunk/content/jpa.mdtext

Modified: deltaspike/site/trunk/content/jpa.mdtext
URL: http://svn.apache.org/viewvc/deltaspike/site/trunk/content/jpa.mdtext?rev=1586690&r1=1586689&r2=1586690&view=diff
==============================================================================
--- deltaspike/site/trunk/content/jpa.mdtext (original)
+++ deltaspike/site/trunk/content/jpa.mdtext Fri Apr 11 15:43:41 2014
@@ -326,6 +326,105 @@ Producer for the default EntityManager w
         }
     }
 
+# Extended Persistence Contexts
+
+Frameworks like MyFaces Orchestra provide a feature which allows keeping an `EntityManager` across multiple requests. That means it isn't required to call `EntityManager#merge` to add detached entities to the context. However, several application architectures don't allow such an approach (due to different reasons like scalability). In theory that sounds nice and it works pretty well for small to medium sized projects esp. if an application doesn't rely on session replication in clusters. That also means that such an approach restricts your target environment from the very beginning. One of the base problems is that an `EntityManager` isn't serializable. Beans which are scoped in a normal-scoped CDI context have to be serializable. So by default it isn't allowed by CDI to provide a producer-method which exposes e.g. a conversation scoped `EntityManager` as it is. We **don't** recommend to use this approach and therefore it isn't available out-of-the-box. However, if you really need 
 this approach to avoid calling `#merge` for your detached entities, it's pretty simple to add this functionality.
+
+Usage of a simple `ExtendedEntityManager`
+
+    :::java
+    @Inject
+    private EntityManager entityManager;
+
+As you see the usage is the same. You **don't** have to use `ExtendedEntityManager` at the injection point. It's just needed in the producer-method:
+
+
+Producer for the default Extended-`EntityManager` (no EE-Server):
+
+    :::java
+    //...
+    public class ExtendedEntityManagerProducer
+    {
+        //or manual bootstrapping
+        @PersistenceContext
+        private EntityManager entityManager;
+
+        @Produces
+        @RequestScoped
+        protected ExtendedEntityManager createEntityManager()
+        {
+            return new ExtendedEntityManager(this.entityManager);
+        }
+
+        protected void closeEntityManager(@Disposes ExtendedEntityManager entityManager)
+        {
+            if (entityManager.isOpen())
+            {
+                entityManager.close();
+            }
+        }
+    }
+
+
+Producer for the default Extended-`EntityManager` (EE-Server):
+
+
+    :::java
+    @ApplicationScoped
+    public class ExtendedEntityManagerProducer
+    {
+        @PersistenceUnit
+        private EntityManagerFactory entityManagerFactory;
+
+        @Produces
+        @Default
+        @RequestScoped
+        public ExtendedEntityManager create()
+        {
+            return new ExtendedEntityManager(this.entityManagerFactory.createEntityManager());
+        }
+
+        public void dispose(@Disposes @Default ExtendedEntityManager entityManager)
+        {
+            if (entityManager.isOpen())
+            {
+                entityManager.close();
+            }
+        }
+    }
+
+
+Implementation of a simple `ExtendedEntityManager`:
+
+
+    :::java
+    @Typed()
+    public class ExtendedEntityManager implements EntityManager, Serializable
+    {
+        private static final long serialVersionUID = 3770954229283539616L;
+ 
+        private transient EntityManager wrapped;
+ 
+        protected ExtendedEntityManager()
+        {
+        }
+ 
+        public ExtendedEntityManager(EntityManager wrapped)
+        {
+            this.wrapped = wrapped;
+        }
+ 
+        /*
+         * generated
+         */
+        //delegate all calls to this.wrapped - most IDEs allow to generate it
+    }
+
+This approach just works if it **doesn't come to serialization** of this wrapper e.g. in case of session-replication.
+If those beans get serialized, you have to overcome this restriction by storing the persistence-unit-name and recreate the `EntityManager` via `Persistence.createEntityManagerFactory(this.persistenceUnitName).createEntityManager();` and sync it with the database before closing it on serialization.
+Furthermore, you have to intercept some methods of the `EntityManager` to merge detached entities automatically if those entities get serialized as well. However, as mentioned before **we don't recommend** such an approach.
+
+
 # JTA Support
 
 Per default the transaction-type used by `@Transactional`is 'RESOURCE_LOCAL'. If you configure `transaction-type="JTA"`in the persistence.xml, you have to enable an alternative `TransactionStrategy` in the beans.xml which is called `org.apache.deltaspike.jpa.impl.transaction.BeanManagedUserTransactionStrategy`.