deltaspike-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From t...@apache.org
Subject git commit: DELTASPIKE-420 Repository integration with TransactionStrategy
Date Thu, 27 Feb 2014 18:55:54 GMT
Repository: deltaspike
Updated Branches:
  refs/heads/master 303507d6b -> db37a83a2


DELTASPIKE-420 Repository integration with TransactionStrategy


Project: http://git-wip-us.apache.org/repos/asf/deltaspike/repo
Commit: http://git-wip-us.apache.org/repos/asf/deltaspike/commit/db37a83a
Tree: http://git-wip-us.apache.org/repos/asf/deltaspike/tree/db37a83a
Diff: http://git-wip-us.apache.org/repos/asf/deltaspike/diff/db37a83a

Branch: refs/heads/master
Commit: db37a83a2cdd44cde147e6f9926c63e80422c5c6
Parents: 303507d
Author: Thomas Hug <Thomas.Hug@ctp.com>
Authored: Wed Feb 19 08:34:58 2014 +0100
Committer: Thomas Hug <Thomas.Hug@ctp.com>
Committed: Thu Feb 27 09:49:48 2014 +0100

----------------------------------------------------------------------
 deltaspike/modules/data/impl/pom.xml            |  12 ++
 .../data/impl/builder/DelegateQueryBuilder.java |  21 +---
 .../impl/handler/CdiQueryInvocationContext.java |   5 +
 .../impl/handler/EntityRepositoryHandler.java   |   8 ++
 .../data/impl/handler/QueryHandler.java         |  32 +----
 .../data/impl/handler/QueryRunner.java          |  28 +++++
 .../data/impl/meta/RepositoryMethod.java        |  12 ++
 .../data/impl/meta/RequiresTransaction.java     |  31 +++++
 .../data/impl/tx/InvocationContextWrapper.java  |  74 +++++++++++
 .../data/impl/tx/TransactionalQueryRunner.java  |  94 ++++++++++++++
 .../deltaspike/data/impl/util/ClassUtils.java   |  46 +++++++
 .../deltaspike/data/impl/util/ProxyUtils.java   |  53 ++++++++
 .../impl/tx/TransactionalQueryRunnerTest.java   | 123 +++++++++++++++++++
 .../tx/TransactionalQueryRunnerWrapper.java     |  65 ++++++++++
 .../service/ExtendedRepositoryInterface.java    |  14 +++
 .../data/test/util/TestDeployments.java         |  24 +++-
 .../impl/entitymanager/EntityManagerHolder.java |  49 ++++++++
 .../ResourceLocalTransactionStrategy.java       |  38 ++++--
 18 files changed, 667 insertions(+), 62 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/deltaspike/blob/db37a83a/deltaspike/modules/data/impl/pom.xml
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/pom.xml b/deltaspike/modules/data/impl/pom.xml
index 7b262fb..f54bef6 100755
--- a/deltaspike/modules/data/impl/pom.xml
+++ b/deltaspike/modules/data/impl/pom.xml
@@ -113,6 +113,12 @@
             <artifactId>deltaspike-partial-bean-module-impl</artifactId>
             <scope>runtime</scope>
         </dependency>
+        
+        <dependency>
+            <groupId>org.apache.deltaspike.modules</groupId>
+            <artifactId>deltaspike-jpa-module-impl</artifactId>
+            <scope>compile</scope>
+        </dependency>
 
         <!-- Tests -->
 
@@ -121,6 +127,12 @@
             <artifactId>shrinkwrap-resolver-impl-maven</artifactId>
             <scope>test</scope>
         </dependency>
+        
+        <dependency>
+            <groupId>org.jboss.shrinkwrap.descriptors</groupId>
+            <artifactId>shrinkwrap-descriptors-impl-javaee</artifactId>
+            <scope>test</scope>
+        </dependency>
 
     </dependencies>
 

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/db37a83a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/DelegateQueryBuilder.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/DelegateQueryBuilder.java
b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/DelegateQueryBuilder.java
index 0668ce7..1d9ca5d 100644
--- a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/DelegateQueryBuilder.java
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/DelegateQueryBuilder.java
@@ -18,6 +18,9 @@
  */
 package org.apache.deltaspike.data.impl.builder;
 
+import static org.apache.deltaspike.data.impl.util.ClassUtils.contains;
+import static org.apache.deltaspike.data.impl.util.ClassUtils.extract;
+
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.Set;
@@ -87,24 +90,6 @@ public class DelegateQueryBuilder extends QueryBuilder
         return null;
     }
 
-    private boolean contains(Class<?> obj, Method method)
-    {
-        return extract(obj, method) != null;
-    }
-
-    private Method extract(Class<?> obj, Method method)
-    {
-        try
-        {
-            String name = method.getName();
-            return obj != null ? obj.getMethod(name, method.getParameterTypes()) : null;
-        }
-        catch (NoSuchMethodException e)
-        {
-            return null;
-        }
-    }
-
     private Object invoke(DelegateQueryHandler delegate, CdiQueryInvocationContext context)
     {
         try

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/db37a83a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/CdiQueryInvocationContext.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/CdiQueryInvocationContext.java
b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/CdiQueryInvocationContext.java
index 8900d68..d553114 100644
--- a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/CdiQueryInvocationContext.java
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/CdiQueryInvocationContext.java
@@ -226,4 +226,9 @@ public class CdiQueryInvocationContext implements QueryInvocationContext
         return repoMethod.getSingleResultStyle();
     }
 
+    public Object getProxy()
+    {
+        return proxy;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/db37a83a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/EntityRepositoryHandler.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/EntityRepositoryHandler.java
b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/EntityRepositoryHandler.java
index 709d733..0c6ce40 100755
--- a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/EntityRepositoryHandler.java
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/EntityRepositoryHandler.java
@@ -37,6 +37,7 @@ import javax.persistence.metamodel.SingularAttribute;
 
 import org.apache.deltaspike.data.api.EntityRepository;
 import org.apache.deltaspike.data.impl.builder.QueryBuilder;
+import org.apache.deltaspike.data.impl.meta.RequiresTransaction;
 import org.apache.deltaspike.data.impl.property.Property;
 import org.apache.deltaspike.data.impl.property.query.NamedPropertyCriteria;
 import org.apache.deltaspike.data.impl.property.query.PropertyQueries;
@@ -59,6 +60,7 @@ public class EntityRepositoryHandler<E, PK extends Serializable>
     private QueryInvocationContext context;
 
     @Override
+    @RequiresTransaction
     public E save(E entity)
     {
         if (context.isNew(entity))
@@ -70,6 +72,7 @@ public class EntityRepositoryHandler<E, PK extends Serializable>
     }
 
     @Override
+    @RequiresTransaction
     public E saveAndFlush(E entity)
     {
         E result = save(entity);
@@ -78,6 +81,7 @@ public class EntityRepositoryHandler<E, PK extends Serializable>
     }
 
     @Override
+    @RequiresTransaction
     public E saveAndFlushAndRefresh(E entity)
     {
         E result = saveAndFlush(entity);
@@ -86,6 +90,7 @@ public class EntityRepositoryHandler<E, PK extends Serializable>
     }
 
     @Override
+    @RequiresTransaction
     public void refresh(E entity)
     {
         entityManager().refresh(entity);
@@ -161,12 +166,14 @@ public class EntityRepositoryHandler<E, PK extends Serializable>
     }
 
     @Override
+    @RequiresTransaction
     public void remove(E entity)
     {
         entityManager().remove(entity);
     }
 
     @Override
+    @RequiresTransaction
     public void removeAndFlush(E entity)
     {
         entityManager().remove(entity);
@@ -174,6 +181,7 @@ public class EntityRepositoryHandler<E, PK extends Serializable>
     }
 
     @Override
+    @RequiresTransaction
     public void flush()
     {
         entityManager().flush();

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/db37a83a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/QueryHandler.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/QueryHandler.java
b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/QueryHandler.java
index 6ce2af8..4a0ecd0 100755
--- a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/QueryHandler.java
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/QueryHandler.java
@@ -18,12 +18,11 @@
  */
 package org.apache.deltaspike.data.impl.handler;
 
+import static org.apache.deltaspike.data.impl.util.ProxyUtils.extractFromProxy;
+
 import java.io.Serializable;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import java.util.Arrays;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -64,6 +63,9 @@ public class QueryHandler implements Serializable, InvocationHandler
     @Inject
     private EntityManagerLookup entityManagerLookup;
 
+    @Inject
+    private QueryRunner runner;
+
     @Override
     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
     {
@@ -75,7 +77,7 @@ public class QueryHandler implements Serializable, InvocationHandler
             RepositoryMethod repoMethod = components.lookupMethod(repo.getRepositoryClass(),
method);
             queryContext = createContext(proxy, method, args, repo, repoMethod);
             QueryBuilder builder = queryBuilder.build(repoMethod, queryContext);
-            Object result = builder.executeQuery(queryContext);
+            Object result = runner.executeQuery(builder, queryContext);
             return result;
         }
         catch (PersistenceException e)
@@ -107,26 +109,4 @@ public class QueryHandler implements Serializable, InvocationHandler
         return queryContext;
     }
 
-    protected List<Class<?>> extractFromProxy(Class<?> proxyClass)
-    {
-        List<Class<?>> result = new LinkedList<Class<?>>();
-        result.add(proxyClass);
-        if (isInterfaceProxy(proxyClass))
-        {
-            result.addAll(Arrays.asList(proxyClass.getInterfaces()));
-        }
-        else
-        {
-            result.add(proxyClass.getSuperclass());
-        }
-        return result;
-    }
-
-    private boolean isInterfaceProxy(Class<?> proxyClass)
-    {
-        Class<?>[] interfaces = proxyClass.getInterfaces();
-        return Proxy.class.equals(proxyClass.getSuperclass()) &&
-                interfaces != null && interfaces.length > 0;
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/db37a83a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/QueryRunner.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/QueryRunner.java
b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/QueryRunner.java
new file mode 100644
index 0000000..a0f9206
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/QueryRunner.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.data.impl.handler;
+
+import org.apache.deltaspike.data.impl.builder.QueryBuilder;
+
+public interface QueryRunner
+{
+
+    Object executeQuery(QueryBuilder builder, CdiQueryInvocationContext context) throws Throwable;
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/db37a83a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/RepositoryMethod.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/RepositoryMethod.java
b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/RepositoryMethod.java
index ac90562..ff051fe 100644
--- a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/RepositoryMethod.java
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/RepositoryMethod.java
@@ -27,10 +27,12 @@ import java.util.Set;
 
 import javax.enterprise.inject.spi.Bean;
 import javax.enterprise.inject.spi.BeanManager;
+import javax.persistence.LockModeType;
 
 import org.apache.deltaspike.core.api.provider.BeanManagerProvider;
 import org.apache.deltaspike.core.api.provider.BeanProvider;
 import org.apache.deltaspike.core.api.provider.DependentProvider;
+import org.apache.deltaspike.data.api.Modifying;
 import org.apache.deltaspike.data.api.Query;
 import org.apache.deltaspike.data.api.SingleResultType;
 import org.apache.deltaspike.data.api.mapping.MappingConfig;
@@ -230,4 +232,14 @@ public class RepositoryMethod
         return methodPrefix.getSingleResultStyle();
     }
 
+    public boolean requiresTransaction()
+    {
+        boolean hasLockMode = false;
+        if (method.isAnnotationPresent(Query.class))
+        {
+            hasLockMode = !method.getAnnotation(Query.class).lock().equals(LockModeType.NONE);
+        }
+        return hasLockMode || method.isAnnotationPresent(Modifying.class);
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/db37a83a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/RequiresTransaction.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/RequiresTransaction.java
b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/RequiresTransaction.java
new file mode 100644
index 0000000..c59593e
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/RequiresTransaction.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.data.impl.meta;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+@Target(METHOD)
+@Retention(RUNTIME)
+public @interface RequiresTransaction
+{
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/db37a83a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/tx/InvocationContextWrapper.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/tx/InvocationContextWrapper.java
b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/tx/InvocationContextWrapper.java
new file mode 100644
index 0000000..e8692cb
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/tx/InvocationContextWrapper.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.data.impl.tx;
+
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.interceptor.InvocationContext;
+
+import org.apache.deltaspike.data.impl.handler.CdiQueryInvocationContext;
+
+public abstract class InvocationContextWrapper implements InvocationContext
+{
+
+    private final CdiQueryInvocationContext context;
+
+    public InvocationContextWrapper(CdiQueryInvocationContext context)
+    {
+        this.context = context;
+    }
+
+    @Override
+    public Map<String, Object> getContextData()
+    {
+        return new HashMap<String, Object>(0);
+    }
+
+    @Override
+    public Method getMethod()
+    {
+        return context.getMethod();
+    }
+
+    @Override
+    public Object[] getParameters()
+    {
+        return context.getMethodParameters();
+    }
+
+    @Override
+    public Object getTarget()
+    {
+        return context.getProxy();
+    }
+
+    @Override
+    public Object getTimer()
+    {
+        return null;
+    }
+
+    @Override
+    public void setParameters(Object[] args)
+    {
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/db37a83a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/tx/TransactionalQueryRunner.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/tx/TransactionalQueryRunner.java
b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/tx/TransactionalQueryRunner.java
new file mode 100644
index 0000000..d1b7d00
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/tx/TransactionalQueryRunner.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.data.impl.tx;
+
+import static org.apache.deltaspike.data.impl.util.ClassUtils.contains;
+import static org.apache.deltaspike.data.impl.util.ClassUtils.extract;
+
+import java.lang.reflect.Method;
+
+import javax.inject.Inject;
+
+import org.apache.deltaspike.data.impl.builder.QueryBuilder;
+import org.apache.deltaspike.data.impl.handler.CdiQueryInvocationContext;
+import org.apache.deltaspike.data.impl.handler.EntityRepositoryHandler;
+import org.apache.deltaspike.data.impl.handler.QueryRunner;
+import org.apache.deltaspike.data.impl.meta.RequiresTransaction;
+import org.apache.deltaspike.jpa.impl.entitymanager.EntityManagerHolder;
+import org.apache.deltaspike.jpa.spi.transaction.TransactionStrategy;
+
+public class TransactionalQueryRunner implements QueryRunner
+{
+
+    @Inject
+    private TransactionStrategy strategy;
+
+    @Inject
+    private EntityManagerHolder entityManagerHolder;
+
+    @Override
+    public Object executeQuery(final QueryBuilder builder, final CdiQueryInvocationContext
context)
+        throws Throwable
+    {
+        if (needsTransaction(context))
+        {
+            try
+            {
+                entityManagerHolder.set(context.getEntityManager());
+                return executeTransactional(builder, context);
+            }
+            finally
+            {
+                entityManagerHolder.dispose();
+            }
+        }
+        return executeNonTransactional(builder, context);
+    }
+
+    protected Object executeNonTransactional(final QueryBuilder builder, final CdiQueryInvocationContext
context)
+    {
+        return builder.executeQuery(context);
+    }
+
+    protected Object executeTransactional(final QueryBuilder builder, final CdiQueryInvocationContext
context)
+        throws Exception
+    {
+        return strategy.execute(new InvocationContextWrapper(context)
+        {
+            @Override
+            public Object proceed() throws Exception
+            {
+                return builder.executeQuery(context);
+            }
+        });
+    }
+
+    private boolean needsTransaction(CdiQueryInvocationContext context)
+    {
+        boolean requiresTx = false;
+        Method method = context.getMethod();
+        if (contains(EntityRepositoryHandler.class, method))
+        {
+            Method executed = extract(EntityRepositoryHandler.class, method);
+            requiresTx = executed.isAnnotationPresent(RequiresTransaction.class);
+        }
+        return requiresTx || context.getRepositoryMethod().requiresTransaction();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/db37a83a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/util/ClassUtils.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/util/ClassUtils.java
b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/util/ClassUtils.java
new file mode 100644
index 0000000..d1e73ff
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/util/ClassUtils.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.data.impl.util;
+
+import java.lang.reflect.Method;
+
+public class ClassUtils
+{
+    private ClassUtils()
+    {
+    }
+
+    public static boolean contains(Class<?> obj, Method method)
+    {
+        return extract(obj, method) != null;
+    }
+
+    public static Method extract(Class<?> clazz, Method method)
+    {
+        try
+        {
+            String name = method.getName();
+            return clazz != null ? clazz.getMethod(name, method.getParameterTypes()) : null;
+        }
+        catch (NoSuchMethodException e)
+        {
+            return null;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/db37a83a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/util/ProxyUtils.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/util/ProxyUtils.java
b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/util/ProxyUtils.java
new file mode 100644
index 0000000..d683e32
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/util/ProxyUtils.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.data.impl.util;
+
+import java.lang.reflect.Proxy;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+public class ProxyUtils
+{
+    private ProxyUtils()
+    {
+    }
+
+    public static List<Class<?>> extractFromProxy(Class<?> proxyClass)
+    {
+        List<Class<?>> result = new LinkedList<Class<?>>();
+        result.add(proxyClass);
+        if (isInterfaceProxy(proxyClass))
+        {
+            result.addAll(Arrays.asList(proxyClass.getInterfaces()));
+        }
+        else
+        {
+            result.add(proxyClass.getSuperclass());
+        }
+        return result;
+    }
+
+    public static boolean isInterfaceProxy(Class<?> proxyClass)
+    {
+        Class<?>[] interfaces = proxyClass.getInterfaces();
+        return Proxy.class.equals(proxyClass.getSuperclass()) &&
+                interfaces != null && interfaces.length > 0;
+    }
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/db37a83a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/tx/TransactionalQueryRunnerTest.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/tx/TransactionalQueryRunnerTest.java
b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/tx/TransactionalQueryRunnerTest.java
new file mode 100644
index 0000000..c6c7346
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/tx/TransactionalQueryRunnerTest.java
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.data.impl.tx;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import javax.enterprise.inject.Produces;
+import javax.inject.Inject;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+
+import org.apache.deltaspike.data.test.domain.Simple;
+import org.apache.deltaspike.data.test.service.ExtendedRepositoryInterface;
+import org.apache.deltaspike.data.test.util.TestDeployments;
+import org.apache.deltaspike.test.category.WebProfileCategory;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.arquillian.junit.InSequence;
+import org.jboss.shrinkwrap.api.Archive;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+
+@Category(WebProfileCategory.class)
+@RunWith(Arquillian.class)
+public class TransactionalQueryRunnerTest
+{
+
+    private static final String NAME = "should_run_in_transaction";
+
+    @Deployment
+    public static Archive<?> deployment()
+    {
+        return TestDeployments.initDeployment()
+                .addClasses(ExtendedRepositoryInterface.class)
+                .addPackage(Simple.class.getPackage());
+    }
+
+    @Inject
+    private ExtendedRepositoryInterface repository;
+
+    @Produces
+    @PersistenceContext
+    private EntityManager entityManager;
+
+    @Inject
+    private TransactionalQueryRunnerWrapper wrapper;
+
+    @Test
+    @InSequence(1)
+    public void should_run_modifying_in_transaction() throws Exception
+    {
+        // when
+        repository.deleteAll();
+
+        // then
+        assertTrue(wrapper.isRunInTx());
+    }
+
+    @Test
+    @InSequence(2)
+    public void should_save_in_transaction() throws Exception
+    {
+        // given
+        Simple simple = new Simple(NAME);
+
+        // when
+        simple = repository.save(simple);
+
+        // then
+        assertNotNull(simple.getId());
+        assertTrue(wrapper.isRunInTx());
+    }
+
+    @Test
+    @InSequence(3)
+    public void should_find_with_lockmode_in_transaction() throws Exception
+    {
+        // when
+        Simple simple = repository.findByName(NAME);
+
+        // then
+        assertNotNull(simple);
+        assertTrue(wrapper.isRunInTx());
+    }
+
+    @Test
+    @InSequence(4)
+    public void should_find_no_lock_without_transaction() throws Exception
+    {
+        // when
+        Simple simple = repository.findByNameNoLock(NAME);
+
+        // then
+        assertNotNull(simple);
+        assertTrue(wrapper.isRunInNonTx());
+    }
+
+    @Before
+    public void init()
+    {
+        wrapper.reset();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/db37a83a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/tx/TransactionalQueryRunnerWrapper.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/tx/TransactionalQueryRunnerWrapper.java
b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/tx/TransactionalQueryRunnerWrapper.java
new file mode 100644
index 0000000..14e0e63
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/tx/TransactionalQueryRunnerWrapper.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.data.impl.tx;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.inject.Specializes;
+
+import org.apache.deltaspike.data.impl.builder.QueryBuilder;
+import org.apache.deltaspike.data.impl.handler.CdiQueryInvocationContext;
+
+@Specializes
+@ApplicationScoped
+public class TransactionalQueryRunnerWrapper extends TransactionalQueryRunner
+{
+
+    private boolean runInTx = false;
+    private boolean runInNonTx = false;
+
+    public void reset()
+    {
+        runInTx = false;
+        runInNonTx = false;
+    }
+
+    @Override
+    protected Object executeNonTransactional(QueryBuilder builder, CdiQueryInvocationContext
context)
+    {
+        runInNonTx = true;
+        return super.executeNonTransactional(builder, context);
+    }
+
+    @Override
+    protected Object executeTransactional(QueryBuilder builder, CdiQueryInvocationContext
context) throws Exception
+    {
+        runInTx = true;
+        return super.executeTransactional(builder, context);
+    }
+
+    public boolean isRunInTx()
+    {
+        return runInTx;
+    }
+
+    public boolean isRunInNonTx()
+    {
+        return runInNonTx;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/db37a83a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/ExtendedRepositoryInterface.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/ExtendedRepositoryInterface.java
b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/ExtendedRepositoryInterface.java
index 49ab7f4..1445d33 100755
--- a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/ExtendedRepositoryInterface.java
+++ b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/ExtendedRepositoryInterface.java
@@ -18,11 +18,25 @@
  */
 package org.apache.deltaspike.data.test.service;
 
+import static javax.persistence.LockModeType.PESSIMISTIC_READ;
+
 import org.apache.deltaspike.data.api.EntityRepository;
+import org.apache.deltaspike.data.api.Modifying;
+import org.apache.deltaspike.data.api.Query;
 import org.apache.deltaspike.data.api.Repository;
 import org.apache.deltaspike.data.test.domain.Simple;
 
 @Repository
 public interface ExtendedRepositoryInterface extends EntityRepository<Simple, Long>
 {
+
+    @Query(lock = PESSIMISTIC_READ)
+    Simple findByName(String name);
+
+    @Query(named = Simple.BY_NAME_LIKE)
+    Simple findByNameNoLock(String name);
+
+    @Modifying @Query("delete from Simple")
+    int deleteAll();
+
 }

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/db37a83a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/util/TestDeployments.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/util/TestDeployments.java
b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/util/TestDeployments.java
index d002913..0472a40 100755
--- a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/util/TestDeployments.java
+++ b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/util/TestDeployments.java
@@ -47,13 +47,16 @@ import org.apache.deltaspike.data.impl.builder.QueryBuilder;
 import org.apache.deltaspike.data.impl.criteria.QueryCriteria;
 import org.apache.deltaspike.data.impl.handler.QueryHandler;
 import org.apache.deltaspike.data.impl.meta.RepositoryComponents;
+import org.apache.deltaspike.data.impl.meta.RequiresTransaction;
 import org.apache.deltaspike.data.impl.param.Parameters;
 import org.apache.deltaspike.data.impl.property.Property;
+import org.apache.deltaspike.data.impl.tx.TransactionalQueryRunner;
 import org.apache.deltaspike.data.impl.util.EntityUtils;
 import org.apache.deltaspike.data.spi.DelegateQueryHandler;
 import org.apache.deltaspike.data.spi.QueryInvocationContext;
 import org.apache.deltaspike.data.test.TransactionalTestCase;
 import org.apache.deltaspike.data.test.domain.AuditedEntity;
+import org.apache.deltaspike.jpa.impl.transaction.EnvironmentAwareTransactionStrategy;
 import org.apache.deltaspike.test.category.WebProfileCategory;
 import org.apache.deltaspike.test.utils.CdiContainerUnderTest;
 import org.jboss.shrinkwrap.api.Archive;
@@ -61,9 +64,11 @@ import org.jboss.shrinkwrap.api.ArchivePath;
 import org.jboss.shrinkwrap.api.ArchivePaths;
 import org.jboss.shrinkwrap.api.Filter;
 import org.jboss.shrinkwrap.api.ShrinkWrap;
-import org.jboss.shrinkwrap.api.asset.EmptyAsset;
+import org.jboss.shrinkwrap.api.asset.StringAsset;
 import org.jboss.shrinkwrap.api.spec.JavaArchive;
 import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.jboss.shrinkwrap.descriptor.api.Descriptors;
+import org.jboss.shrinkwrap.descriptor.api.beans10.BeansDescriptor;
 import org.jboss.shrinkwrap.impl.base.filter.ExcludeRegExpPaths;
 import org.jboss.shrinkwrap.resolver.api.maven.Maven;
 
@@ -85,6 +90,12 @@ public abstract class TestDeployments
     public static WebArchive initDeployment(String testFilter)
     {
         Logging.reconfigure();
+        String descriptor = Descriptors.create(BeansDescriptor.class)
+                .addDefaultNamespaces()
+                .createAlternatives()
+                    .clazz(EnvironmentAwareTransactionStrategy.class.getName())
+                    .up()
+                .exportAsString();
         WebArchive archive = ShrinkWrap
                 .create(WebArchive.class, "test.war")
                 .addAsLibrary(createApiArchive())
@@ -98,7 +109,7 @@ public abstract class TestDeployments
                         ArchivePaths.create("classes/META-INF/persistence.xml"))
                 .addAsWebInfResource("META-INF/services/javax.enterprise.inject.spi.Extension",
                         ArchivePaths.create("classes/META-INF/services/javax.enterprise.inject.spi.Extension"))
-                .addAsWebInfResource(EmptyAsset.INSTANCE, ArchivePaths.create("beans.xml"));
+                .addAsWebInfResource(new StringAsset(descriptor), ArchivePaths.create("beans.xml"));
 
         return addDependencies(archive);
     }
@@ -113,7 +124,8 @@ public abstract class TestDeployments
                 RepositoryComponents.class.getPackage(),
                 Parameters.class.getPackage(),
                 EntityUtils.class.getPackage(),
-                Property.class.getPackage()
+                Property.class.getPackage(),
+                TransactionalQueryRunner.class.getPackage()
         };
     }
 
@@ -128,7 +140,7 @@ public abstract class TestDeployments
                 .addClasses(Criteria.class, QuerySelection.class, CriteriaSupport.class)
                 .addClasses(CreatedOn.class, CurrentUser.class, ModifiedBy.class, ModifiedOn.class)
                 .addClasses(MappingConfig.class, QueryInOutMapper.class)
-                .addClasses(DelegateQueryHandler.class, QueryInvocationContext.class);
+                .addClasses(DelegateQueryHandler.class, QueryInvocationContext.class, RequiresTransaction.class);
     }
 
     public static WebArchive addDependencies(WebArchive archive)
@@ -138,7 +150,9 @@ public abstract class TestDeployments
                         "org.apache.deltaspike.core:deltaspike-core-api",
                         "org.apache.deltaspike.core:deltaspike-core-impl",
                         "org.apache.deltaspike.modules:deltaspike-partial-bean-module-api",
-                        "org.apache.deltaspike.modules:deltaspike-partial-bean-module-impl")
+                        "org.apache.deltaspike.modules:deltaspike-partial-bean-module-impl",
+                        "org.apache.deltaspike.modules:deltaspike-jpa-module-api",
+                        "org.apache.deltaspike.modules:deltaspike-jpa-module-impl")
                         .withTransitivity()
                         .asFile());
         if (CdiContainerUnderTest.is("owb-.*") ||

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/db37a83a/deltaspike/modules/jpa/impl/src/main/java/org/apache/deltaspike/jpa/impl/entitymanager/EntityManagerHolder.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jpa/impl/src/main/java/org/apache/deltaspike/jpa/impl/entitymanager/EntityManagerHolder.java
b/deltaspike/modules/jpa/impl/src/main/java/org/apache/deltaspike/jpa/impl/entitymanager/EntityManagerHolder.java
new file mode 100644
index 0000000..2d3a5a4
--- /dev/null
+++ b/deltaspike/modules/jpa/impl/src/main/java/org/apache/deltaspike/jpa/impl/entitymanager/EntityManagerHolder.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.jpa.impl.entitymanager;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.persistence.EntityManager;
+
+@ApplicationScoped
+public class EntityManagerHolder
+{
+
+    private final ThreadLocal<EntityManager> entityManager = new ThreadLocal<EntityManager>();
+
+    public void set(EntityManager entityManager)
+    {
+        this.entityManager.set(entityManager);
+    }
+
+    public boolean isSet()
+    {
+        return get() != null;
+    }
+
+    public EntityManager get()
+    {
+        return entityManager.get();
+    }
+
+    public void dispose()
+    {
+        entityManager.remove();
+    }
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/db37a83a/deltaspike/modules/jpa/impl/src/main/java/org/apache/deltaspike/jpa/impl/transaction/ResourceLocalTransactionStrategy.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jpa/impl/src/main/java/org/apache/deltaspike/jpa/impl/transaction/ResourceLocalTransactionStrategy.java
b/deltaspike/modules/jpa/impl/src/main/java/org/apache/deltaspike/jpa/impl/transaction/ResourceLocalTransactionStrategy.java
index 717206c..d5819ae 100644
--- a/deltaspike/modules/jpa/impl/src/main/java/org/apache/deltaspike/jpa/impl/transaction/ResourceLocalTransactionStrategy.java
+++ b/deltaspike/modules/jpa/impl/src/main/java/org/apache/deltaspike/jpa/impl/transaction/ResourceLocalTransactionStrategy.java
@@ -19,14 +19,15 @@
 package org.apache.deltaspike.jpa.impl.transaction;
 
 
-import org.apache.deltaspike.core.api.literal.AnyLiteral;
-import org.apache.deltaspike.core.util.ProxyUtils;
-import org.apache.deltaspike.jpa.api.transaction.Transactional;
-import org.apache.deltaspike.jpa.impl.transaction.context.EntityManagerEntry;
-import org.apache.deltaspike.jpa.impl.transaction.context.TransactionBeanStorage;
-import org.apache.deltaspike.jpa.spi.transaction.TransactionStrategy;
+import java.lang.annotation.Annotation;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 import javax.enterprise.context.Dependent;
+import javax.enterprise.inject.Default;
 import javax.enterprise.inject.spi.Bean;
 import javax.enterprise.inject.spi.BeanManager;
 import javax.inject.Inject;
@@ -34,11 +35,13 @@ import javax.interceptor.InvocationContext;
 import javax.persistence.EntityManager;
 import javax.persistence.EntityTransaction;
 
-import java.lang.annotation.Annotation;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.logging.Level;
-import java.util.logging.Logger;
+import org.apache.deltaspike.core.api.literal.AnyLiteral;
+import org.apache.deltaspike.core.util.ProxyUtils;
+import org.apache.deltaspike.jpa.api.transaction.Transactional;
+import org.apache.deltaspike.jpa.impl.entitymanager.EntityManagerHolder;
+import org.apache.deltaspike.jpa.impl.transaction.context.EntityManagerEntry;
+import org.apache.deltaspike.jpa.impl.transaction.context.TransactionBeanStorage;
+import org.apache.deltaspike.jpa.spi.transaction.TransactionStrategy;
 
 /**
  * <p>Default implementation of our plugable TransactionStrategy.
@@ -70,6 +73,10 @@ public class ResourceLocalTransactionStrategy implements TransactionStrategy
     @Inject
     private TransactionStrategyHelper transactionHelper;
 
+    @Inject
+    private EntityManagerHolder emHolder;
+
+    @Override
     public Object execute(InvocationContext invocationContext) throws Exception
     {
         Transactional transactionalAnnotation = transactionHelper.extractTransactionalAnnotation(invocationContext);
@@ -77,8 +84,9 @@ public class ResourceLocalTransactionStrategy implements TransactionStrategy
         Class targetClass = ProxyUtils.getUnproxiedClass(invocationContext.getTarget().getClass());
//see DELTASPIKE-517
 
         // all the configured qualifier keys
-        Set<Class<? extends Annotation>> emQualifiers = transactionHelper.resolveEntityManagerQualifiers(
-                    transactionalAnnotation, targetClass);
+        Set<Class<? extends Annotation>> emQualifiers = emHolder.isSet() ?
+                new HashSet<Class<? extends Annotation>>(Arrays.asList(Default.class))
:
+                transactionHelper.resolveEntityManagerQualifiers(transactionalAnnotation,
targetClass);
 
         TransactionBeanStorage transactionBeanStorage = TransactionBeanStorage.getInstance();
 
@@ -307,6 +315,10 @@ public class ResourceLocalTransactionStrategy implements TransactionStrategy
 
     private EntityManager resolveEntityManagerForQualifier(Class<? extends Annotation>
emQualifier)
     {
+        if (emHolder.isSet())
+        {
+            return emHolder.get();
+        }
         Bean<EntityManager> entityManagerBean = resolveEntityManagerBean(emQualifier);
 
         if (entityManagerBean == null)


Mime
View raw message