Repository: deltaspike Updated Branches: refs/heads/master 515883430 -> 3a424c771
DELTASPIKE-1050 EntityManagerLookup isn't thread-safe Project: http://git-wip-us.apache.org/repos/asf/deltaspike/repo Commit: http://git-wip-us.apache.org/repos/asf/deltaspike/commit/3a424c77 Tree: http://git-wip-us.apache.org/repos/asf/deltaspike/tree/3a424c77 Diff: http://git-wip-us.apache.org/repos/asf/deltaspike/diff/3a424c77 Branch: refs/heads/master Commit: 3a424c771dda350eb9abfbe139d0eaca159cac62 Parents: 5158834 Author: Thomas Andraschko <[email protected]> Authored: Sat Jan 30 01:40:17 2016 +0100 Committer: Thomas Andraschko <[email protected]> Committed: Sat Jan 30 01:40:17 2016 +0100 ---------------------------------------------------------------------- .../data/impl/handler/EntityManagerLookup.java | 91 ------------------- .../data/impl/handler/EntityManagerRef.java | 72 +++++++++++++++ .../impl/handler/EntityManagerRefLookup.java | 92 ++++++++++++++++++++ .../data/impl/handler/QueryHandler.java | 17 ++-- 4 files changed, 176 insertions(+), 96 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/deltaspike/blob/3a424c77/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/EntityManagerLookup.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/EntityManagerLookup.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/EntityManagerLookup.java deleted file mode 100644 index 5970544..0000000 --- a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/EntityManagerLookup.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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 javax.enterprise.inject.Any; -import javax.enterprise.inject.Instance; -import javax.inject.Inject; -import javax.persistence.EntityManager; - -import org.apache.deltaspike.core.api.literal.DefaultLiteral; -import org.apache.deltaspike.core.api.provider.BeanProvider; -import org.apache.deltaspike.core.api.provider.DependentProvider; -import org.apache.deltaspike.data.api.EntityManagerResolver; -import org.apache.deltaspike.data.impl.meta.RepositoryComponent; -import org.apache.deltaspike.jpa.spi.entitymanager.ActiveEntityManagerHolder; - -public class EntityManagerLookup -{ - - @Inject - @Any - private Instance<EntityManager> entityManager; - - @Inject - private ActiveEntityManagerHolder activeEntityManagerHolder; - - private DependentProvider<? extends EntityManagerResolver> dependentResolverProvider; - - public EntityManager lookupFor(final RepositoryComponent repository) - { - EntityManager result = null; - if (repository.hasEntityManagerResolver()) - { - final Class<? extends EntityManagerResolver> emrc = repository.getEntityManagerResolverClass(); - if (!repository.isEntityManagerResolverIsNormalScope()) - { - final DependentProvider<? extends EntityManagerResolver> resolver = lookupResolver(emrc); - dependentResolverProvider = resolver; - result = resolver.get().resolveEntityManager(); - } - else - { - result = BeanProvider.getContextualReference(emrc).resolveEntityManager(); - } - } - else - { - if (activeEntityManagerHolder.isSet()) - { - return activeEntityManagerHolder.get(); - } - - result = entityManager.select(new DefaultLiteral()).get(); - } - if (repository.hasEntityManagerFlushMode()) - { - result.setFlushMode(repository.getEntityManagerFlushMode()); - } - return result; - } - - public void release() - { - if (dependentResolverProvider != null) - { - dependentResolverProvider.destroy(); - } - } - - private DependentProvider<? extends EntityManagerResolver> lookupResolver( - Class<? extends EntityManagerResolver> resolverClass) - { - return BeanProvider.getDependent(resolverClass); - } -} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/3a424c77/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/EntityManagerRef.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/EntityManagerRef.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/EntityManagerRef.java new file mode 100644 index 0000000..758be22 --- /dev/null +++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/EntityManagerRef.java @@ -0,0 +1,72 @@ +/* + * 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 javax.persistence.EntityManager; +import org.apache.deltaspike.core.api.provider.DependentProvider; +import org.apache.deltaspike.data.api.EntityManagerResolver; + +public class EntityManagerRef +{ + private Class<? extends EntityManagerResolver> entityManagerResolverClass; + private DependentProvider<? extends EntityManagerResolver> entityManagerResolverDependentProvider; + private EntityManager entityManager; + private EntityManagerResolver entityManagerResolver; + + public Class<? extends EntityManagerResolver> getEntityManagerResolverClass() + { + return entityManagerResolverClass; + } + + public void setEntityManagerResolverClass(Class<? extends EntityManagerResolver> entityManagerResolverClass) + { + this.entityManagerResolverClass = entityManagerResolverClass; + } + + public DependentProvider<? extends EntityManagerResolver> getEntityManagerResolverDependentProvider() + { + return entityManagerResolverDependentProvider; + } + + public void setEntityManagerResolverDependentProvider( + DependentProvider<? extends EntityManagerResolver> entityManagerResolverDependentProvider) + { + this.entityManagerResolverDependentProvider = entityManagerResolverDependentProvider; + } + + public EntityManager getEntityManager() + { + return entityManager; + } + + public void setEntityManager(EntityManager entityManager) + { + this.entityManager = entityManager; + } + + public EntityManagerResolver getEntityManagerResolver() + { + return entityManagerResolver; + } + + public void setEntityManagerResolver(EntityManagerResolver entityManagerResolver) + { + this.entityManagerResolver = entityManagerResolver; + } +} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/3a424c77/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/EntityManagerRefLookup.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/EntityManagerRefLookup.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/EntityManagerRefLookup.java new file mode 100644 index 0000000..62ea5b8 --- /dev/null +++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/EntityManagerRefLookup.java @@ -0,0 +1,92 @@ +/* + * 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 javax.enterprise.context.ApplicationScoped; +import javax.enterprise.inject.Any; +import javax.enterprise.inject.Instance; +import javax.inject.Inject; +import javax.persistence.EntityManager; + +import org.apache.deltaspike.core.api.literal.DefaultLiteral; +import org.apache.deltaspike.core.api.provider.BeanProvider; +import org.apache.deltaspike.data.impl.meta.RepositoryComponent; +import org.apache.deltaspike.jpa.spi.entitymanager.ActiveEntityManagerHolder; + +@ApplicationScoped +public class EntityManagerRefLookup +{ + @Inject + @Any + private Instance<EntityManager> entityManager; + + @Inject + private ActiveEntityManagerHolder activeEntityManagerHolder; + + public EntityManagerRef lookupReference(final RepositoryComponent repository) + { + EntityManagerRef ref = new EntityManagerRef(); + + if (repository.hasEntityManagerResolver()) + { + ref.setEntityManagerResolverClass( + repository.getEntityManagerResolverClass()); + + if (repository.isEntityManagerResolverIsNormalScope()) + { + ref.setEntityManagerResolver( + BeanProvider.getContextualReference(ref.getEntityManagerResolverClass())); + } + else + { + ref.setEntityManagerResolverDependentProvider( + BeanProvider.getDependent(ref.getEntityManagerResolverClass())); + + ref.setEntityManagerResolver( + ref.getEntityManagerResolverDependentProvider().get()); + } + + ref.setEntityManager( + ref.getEntityManagerResolver().resolveEntityManager()); + } + else + { + if (activeEntityManagerHolder.isSet()) + { + ref.setEntityManager( + activeEntityManagerHolder.get()); + + // TODO should we really not apply the FlushMode on the active EntityManager? + return ref; + } + else + { + ref.setEntityManager( + entityManager.select(new DefaultLiteral()).get()); + } + } + + if (repository.hasEntityManagerFlushMode()) + { + ref.getEntityManager().setFlushMode(repository.getEntityManagerFlushMode()); + } + + return ref; + } +} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/3a424c77/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 0831596..4838cb5 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 @@ -70,7 +70,7 @@ public class QueryHandler implements Serializable, InvocationHandler private CdiQueryContextHolder context; @Inject - private EntityManagerLookup entityManagerLookup; + private EntityManagerRefLookup entityManagerRefLookup; @Inject private QueryRunner runner; @@ -133,12 +133,16 @@ public class QueryHandler implements Serializable, InvocationHandler public Object process(Object proxy, Method method, Object[] args) throws Throwable { CdiQueryInvocationContext queryContext = null; + EntityManagerRef entityManagerRef = null; try { List<Class<?>> candidates = ProxyUtils.getProxyAndBaseTypes(proxy.getClass()); RepositoryComponent repo = components.lookupComponent(candidates); RepositoryMethod repoMethod = components.lookupMethod(repo.getRepositoryClass(), method); - queryContext = createContext(proxy, method, args, repo, repoMethod); + + entityManagerRef = entityManagerRefLookup.lookupReference(repo); + queryContext = createContext(proxy, method, args, entityManagerRef.getEntityManager(), repoMethod); + QueryBuilder builder = queryBuilder.build(repoMethod, queryContext); Object result = runner.executeQuery(builder, queryContext); return result; @@ -158,16 +162,19 @@ public class QueryHandler implements Serializable, InvocationHandler } finally { - entityManagerLookup.release(); + if (entityManagerRef != null && entityManagerRef.getEntityManagerResolverDependentProvider() != null) + { + entityManagerRef.getEntityManagerResolverDependentProvider().destroy(); + } context.dispose(); } } private CdiQueryInvocationContext createContext(Object proxy, Method method, - Object[] args, RepositoryComponent repo, RepositoryMethod repoMethod) + Object[] args, EntityManager entityManager, RepositoryMethod repoMethod) { CdiQueryInvocationContext queryContext = new CdiQueryInvocationContext(proxy, method, args, repoMethod, - entityManagerLookup.lookupFor(repo)); + entityManager); context.set(queryContext); queryContext.initMapper(); return queryContext;
