Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 780FE200B57 for ; Sat, 6 Aug 2016 15:46:35 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id 76CCC160AAA; Sat, 6 Aug 2016 13:46:35 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 5D960160A7C for ; Sat, 6 Aug 2016 15:46:33 +0200 (CEST) Received: (qmail 63069 invoked by uid 500); 6 Aug 2016 13:46:32 -0000 Mailing-List: contact commits-help@deltaspike.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@deltaspike.apache.org Delivered-To: mailing list commits@deltaspike.apache.org Received: (qmail 63060 invoked by uid 99); 6 Aug 2016 13:46:32 -0000 Received: from pnap-us-west-generic-nat.apache.org (HELO spamd3-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 06 Aug 2016 13:46:32 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd3-us-west.apache.org (ASF Mail Server at spamd3-us-west.apache.org) with ESMTP id 0AB4E18642E for ; Sat, 6 Aug 2016 13:46:32 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd3-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: -0.426 X-Spam-Level: X-Spam-Status: No, score=-0.426 tagged_above=-999 required=6.31 tests=[KAM_LAZY_DOMAIN_SECURITY=1, RP_MATCHES_RCVD=-1.426] autolearn=disabled Received: from mx1-lw-us.apache.org ([10.40.0.8]) by localhost (spamd3-us-west.apache.org [10.40.0.10]) (amavisd-new, port 10024) with ESMTP id ycA1ubwb-yaw for ; Sat, 6 Aug 2016 13:46:19 +0000 (UTC) Received: from mailrelay1-us-west.apache.org (mailrelay1-us-west.apache.org [209.188.14.139]) by mx1-lw-us.apache.org (ASF Mail Server at mx1-lw-us.apache.org) with ESMTP id 17A365F1F6 for ; Sat, 6 Aug 2016 13:46:19 +0000 (UTC) Received: from svn01-us-west.apache.org (svn.apache.org [10.41.0.6]) by mailrelay1-us-west.apache.org (ASF Mail Server at mailrelay1-us-west.apache.org) with ESMTP id 6CED0E546A for ; Sat, 6 Aug 2016 13:46:17 +0000 (UTC) Received: from svn01-us-west.apache.org (localhost [127.0.0.1]) by svn01-us-west.apache.org (ASF Mail Server at svn01-us-west.apache.org) with ESMTP id 4B93F3A2B4E for ; Sat, 6 Aug 2016 13:46:17 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1755397 [9/18] - /deltaspike/site/trunk/content/documentation/ Date: Sat, 06 Aug 2016 13:46:16 -0000 To: commits@deltaspike.apache.org From: rmannibucau@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20160806134617.4B93F3A2B4E@svn01-us-west.apache.org> archived-at: Sat, 06 Aug 2016 13:46:35 -0000 Modified: deltaspike/site/trunk/content/documentation/jpa.html URL: http://svn.apache.org/viewvc/deltaspike/site/trunk/content/documentation/jpa.html?rev=1755397&r1=1755396&r2=1755397&view=diff ============================================================================== --- deltaspike/site/trunk/content/documentation/jpa.html (original) +++ deltaspike/site/trunk/content/documentation/jpa.html Sat Aug 6 13:46:15 2016 @@ -1,987 +1,989 @@ - - - - - - - - - - - - - JPA Module - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - -
-
-

JPA Module

-
- -
-
-

Overview

-
-
-

The JPA module provides a transactional context and scope, enabling execution of methods within transactions.

-
-
-
-
-

Project Setup

-
-
-

The configuration information provided here is for Maven-based projects and it assumes that you have already declared the DeltaSpike version and DeltaSpike Core module for your projects, as detailed in Configure DeltaSpike in Your Projects. For Maven-independent projects, see Configure DeltaSpike in Maven-independent Projects.

-
-
-

1. Declare JPA Module Dependencies

-
-

Add the JPA module to the list of dependencies in the project pom.xml file using this code snippet:

-
-
-
-
<dependency>
-    <groupId>org.apache.deltaspike.modules</groupId>
-    <artifactId>deltaspike-jpa-module-api</artifactId>
-    <version>${deltaspike.version}</version>
-    <scope>compile</scope>
-</dependency>
-
-<dependency>
-    <groupId>org.apache.deltaspike.modules</groupId>
-    <artifactId>deltaspike-jpa-module-impl</artifactId>
-    <version>${deltaspike.version}</version>
-    <scope>runtime</scope>
-</dependency>
-
-
-
-

Or if you’re using Gradle, add these dependencies to your build.gradle:

-
-
-
-
     runtime 'org.apache.deltaspike.modules:deltaspike-jpa-module-impl'
-     compile 'org.apache.deltaspike.modules:deltaspike-jpa-module-api'
-
-
-
-
-

2. (Optional) Enable the Transaction Interceptor

-
- - - - - -
- - -If you are using CDI 1.0 or CDI 1.1+ with DeltaSpike v1.1.0 and earlier, you must enable the transaction interceptor in the project beans.xml file: -
-
-
-
-
<beans>
-    <!-- Not needed with CDI 1.1+ and DeltaSpike v1.1.1+ -->
-    <interceptors>
-        <class>org.apache.deltaspike.jpa.impl.transaction.TransactionalInterceptor</class>
-    </interceptors>
-</beans>
-
-
-
-
-
-
-

@Transactional

-
-
-

This annotation is an alternative to transactional EJBs and enables the execution -of a method within a transaction. Before it is possible to start -using the annotation, it is required to implement a CDI producer for an -EntityManager and it is needed to inject the EntityManager in the -bean which uses @Transactional. As shown later on, it is also possible -to use multiple qualifiers for using different EntityManagers.

-
-
-

Basic usage

-
-

The following example shows a simple producer for an EntityManager and -the corresponding disposer method. Producing it as request scoped bean -means that the disposer method will be called on finishing the request. -Alternatively it is possible to use a special scope called -@TransactionScoped.

-
-
-
Producer for the Default EntityManager (non-EE server)
-
-
//...
-public class EntityManagerProducer
-{
-    //or manual bootstrapping
-    @PersistenceContext
-    private EntityManager entityManager;
-
-    @Produces
-    @RequestScoped
-    protected EntityManager createEntityManager()
-    {
-        return this.entityManager;
-    }
-
-    protected void closeEntityManager(@Disposes EntityManager entityManager)
-    {
-        if (entityManager.isOpen())
-        {
-            entityManager.close();
-        }
-    }
-}
-
-
-
-
Producer for the Default EntityManager (EE server)
-
-
@ApplicationScoped
-public class EntityManagerProducer
-{
-    @PersistenceUnit
-    private EntityManagerFactory entityManagerFactory;
-
-    @Produces
-    @Default
-    @RequestScoped
-    public EntityManager create()
-    {
-        return this.entityManagerFactory.createEntityManager();
-    }
-
-    public void dispose(@Disposes @Default EntityManager entityManager)
-    {
-        if (entityManager.isOpen())
-        {
-            entityManager.close();
-        }
-    }
-}
-
-
-
-

The following examples show how to use the EntityManager produced by -the example above.

-
-
-
Bean with a Transactional Method
-
-
//...
-public class TransactionalBean
-{
-    @Inject
-    private EntityManager entityManager;
-
-    @Transactional
-    public void executeInTransaction()
-    {
-        //...
-    }
-}
-
-
-
-
Simple Transactional Bean (All Methods are Transactional)
-
-
//...
-@Transactional
-public class TransactionalBean
-{
-    @Inject
-    private EntityManager entityManager;
-
-    //...
-}
-
-
-
-

As illustrated in the following example it is also possible to use -@Transactional for stereotypes.

-
-
-
Stereotype for Transactional Beans (+ Usage)
-
-
@Stereotype
-@Transactional
-@ApplicationScoped
-public @interface Repository
-{
-}
-
-//...
-@Repository
-public class TransactionalBean
-{
-    @Inject
-    private EntityManager entityManager;
-
-    //...
-}
-
-
-
-
-

Multiple EntityManagers

-
-

The default qualifier for @Transactional is @Any whereby a transaction gets started for every injected entity manager. Besides such simple usages, it is also possible to access multiple persistence units in parallel using qualifiers.

-
-
-

First, the EntityManagers or EntityManagerFactories must be obtained from the JPA subsystem, then EntityManagers must be made available as CDI beans and finally injected into @Transactional beans for usage.

-
-
-

Obtaining EntityManagers from JPA

-
-

In EE managed environments the EntityManager can be obtained directly or through an EntityManagerFactory using standard JPA annotations @PersistenceContext for an EntityManager or @PersistenceUnit for an EntityManagerFactory.

-
-
-
JPA Managed EntityManager
-
-
public class EntityManagerProducer {
-
-    @PersistenceContext(unitName = "firstDB")
-    private EntityManager firstEntityManager;
-
-    @PersistenceContext(unitName = "secondDB")
-    private EntityManager secondEntityManager;
-
-    // ...
-}
-
-
-
-

An alternative for non-EE environments is available through DeltaSpike’s @PersistenceUnitName qualifier allowing to inject EntityManagerFactories.

-
-
-
Unmanaged EntityManagerFactory
-
-
public class EntityManagerProducer {
-
-    @Inject
-    @PersistenceUnitName("puA")
-    private EntityManagerFactory emfA;
-
-    @Inject
-    @PersistenceUnitName("puB")
-    private EntityManagerFactory emfB;
-
-    // ...
-}
-
-
-
-

Obtaining an EntityManager from an EntityManagerFactory is just a matter of calling emfA.createEntityManager(). -DeltaSpike provides a built-in producer for @PersistenceUnitName qualified EntityManagerFactories. -This producer also looks up a property files with the name persistence-{persistenceunit name}.properties via the DeltaSpike PropertyLoader. -For the example above this would be persistence-puA.properties. -The properties in this file will be passed 1:1 to Persistence#createEntityManagerFactory(properties) by the built-in producer method.

-
-
-
-

Producing Multiple EntityManagers

-
-

There are several ways to make multiple entity managers available for use in @Transactional methods, each suitable for a different situation.

-
-
-

The simplest method employs a producer and a disposer for each EntityManager.

-
-
-
Deciding using qualifiers
-
-
public class EntityManagerProducer {
-
-    // ...entity managers or factories injected here
-
-    @Produces
-    @RequestScoped // or other
-    @DbA //custom qualifier annotation
-    public EntityManager createEntityManagerA()
-    {
-        return emfA.createEntityManager();
-    }
-
-    public void closeEmA(@Disposes @DbA EntityManager em)
-    {
-        em.close();
-    }
-
-    @Produces
-    @RequestScoped
-    @DbB //custom qualifier annotation
-    public EntityManager createEntityManagerB()
-    {
-        return emfB.createEntityManager();
-    }
-
-    public void closeEmB(@Disposes @DbB EntityManager em)
-    {
-        em.close();
-    }
-
-}
-
-
-
-

If there’s the need to decide dynamically on which EntityManager should be used when it’s possible to use the standard CDI facility of InjectionPoint to get information about the injection points and produce different EntityManagers with just one producer method.

-
-
-
Deciding using InjectionPoint
-
-
public class EntityManagerProducer {
-
-    // ...entity managers or factories injected here
-
-    @Produces
-    protected EntityManager createEntityManager(InjectionPoint injectionPoint)
-    {
-        CustomQualifier customQualifier = injectionPoint.getAnnotated().getAnnotation(CustomQualifier.class);
-        return selectEntityManager(customQualifier); //selects firstEntityManager or secondEntityManager based on the details provided by CustomQualifier
-    }
-}
-
-
-
-

The information necessary to make the decision about the EntityManager appropriate for the current situation and injection point may be available elsewhere, for example in a custom context.

-
-
-
Deciding using anything else
-
-
public class EntityManagerProducer {
-
-    // ...entity managers or factories injected here
-
-    @Inject
-    private CustomDatabaseContext customDatabaseContext;
-
-    @Produces
-    protected EntityManager createEntityManager()
-    {
-        if (customDatabaseContext.usePrimaryDb()) {
-            return firstEntityManager;
-        }
-        return secondEntityManager;
-    }
-}
-
-
-
-
-

Using transactions with multiple EntityManagers

-
-

One use case for multiple EntityManagers is their usage in nested transactions. When a transactional method is called from within a transactional method, it joins the existing transaction.

-
-
-
Nested transactions with multiple EntityManagers
-
-
public class FirstLevelTransactionBean
-{
-    @Inject
-    private @First EntityManager firstEntityManager;
-
-    @Inject
-    private NestedTransactionBean nestedTransactionBean;
-
-    @Transactional
-    public void executeInTransaction()
-    {
-        //...
-        this.nestedTransactionBean.executeInTransaction();
-    }
-}
-
-public class NestedTransactionBean
-{
-    @Inject
-    private @Second EntityManager secondEntityManager;
-
-    @Transactional
-    public void executeInTransaction()
-    {
-        //...
-    }
-}
-
-
-
-

It’s also easy to use multiple EntityManagers in the same bean in different transactional methods. By default, a @Transactional method would enroll all of the EntityManagers in the transaction. By using @Transactional(qualifier=…​) it’s easy to choose individual EntityManagers for each transactional method.

-
-
-
Selecting individual EntityManagers for a transactional method
-
-
public class MultiTransactionBean
-{
-    @Inject
-    private EntityManager defaultEntityManager;
-
-    @Inject
-    private @First EntityManager firstEntityManager;
-
-    @Inject
-    private @Second EntityManager secondEntityManager;
-
-    @Transactional(qualifier = Default.class)
-    public void executeInDefaultTransaction() {...}
-
-    @Transactional(qualifier = First.class)
-    public void executeInFirstTransaction() {...}
-
-    @Transactional(qualifier = {First.class, Second.class})
-    public void executeInFirstAndSecondTransaction() {...}
-}
-
-
-
-

The final transaction handling for all EntityManager s is also done -after the outermost transactional method if NestedTransactionBean uses -a different EntityManager. So it is possible to catch an exception in -FirstLevelTransactionBean, for example, to try an optional path instead of an -immediate rollback.

-
-
-
-
-
-
-

@TransactionScoped

-
-
-

@Transactional also starts a context which is available as long as the -transaction started by @Transactional. Besides other beans you can use -this scope for the EntityManager itself. That means the -EntityManager will be closed after leaving the method annotated with -@Transactional.

-
-
-
Using a transaction-scoped EntityManager
-
-
public class EntityManagerProducer
-{
-    //or manual bootstrapping
-    @PersistenceContext
-    private EntityManager entityManager;
-
-    @Produces
-    @TransactionScoped
-    protected EntityManager createEntityManager()
-    {
-        return this.entityManager;
-    }
-
-    protected void closeEntityManager(@Disposes EntityManager entityManager)
-    {
-        if (entityManager.isOpen())
-        {
-            entityManager.close();
-        }
-    }
-}
-
-
-
-
-
-

Extended Persistence Contexts

-
-
-

Frameworks like MyFaces Orchestra provide a feature which allows keeping -an EntityManager across multiple requests. That means it is not -required to call EntityManager#merge to add detached entities to the -context. However, several application architectures do not 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 -especially if an application does not 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 is not serializable. Beans which are scoped in a -normal-scoped CDI context have to be serializable. So by default it -is not allowed by CDI to provide a producer-method which exposes, for example, a -conversation scoped EntityManager as it is. We do not recommend this approach and therefore it is not available out-of-the-box. -However, if you really need this approach to avoid calling #merge for -your detached entities, it is pretty simple to add this functionality.

-
-
-
Usage of a Simple extended EntityManager
-
-
@Inject
-private EntityManager entityManager;
-
-
-
-

As you see the usage is the same. You do not have to use -ExtendedEntityManager at the injection point. It is just needed in the -producer-method:

-
-
-
Producer for an extended EntityManager (non-EE server)
-
-
//...
-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 an extended EntityManager (EE server)
-
-
@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 extended EntityManager
-
-
@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 does not come to serialization of this -wrapper, for example 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 do not recommend -such an approach.

-
-
-
-
-

JTA Support

-
-
-

By default the transaction-type used by @Transactional is -RESOURCE_LOCAL. If you configure transaction-type="JTA" in the -persistence.xml file, you have to enable an alternative TransactionStrategy -in the beans.xml which is called -org.apache.deltaspike.jpa.impl.transaction.BeanManagedUserTransactionStrategy.

-
-
-
-
<beans>
-    <alternatives>
-        <class>org.apache.deltaspike.jpa.impl.transaction.BeanManagedUserTransactionStrategy</class>
-    </alternatives>
-</beans>
-
-
-
-

Alternatively, you may expect that your transactions are started at a higher level, e.g. you’re exposing a REST API -and the endpoints themselves are either @Transactional or Stateless session beans, either with container managed -Transactions, you would use org.apache.deltaspike.jpa.impl.transaction.ContainerManagedTransactionStrategy. This -is the strategy to use if you are leveraging @PersistenceContext to inject your EntityManager.

-
-
-

If you have multiple persistence units and you have to use both -transaction types or the settings for development have to be different -than the production settings, you can use -org.apache.deltaspike.jpa.impl.transaction.EnvironmentAwareTransactionStrategy -instead.

-
-
- - - - - -
- - -In case of some versions of Weld (or OpenWebBeans in BDA mode), you have -to configure it as a global alternative instead of an alternative in -beans.xml. That means you have to add, for example, -globalAlternatives.org.apache.deltaspike.jpa.spi.transaction.TransactionStrategy -=org.apache.deltaspike.jpa.impl.transaction.BeanManagedUserTransactionStrategy -to /META-INF/apache-deltaspike.properties. -
-
-
-
-
-
- - - - - -
-
-
-
-

Copyright © 2011-2016 The Apache Software Foundation, - Licensed under the Apache License, Version 2.0.

- -

Apache and the Apache feather logo are trademarks of The Apache Software Foundation.

-
-
-
- - + + + + + + + + + + + + + JPA Module + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+
+

JPA Module

+
+ +
+
+

Overview

+
+
+

The JPA module provides a transactional context and scope, enabling execution of methods within transactions.

+
+
+
+
+

Project Setup

+
+
+

The configuration information provided here is for Maven-based projects and it assumes that you have already declared the DeltaSpike version and DeltaSpike Core module for your projects, as detailed in Configure DeltaSpike in Your Projects. For Maven-independent projects, see Configure DeltaSpike in Maven-independent Projects.

+
+
+

1. Declare JPA Module Dependencies

+
+

Add the JPA module to the list of dependencies in the project pom.xml file using this code snippet:

+
+
+
+
<dependency>
+    <groupId>org.apache.deltaspike.modules</groupId>
+    <artifactId>deltaspike-jpa-module-api</artifactId>
+    <version>${deltaspike.version}</version>
+    <scope>compile</scope>
+</dependency>
+
+<dependency>
+    <groupId>org.apache.deltaspike.modules</groupId>
+    <artifactId>deltaspike-jpa-module-impl</artifactId>
+    <version>${deltaspike.version}</version>
+    <scope>runtime</scope>
+</dependency>
+
+
+
+

Or if you’re using Gradle, add these dependencies to your build.gradle:

+
+
+
+
     runtime 'org.apache.deltaspike.modules:deltaspike-jpa-module-impl'
+     compile 'org.apache.deltaspike.modules:deltaspike-jpa-module-api'
+
+
+
+
+

2. (Optional) Enable the Transaction Interceptor

+
+ + + + + +
+ + +If you are using CDI 1.0 or CDI 1.1+ with DeltaSpike v1.1.0 and earlier, you must enable the transaction interceptor in the project beans.xml file: +
+
+
+
+
<beans>
+    <!-- Not needed with CDI 1.1+ and DeltaSpike v1.1.1+ -->
+    <interceptors>
+        <class>org.apache.deltaspike.jpa.impl.transaction.TransactionalInterceptor</class>
+    </interceptors>
+</beans>
+
+
+
+
+
+
+

@Transactional

+
+
+

This annotation is an alternative to transactional EJBs and enables the execution +of a method within a transaction. Before it is possible to start +using the annotation, it is required to implement a CDI producer for an +EntityManager and it is needed to inject the EntityManager in the +bean which uses @Transactional. As shown later on, it is also possible +to use multiple qualifiers for using different EntityManagers.

+
+
+

Basic usage

+
+

The following example shows a simple producer for an EntityManager and +the corresponding disposer method. Producing it as request scoped bean +means that the disposer method will be called on finishing the request. +Alternatively it is possible to use a special scope called +@TransactionScoped.

+
+
+
Producer for the Default EntityManager (non-EE server)
+
+
//...
+public class EntityManagerProducer
+{
+    //or manual bootstrapping
+    @PersistenceContext
+    private EntityManager entityManager;
+
+    @Produces
+    @RequestScoped
+    protected EntityManager createEntityManager()
+    {
+        return this.entityManager;
+    }
+
+    protected void closeEntityManager(@Disposes EntityManager entityManager)
+    {
+        if (entityManager.isOpen())
+        {
+            entityManager.close();
+        }
+    }
+}
+
+
+
+
Producer for the Default EntityManager (EE server)
+
+
@ApplicationScoped
+public class EntityManagerProducer
+{
+    @PersistenceUnit
+    private EntityManagerFactory entityManagerFactory;
+
+    @Produces
+    @Default
+    @RequestScoped
+    public EntityManager create()
+    {
+        return this.entityManagerFactory.createEntityManager();
+    }
+
+    public void dispose(@Disposes @Default EntityManager entityManager)
+    {
+        if (entityManager.isOpen())
+        {
+            entityManager.close();
+        }
+    }
+}
+
+
+
+

The following examples show how to use the EntityManager produced by +the example above.

+
+
+
Bean with a Transactional Method
+
+
//...
+public class TransactionalBean
+{
+    @Inject
+    private EntityManager entityManager;
+
+    @Transactional
+    public void executeInTransaction()
+    {
+        //...
+    }
+}
+
+
+
+
Simple Transactional Bean (All Methods are Transactional)
+
+
//...
+@Transactional
+public class TransactionalBean
+{
+    @Inject
+    private EntityManager entityManager;
+
+    //...
+}
+
+
+
+

As illustrated in the following example it is also possible to use +@Transactional for stereotypes.

+
+
+
Stereotype for Transactional Beans (+ Usage)
+
+
@Stereotype
+@Transactional
+@ApplicationScoped
+public @interface Repository
+{
+}
+
+//...
+@Repository
+public class TransactionalBean
+{
+    @Inject
+    private EntityManager entityManager;
+
+    //...
+}
+
+
+
+
+

Multiple EntityManagers

+
+

The default qualifier for @Transactional is @Any whereby a transaction gets started for every injected entity manager. Besides such simple usages, it is also possible to access multiple persistence units in parallel using qualifiers.

+
+
+

First, the EntityManagers or EntityManagerFactories must be obtained from the JPA subsystem, then EntityManagers must be made available as CDI beans and finally injected into @Transactional beans for usage.

+
+
+

Obtaining EntityManagers from JPA

+
+

In EE managed environments the EntityManager can be obtained directly or through an EntityManagerFactory using standard JPA annotations @PersistenceContext for an EntityManager or @PersistenceUnit for an EntityManagerFactory.

+
+
+
JPA Managed EntityManager
+
+
public class EntityManagerProducer {
+
+    @PersistenceContext(unitName = "firstDB")
+    private EntityManager firstEntityManager;
+
+    @PersistenceContext(unitName = "secondDB")
+    private EntityManager secondEntityManager;
+
+    // ...
+}
+
+
+
+

An alternative for non-EE environments is available through DeltaSpike’s @PersistenceUnitName qualifier allowing to inject EntityManagerFactories.

+
+
+
Unmanaged EntityManagerFactory
+
+
public class EntityManagerProducer {
+
+    @Inject
+    @PersistenceUnitName("puA")
+    private EntityManagerFactory emfA;
+
+    @Inject
+    @PersistenceUnitName("puB")
+    private EntityManagerFactory emfB;
+
+    // ...
+}
+
+
+
+

Obtaining an EntityManager from an EntityManagerFactory is just a matter of calling emfA.createEntityManager(). +DeltaSpike provides a built-in producer for @PersistenceUnitName qualified EntityManagerFactories. +This producer also looks up a property files with the name persistence-{persistenceunit name}.properties via the DeltaSpike PropertyLoader. +For the example above this would be persistence-puA.properties. +The properties in this file will be passed 1:1 to Persistence#createEntityManagerFactory(properties) by the built-in producer method.

+
+
+
+

Producing Multiple EntityManagers

+
+

There are several ways to make multiple entity managers available for use in @Transactional methods, each suitable for a different situation.

+
+
+

The simplest method employs a producer and a disposer for each EntityManager.

+
+
+
Deciding using qualifiers
+
+
public class EntityManagerProducer {
+
+    // ...entity managers or factories injected here
+
+    @Produces
+    @RequestScoped // or other
+    @DbA //custom qualifier annotation
+    public EntityManager createEntityManagerA()
+    {
+        return emfA.createEntityManager();
+    }
+
+    public void closeEmA(@Disposes @DbA EntityManager em)
+    {
+        em.close();
+    }
+
+    @Produces
+    @RequestScoped
+    @DbB //custom qualifier annotation
+    public EntityManager createEntityManagerB()
+    {
+        return emfB.createEntityManager();
+    }
+
+    public void closeEmB(@Disposes @DbB EntityManager em)
+    {
+        em.close();
+    }
+
+}
+
+
+
+

If there’s the need to decide dynamically on which EntityManager should be used when it’s possible to use the standard CDI facility of InjectionPoint to get information about the injection points and produce different EntityManagers with just one producer method.

+
+
+
Deciding using InjectionPoint
+
+
public class EntityManagerProducer {
+
+    // ...entity managers or factories injected here
+
+    @Produces
+    protected EntityManager createEntityManager(InjectionPoint injectionPoint)
+    {
+        CustomQualifier customQualifier = injectionPoint.getAnnotated().getAnnotation(CustomQualifier.class);
+        return selectEntityManager(customQualifier); //selects firstEntityManager or secondEntityManager based on the details provided by CustomQualifier
+    }
+}
+
+
+
+

The information necessary to make the decision about the EntityManager appropriate for the current situation and injection point may be available elsewhere, for example in a custom context.

+
+
+
Deciding using anything else
+
+
public class EntityManagerProducer {
+
+    // ...entity managers or factories injected here
+
+    @Inject
+    private CustomDatabaseContext customDatabaseContext;
+
+    @Produces
+    protected EntityManager createEntityManager()
+    {
+        if (customDatabaseContext.usePrimaryDb()) {
+            return firstEntityManager;
+        }
+        return secondEntityManager;
+    }
+}
+
+
+
+
+

Using transactions with multiple EntityManagers

+
+

One use case for multiple EntityManagers is their usage in nested transactions. When a transactional method is called from within a transactional method, it joins the existing transaction.

+
+
+
Nested transactions with multiple EntityManagers
+
+
public class FirstLevelTransactionBean
+{
+    @Inject
+    private @First EntityManager firstEntityManager;
+
+    @Inject
+    private NestedTransactionBean nestedTransactionBean;
+
+    @Transactional
+    public void executeInTransaction()
+    {
+        //...
+        this.nestedTransactionBean.executeInTransaction();
+    }
+}
+
+public class NestedTransactionBean
+{
+    @Inject
+    private @Second EntityManager secondEntityManager;
+
+    @Transactional
+    public void executeInTransaction()
+    {
+        //...
+    }
+}
+
+
+
+

It’s also easy to use multiple EntityManagers in the same bean in different transactional methods. By default, a @Transactional method would enroll all of the EntityManagers in the transaction. By using @Transactional(qualifier=…​) it’s easy to choose individual EntityManagers for each transactional method.

+
+
+
Selecting individual EntityManagers for a transactional method
+
+
public class MultiTransactionBean
+{
+    @Inject
+    private EntityManager defaultEntityManager;
+
+    @Inject
+    private @First EntityManager firstEntityManager;
+
+    @Inject
+    private @Second EntityManager secondEntityManager;
+
+    @Transactional(qualifier = Default.class)
+    public void executeInDefaultTransaction() {...}
+
+    @Transactional(qualifier = First.class)
+    public void executeInFirstTransaction() {...}
+
+    @Transactional(qualifier = {First.class, Second.class})
+    public void executeInFirstAndSecondTransaction() {...}
+}
+
+
+
+

The final transaction handling for all EntityManager s is also done +after the outermost transactional method if NestedTransactionBean uses +a different EntityManager. So it is possible to catch an exception in +FirstLevelTransactionBean, for example, to try an optional path instead of an +immediate rollback.

+
+
+
+
+
+
+

@TransactionScoped

+
+
+

@Transactional also starts a context which is available as long as the +transaction started by @Transactional. Besides other beans you can use +this scope for the EntityManager itself. That means the +EntityManager will be closed after leaving the method annotated with +@Transactional.

+
+
+
Using a transaction-scoped EntityManager
+
+
public class EntityManagerProducer
+{
+    //or manual bootstrapping
+    @PersistenceContext
+    private EntityManager entityManager;
+
+    @Produces
+    @TransactionScoped
+    protected EntityManager createEntityManager()
+    {
+        return this.entityManager;
+    }
+
+    protected void closeEntityManager(@Disposes EntityManager entityManager)
+    {
+        if (entityManager.isOpen())
+        {
+            entityManager.close();
+        }
+    }
+}
+
+
+
+
+
+

Extended Persistence Contexts

+
+
+

Frameworks like MyFaces Orchestra provide a feature which allows keeping +an EntityManager across multiple requests. That means it is not +required to call EntityManager#merge to add detached entities to the +context. However, several application architectures do not 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 +especially if an application does not 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 is not serializable. Beans which are scoped in a +normal-scoped CDI context have to be serializable. So by default it +is not allowed by CDI to provide a producer-method which exposes, for example, a +conversation scoped EntityManager as it is. We do not recommend this approach and therefore it is not available out-of-the-box. +However, if you really need this approach to avoid calling #merge for +your detached entities, it is pretty simple to add this functionality.

+
+
+
Usage of a Simple extended EntityManager
+
+
@Inject
+private EntityManager entityManager;
+
+
+
+

As you see the usage is the same. You do not have to use +ExtendedEntityManager at the injection point. It is just needed in the +producer-method:

+
+
+
Producer for an extended EntityManager (non-EE server)
+
+
//...
+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 an extended EntityManager (EE server)
+
+
@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 extended EntityManager
+
+
@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 does not come to serialization of this +wrapper, for example 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 do not recommend +such an approach.

+
+
+
+
+

JTA Support

+
+
+

By default the transaction-type used by @Transactional is +RESOURCE_LOCAL. If you configure transaction-type="JTA" in the +persistence.xml file, you have to enable an alternative TransactionStrategy +in the beans.xml which is called +org.apache.deltaspike.jpa.impl.transaction.BeanManagedUserTransactionStrategy.

+
+
+
+
<beans>
+    <alternatives>
+        <class>org.apache.deltaspike.jpa.impl.transaction.BeanManagedUserTransactionStrategy</class>
+    </alternatives>
+</beans>
+
+
+
+

Alternatively, you may expect that your transactions are started at a higher level, e.g. you’re exposing a REST API +and the endpoints themselves are either @Transactional or Stateless session beans, either with container managed +Transactions, you would use org.apache.deltaspike.jpa.impl.transaction.ContainerManagedTransactionStrategy. This +is the strategy to use if you are leveraging @PersistenceContext to inject your EntityManager.

+
+
+

If you have multiple persistence units and you have to use both +transaction types or the settings for development have to be different +than the production settings, you can use +org.apache.deltaspike.jpa.impl.transaction.EnvironmentAwareTransactionStrategy +instead.

+
+
+ + + + + +
+ + +In case of some versions of Weld - including several versions of JBoss EAP/Wildfly and Websphere Liberty Profile - +or OpenWebBeans in BDA mode - which is not the default one, you have +to configure it as a global alternative instead of an alternative in +beans.xml. That means you have to add, for example, +globalAlternatives.org.apache.deltaspike.jpa.spi.transaction.TransactionStrategy +=org.apache.deltaspike.jpa.impl.transaction.BeanManagedUserTransactionStrategy or +globalAlternatives.org.apache.deltaspike.jpa.spi.transaction.TransactionStrategy = org.apache.deltaspike.jpa.impl.transaction.ContainerManagedTransactionStrategy +to /META-INF/apache-deltaspike.properties. +
+
+
+
+
+
+ + +
+
+
+