You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@deltaspike.apache.org by Gerhard Petracek <gp...@apache.org> on 2014/02/27 20:41:54 UTC
Re: git commit: DELTASPIKE-420 Repository integration with TransactionStrategy
@thomas:
with that you have an overhead (in EntityManagerHolder: proxy due to
@ApplicationScoped + ThreadLocal) which is just useful for users of the
ds-data module.
-> if you would like to keep it that way, please use a specialized bean in
the ds-data module and avoid the overhead in the jpa-module.
regards,
gerhard
2014-02-27 19:55 GMT+01:00 <th...@apache.org>:
> 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 <Th...@ctp.com>
> Authored: Wed Feb 19 08:34:58 2014 +0100
> Committer: Thomas Hug <Th...@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)
>
>