Author: jlmonteiro
Date: Wed Apr 20 16:33:29 2011
New Revision: 1095452
URL: http://svn.apache.org/viewvc?rev=1095452&view=rev
Log:
OPENEJB-1527: Fixing bad transaction management on the JtaEntityManager wrapper.
Thanks a lot Thibaut.
Added:
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/persistence/JtaTypedQuery.java
Modified:
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/persistence/JtaEntityManager.java
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/persistence/JtaEntityManagerRegistry.java
Modified:
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/persistence/JtaEntityManager.java
URL:
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/persistence/JtaEntityManager.java?rev=1095452&r1=1095451&r2=1095452&view=diff
==============================================================================
---
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/persistence/JtaEntityManager.java
(original)
+++
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/persistence/JtaEntityManager.java
Wed Apr 20 16:33:29 2011
@@ -17,23 +17,22 @@
*/
package org.apache.openejb.persistence;
-import org.apache.openejb.util.Logger;
import org.apache.openejb.util.LogCategory;
+import org.apache.openejb.util.Logger;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.EntityTransaction;
import javax.persistence.FlushModeType;
import javax.persistence.LockModeType;
import javax.persistence.Query;
-import javax.persistence.EntityTransaction;
-import javax.persistence.EntityManager;
-import javax.persistence.EntityManagerFactory;
import javax.persistence.TransactionRequiredException;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.metamodel.Metamodel;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
/**
* The JtaEntityManager is a wrapper around an entity manager that
automatically creates and closes entity managers
@@ -240,7 +239,10 @@ public class JtaEntityManager implements
public boolean contains(Object entity) {
final Timer timer = Op.contains.start(this);
try {
- return isTransactionActive() &&
getEntityManager().contains(entity);
+ if (!extended && !isTransactionActive()) {
+ return false;
+ }
+ return getEntityManager().contains(entity);
} finally {
timer.stop();
}
@@ -307,6 +309,13 @@ public class JtaEntityManager implements
}
return query;
}
+
+ private <T> TypedQuery<T> proxyIfNoTx(EntityManager entityManager,
TypedQuery<T> query) {
+ if (!extended && !isTransactionActive()) {
+ return new JtaTypedQuery<T>(entityManager, query);
+ }
+ return query;
+ }
public void joinTransaction() {
if (logger.isDebugEnabled()) {
@@ -327,70 +336,58 @@ public class JtaEntityManager implements
public EntityTransaction getTransaction() {
throw new IllegalStateException("A JTA EntityManager can not use the
EntityTransaction API. See JPA 1.0 section 5.5");
}
-
+
// JPA 2.0
/* (non-Javadoc)
* @see javax.persistence.EntityManager#createNamedQuery(java.lang.String,
java.lang.Class)
*/
public <T> TypedQuery<T> createNamedQuery(String name, Class<T>
resultClass) {
- EntityManager entityManager = getEntityManager();
+ final Timer timer = Op.createNamedQuery.start(this);
try {
- final Timer timer = Op.createNamedQuery.start(this);
- try {
- return entityManager.createNamedQuery(name, resultClass);
- } finally {
- timer.stop();
- }
+ EntityManager entityManager = getEntityManager();
+ TypedQuery<T> query = entityManager.createNamedQuery(name,
resultClass);
+ return proxyIfNoTx(entityManager, query);
} finally {
- closeIfNoTx(entityManager);
+ timer.stop();
}
}
/* (non-Javadoc)
* @see
javax.persistence.EntityManager#createQuery(javax.persistence.criteria.CriteriaQuery)
*/
public <T> TypedQuery<T> createQuery(CriteriaQuery<T> criteriaQuery) {
- EntityManager entityManager = getEntityManager();
+ final Timer timer = Op.createQuery.start(this);
try {
- final Timer timer = Op.createQuery.start(this);
- try {
- return entityManager.createQuery(criteriaQuery);
- } finally {
- timer.stop();
- }
+ EntityManager entityManager = getEntityManager();
+ TypedQuery<T> query = entityManager.createQuery(criteriaQuery);
+ return proxyIfNoTx(entityManager, query);
} finally {
- closeIfNoTx(entityManager);
+ timer.stop();
}
}
/* (non-Javadoc)
* @see javax.persistence.EntityManager#createQuery(java.lang.String,
java.lang.Class)
*/
public <T> TypedQuery<T> createQuery(String qlString, Class<T>
resultClass) {
- EntityManager entityManager = getEntityManager();
+ final Timer timer = Op.createQuery.start(this);
try {
- final Timer timer = Op.createQuery.start(this);
- try {
- return entityManager.createQuery(qlString, resultClass);
- } finally {
- timer.stop();
- }
+ EntityManager entityManager = getEntityManager();
+ TypedQuery<T> query = entityManager.createQuery(qlString,
resultClass);
+ return proxyIfNoTx(entityManager, query);
} finally {
- closeIfNoTx(entityManager);
+ timer.stop();
}
}
/* (non-Javadoc)
* @see javax.persistence.EntityManager#detach(java.lang.Object)
*/
public void detach(Object entity) {
- EntityManager entityManager = getEntityManager();
+ final Timer timer = Op.detach.start(this);
try {
- final Timer timer = Op.detach.start(this);
- try {
- entityManager.detach(entity);
- } finally {
- timer.stop();
+ if (!extended && isTransactionActive()) {
+ getEntityManager().detach(entity);
}
} finally {
- closeIfNoTx(entityManager);
+ timer.stop();
}
}
/* (non-Javadoc)
@@ -451,17 +448,13 @@ public class JtaEntityManager implements
* @see javax.persistence.EntityManager#getLockMode(java.lang.Object)
*/
public LockModeType getLockMode(Object entity) {
- EntityManager entityManager = getEntityManager();
+ assertTransactionActive();
+ final Timer timer = Op.getLockMode.start(this);
try {
- final Timer timer = Op.getLockMode.start(this);
- try {
- return entityManager.getLockMode(entity);
- } finally {
- timer.stop();
- }
+ return getEntityManager().getLockMode(entity);
} finally {
- closeIfNoTx(entityManager);
- }
+ timer.stop();
+ }
}
/* (non-Javadoc)
* @see javax.persistence.EntityManager#getMetamodel()
@@ -515,64 +508,48 @@ public class JtaEntityManager implements
* @see javax.persistence.EntityManager#lock(java.lang.Object,
javax.persistence.LockModeType, java.util.Map)
*/
public void lock(Object entity, LockModeType lockMode, Map<String, Object>
properties) {
- EntityManager entityManager = getEntityManager();
+ assertTransactionActive();
+ final Timer timer = Op.lock.start(this);
try {
- final Timer timer = Op.lock.start(this);
- try {
- entityManager.lock(entityManager, lockMode, properties);
- } finally {
- timer.stop();
- }
+ getEntityManager().lock(entity, lockMode, properties);
} finally {
- closeIfNoTx(entityManager);
- }
+ timer.stop();
+ }
}
/* (non-Javadoc)
* @see javax.persistence.EntityManager#refresh(java.lang.Object,
java.util.Map)
*/
public void refresh(Object entity, Map<String, Object> properties) {
- EntityManager entityManager = getEntityManager();
+ assertTransactionActive();
+ final Timer timer = Op.refresh.start(this);
try {
- final Timer timer = Op.refresh.start(this);
- try {
- entityManager.refresh(entityManager, properties);
- } finally {
- timer.stop();
- }
+ getEntityManager().refresh(entity, properties);
} finally {
- closeIfNoTx(entityManager);
+ timer.stop();
}
}
/* (non-Javadoc)
* @see javax.persistence.EntityManager#refresh(java.lang.Object,
javax.persistence.LockModeType)
*/
public void refresh(Object entity, LockModeType lockMode) {
- EntityManager entityManager = getEntityManager();
+ assertTransactionActive();
+ final Timer timer = Op.refresh.start(this);
try {
- final Timer timer = Op.refresh.start(this);
- try {
- entityManager.refresh(entityManager, lockMode);
- } finally {
- timer.stop();
- }
+ getEntityManager().refresh(entity, lockMode);
} finally {
- closeIfNoTx(entityManager);
+ timer.stop();
}
}
/* (non-Javadoc)
* @see javax.persistence.EntityManager#refresh(java.lang.Object,
javax.persistence.LockModeType, java.util.Map)
*/
public void refresh(Object entity, LockModeType lockMode, Map<String,
Object> properties) {
- EntityManager entityManager = getEntityManager();
+ assertTransactionActive();
+ final Timer timer = Op.refresh.start(this);
try {
- final Timer timer = Op.refresh.start(this);
- try {
- entityManager.refresh(entityManager, lockMode, properties);
- } finally {
- timer.stop();
- }
+ getEntityManager().refresh(entity, lockMode, properties);
} finally {
- closeIfNoTx(entityManager);
+ timer.stop();
}
}
/* (non-Javadoc)
@@ -595,17 +572,7 @@ public class JtaEntityManager implements
* @see javax.persistence.EntityManager#unwrap(java.lang.Class)
*/
public <T> T unwrap(Class<T> cls) {
- EntityManager entityManager = getEntityManager();
- try {
- final Timer timer = Op.unwrap.start(this);
- try {
- return entityManager.unwrap(cls);
- } finally {
- timer.stop();
- }
- } finally {
- closeIfNoTx(entityManager);
- }
+ return getEntityManager().unwrap(cls);
}
public static class Timer {
Modified:
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/persistence/JtaEntityManagerRegistry.java
URL:
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/persistence/JtaEntityManagerRegistry.java?rev=1095452&r1=1095451&r2=1095452&view=diff
==============================================================================
---
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/persistence/JtaEntityManagerRegistry.java
(original)
+++
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/persistence/JtaEntityManagerRegistry.java
Wed Apr 20 16:33:29 2011
@@ -18,22 +18,22 @@
package org.apache.openejb.persistence;
-import org.apache.openejb.util.Logger;
-import org.apache.openejb.util.LogCategory;
import org.apache.openejb.util.Geronimo;
+import org.apache.openejb.util.LogCategory;
+import org.apache.openejb.util.Logger;
-import java.util.Map;
-import java.util.HashMap;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.TransactionRequiredException;
import javax.transaction.Status;
import javax.transaction.Synchronization;
import javax.transaction.TransactionSynchronizationRegistry;
+import java.util.HashMap;
+import java.util.Map;
/**
- * The JtaEntityManagerRegistry tracks JTA entity managers for transation and
extended scoped
- * entity managers. A signle instance of this object should be created and
shared by all
+ * The JtaEntityManagerRegistry tracks JTA entity managers for transaction and
extended scoped
+ * entity managers. A single instance of this object should be created and
shared by all
* JtaEntityManagers in the server instance. Failure to do this will result
in multiple entity
* managers being created for a single persistence until, and that will result
in cache
* incoherence.
@@ -48,7 +48,7 @@ public class JtaEntityManagerRegistry {
private final TransactionSynchronizationRegistry transactionRegistry;
/**
- * Registry of entended context entity managers.
+ * Registry of extended context entity managers.
*/
private final ThreadLocal<ExtendedRegistry> extendedRegistry = new
ThreadLocal<ExtendedRegistry>() {
protected ExtendedRegistry initialValue() {
@@ -65,11 +65,11 @@ public class JtaEntityManagerRegistry {
}
/**
- * Gets an entity manager instance from the transaction registry, extended
regitry or for a transaction scoped
- * entity manager, creates a new one when an exisitng instance is not
found.
+ * Gets an entity manager instance from the transaction registry, extended
registry or for a transaction scoped
+ * entity manager, creates a new one when an existing instance is not
found.
* </p>
* It is important that a component adds extended scoped entity managers
to this registry when the component is
- * entered and removes them when exited. If this registration is not
preformed, an IllegalStateException will
+ * entered and removes them when exited. If this registration is not
performed, an IllegalStateException will
* be thrown when entity manger is fetched.
* @param entityManagerFactory the entity manager factory from which an
entity manager is required
* @param properties the properties passed to the entity manager factory
when an entity manager is created
Added:
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/persistence/JtaTypedQuery.java
URL:
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/persistence/JtaTypedQuery.java?rev=1095452&view=auto
==============================================================================
---
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/persistence/JtaTypedQuery.java
(added)
+++
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/persistence/JtaTypedQuery.java
Wed Apr 20 16:33:29 2011
@@ -0,0 +1,142 @@
+/**
+ *
+ * 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.openejb.persistence;
+
+import javax.persistence.EntityManager;
+import javax.persistence.FlushModeType;
+import javax.persistence.LockModeType;
+import javax.persistence.Parameter;
+import javax.persistence.Query;
+import javax.persistence.TemporalType;
+import javax.persistence.TypedQuery;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @author Thibaut Robert
+ *
+ * This class is the same as {@link JtaQuery} but wraps TypedQuery instead of
Query
+ */
+public class JtaTypedQuery<X> extends JtaQuery implements TypedQuery<X> {
+
+ public JtaTypedQuery(EntityManager entityManager, Query query) {
+ super(entityManager, query);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public List<X> getResultList() {
+ return (List<X>) super.getResultList();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public X getSingleResult() {
+ return (X) super.getSingleResult();
+ }
+
+ @Override
+ public TypedQuery<X> setFirstResult(int i) {
+ super.setFirstResult(i);
+ return this;
+ }
+
+ @Override
+ public TypedQuery<X> setFlushMode(FlushModeType flushModeType) {
+ super.setFlushMode(flushModeType);
+ return this;
+ }
+
+ @Override
+ public TypedQuery<X> setHint(String s, Object o) {
+ super.setHint(s, o);
+ return this;
+ }
+
+ @Override
+ public TypedQuery<X> setLockMode(LockModeType lockMode) {
+ super.setLockMode(lockMode);
+ return this;
+ }
+
+ @Override
+ public TypedQuery<X> setMaxResults(int i) {
+ super.setMaxResults(i);
+ return this;
+ }
+
+ @Override
+ public TypedQuery<X> setParameter(int i, Calendar calendar,
+ TemporalType temporalType) {
+ super.setParameter(i, calendar, temporalType);
+ return this;
+ }
+
+ @Override
+ public TypedQuery<X> setParameter(int i, Date date, TemporalType
temporalType) {
+ super.setParameter(i, date, temporalType);
+ return this;
+ }
+
+ @Override
+ public TypedQuery<X> setParameter(int i, Object o) {
+ super.setParameter(i, o);
+ return this;
+ }
+
+ @Override
+ public TypedQuery<X> setParameter(Parameter<Calendar> param, Calendar
value,
+ TemporalType temporalType) {
+ super.setParameter(param, value, temporalType);
+ return this;
+ }
+
+ @Override
+ public TypedQuery<X> setParameter(Parameter<Date> param, Date value,
+ TemporalType temporalType) {
+ super.setParameter(param, value, temporalType);
+ return this;
+ }
+
+ @Override
+ public <T> TypedQuery<X> setParameter(Parameter<T> param, T value) {
+ super.setParameter(param, value);
+ return this;
+ }
+
+ @Override
+ public TypedQuery<X> setParameter(String s, Calendar calendar,
+ TemporalType temporalType) {
+ super.setParameter(s, calendar, temporalType);
+ return this;
+ }
+
+ @Override
+ public TypedQuery<X> setParameter(String s, Date date, TemporalType
temporalType) {
+ super.setParameter(s, date, temporalType);
+ return this;
+ }
+
+ @Override
+ public TypedQuery<X> setParameter(String s, Object o) {
+ super.setParameter(s, o);
+ return this;
+ }
+
+}