Author: timothyjward
Date: Tue Aug 16 16:49:18 2016
New Revision: 1756532
URL: http://svn.apache.org/viewvc?rev=1756532&view=rev
Log:
[tx-control] Avoid tying XA JPA resources to a single Transaction Control
service
Modified:
aries/trunk/tx-control/tx-control-jpa-itests/src/test/java/org/apache/aries/tx/control/itests/AbstractJPATransactionTest.java
aries/trunk/tx-control/tx-control-jpa-itests/src/test/java/org/apache/aries/tx/control/itests/AbstractSimpleTransactionTest.java
aries/trunk/tx-control/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/eclipse/impl/EclipseTxControlPlatform.java
aries/trunk/tx-control/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/hibernate/impl/HibernateTxControlPlatform.java
aries/trunk/tx-control/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/DelayedJPAEntityManagerProvider.java
aries/trunk/tx-control/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/JPAEntityManagerProviderFactoryImpl.java
aries/trunk/tx-control/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/JPAEntityManagerProviderImpl.java
aries/trunk/tx-control/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/ManagedJPAEMFLocator.java
aries/trunk/tx-control/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/XATxContextBindingEntityManager.java
aries/trunk/tx-control/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/openjpa/impl/OpenJPATxControlPlatform.java
aries/trunk/tx-control/tx-control-provider-jpa-xa/src/test/java/org/apache/aries/tx/control/jpa/xa/impl/XATxContextBindingEntityManagerTest.java
Modified:
aries/trunk/tx-control/tx-control-jpa-itests/src/test/java/org/apache/aries/tx/control/itests/AbstractJPATransactionTest.java
URL:
http://svn.apache.org/viewvc/aries/trunk/tx-control/tx-control-jpa-itests/src/test/java/org/apache/aries/tx/control/itests/AbstractJPATransactionTest.java?rev=1756532&r1=1756531&r2=1756532&view=diff
==============================================================================
---
aries/trunk/tx-control/tx-control-jpa-itests/src/test/java/org/apache/aries/tx/control/itests/AbstractJPATransactionTest.java
(original)
+++
aries/trunk/tx-control/tx-control-jpa-itests/src/test/java/org/apache/aries/tx/control/itests/AbstractJPATransactionTest.java
Tue Aug 16 16:49:18 2016
@@ -92,7 +92,7 @@ public abstract class AbstractJPATransac
em = configuredEntityManager(jdbcUrl);
}
- private <T> T getService(Class<T> clazz, long timeout) {
+ protected <T> T getService(Class<T> clazz, long timeout) {
try {
return getService(clazz, null, timeout);
} catch (InvalidSyntaxException e) {
@@ -100,7 +100,7 @@ public abstract class AbstractJPATransac
}
}
- private <T> T getService(Class<T> clazz, String filter, long timeout)
throws InvalidSyntaxException {
+ protected <T> T getService(Class<T> clazz, String filter, long timeout)
throws InvalidSyntaxException {
Filter f = FrameworkUtil.createFilter(filter == null ?
"(|(foo=bar)(!(foo=bar)))" : filter);
ServiceTracker<T, T> tracker = new ServiceTracker<T,
T>(context, clazz, null) {
Modified:
aries/trunk/tx-control/tx-control-jpa-itests/src/test/java/org/apache/aries/tx/control/itests/AbstractSimpleTransactionTest.java
URL:
http://svn.apache.org/viewvc/aries/trunk/tx-control/tx-control-jpa-itests/src/test/java/org/apache/aries/tx/control/itests/AbstractSimpleTransactionTest.java?rev=1756532&r1=1756531&r2=1756532&view=diff
==============================================================================
---
aries/trunk/tx-control/tx-control-jpa-itests/src/test/java/org/apache/aries/tx/control/itests/AbstractSimpleTransactionTest.java
(original)
+++
aries/trunk/tx-control/tx-control-jpa-itests/src/test/java/org/apache/aries/tx/control/itests/AbstractSimpleTransactionTest.java
Tue Aug 16 16:49:18 2016
@@ -18,15 +18,21 @@
*/
package org.apache.aries.tx.control.itests;
+import static java.util.Arrays.stream;
import static org.junit.Assert.assertEquals;
import java.util.List;
+import java.util.Optional;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import org.apache.aries.tx.control.itests.entity.Message;
+import org.junit.Assume;
import org.junit.Test;
+import org.osgi.framework.Bundle;
+import org.osgi.service.transaction.control.TransactionControl;
+import org.osgi.service.transaction.control.jpa.JPAEntityManagerProvider;
public abstract class AbstractSimpleTransactionTest extends
AbstractJPATransactionTest {
@@ -231,4 +237,23 @@ public abstract class AbstractSimpleTran
return null;
});
}
+
+ @Test
+ public void reassignTxControl() throws Exception {
+
+ Optional<Bundle> bundle = stream(context.getBundles())
+ .filter(b ->
b.getSymbolicName().equals("tx-control-provider-jpa-xa"))
+ .findAny();
+ Assume.assumeTrue(bundle.isPresent());
+
+ bundle.get().stop();
+ bundle.get().start();
+
+ txControl = getService(TransactionControl.class,
+ System.getProperty(TX_CONTROL_FILTER), 5000);
+
+ em = getService(JPAEntityManagerProvider.class,
5000).getResource(txControl);
+
+ testTx();
+ }
}
Modified:
aries/trunk/tx-control/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/eclipse/impl/EclipseTxControlPlatform.java
URL:
http://svn.apache.org/viewvc/aries/trunk/tx-control/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/eclipse/impl/EclipseTxControlPlatform.java?rev=1756532&r1=1756531&r2=1756532&view=diff
==============================================================================
---
aries/trunk/tx-control/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/eclipse/impl/EclipseTxControlPlatform.java
(original)
+++
aries/trunk/tx-control/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/eclipse/impl/EclipseTxControlPlatform.java
Tue Aug 16 16:49:18 2016
@@ -56,8 +56,8 @@ import org.osgi.service.transaction.cont
public class EclipseTxControlPlatform extends ServerPlatformBase {
- public static void setTransactionControl(TransactionControl txControl) {
- TxControlAdapter.txControl = txControl;
+ public static void
setTransactionControl(ThreadLocal<TransactionControl> txControl) {
+ TxControlAdapter.txControlToUse = txControl;
}
public EclipseTxControlPlatform(DatabaseSession newDatabaseSession) {
@@ -76,7 +76,15 @@ public class EclipseTxControlPlatform ex
* to be configured and passed in as instances. It is safe
because
* we use a separate ClassLoader every time we create the
resource.
*/
- private static TransactionControl txControl;
+ private static ThreadLocal<TransactionControl> txControlToUse;
+
+ public TransactionControl getTxControl() {
+ TransactionControl transactionControl =
txControlToUse.get();
+ if(transactionControl == null) {
+ throw new TransactionException("A No
Transaction Context could not be created because there is no associated
Transaction Control");
+ }
+ return transactionControl;
+ }
public TxControlAdapter() {
this.listenerFactory = new TxControlListenerFactory();
@@ -97,7 +105,7 @@ public class EclipseTxControlPlatform ex
@Override
protected Object getTransaction_impl() throws Exception {
- TransactionContext currentContext =
txControl.getCurrentContext();
+ TransactionContext currentContext =
getTxControl().getCurrentContext();
if(currentContext == null ||
currentContext.getTransactionStatus() == NO_TRANSACTION) {
return null;
} else {
@@ -114,7 +122,7 @@ public class EclipseTxControlPlatform ex
@Override
protected Object getTransactionStatus_impl() throws Exception {
- TransactionContext currentContext =
txControl.getCurrentContext();
+ TransactionContext currentContext =
getTxControl().getCurrentContext();
return currentContext == null ? null :
currentContext.getTransactionStatus();
}
@@ -135,7 +143,7 @@ public class EclipseTxControlPlatform ex
@Override
protected void markTransactionForRollback_impl() throws
Exception {
- txControl.setRollbackOnly();
+ getTxControl().setRollbackOnly();
}
@Override
Modified:
aries/trunk/tx-control/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/hibernate/impl/HibernateTxControlPlatform.java
URL:
http://svn.apache.org/viewvc/aries/trunk/tx-control/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/hibernate/impl/HibernateTxControlPlatform.java?rev=1756532&r1=1756531&r2=1756532&view=diff
==============================================================================
---
aries/trunk/tx-control/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/hibernate/impl/HibernateTxControlPlatform.java
(original)
+++
aries/trunk/tx-control/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/hibernate/impl/HibernateTxControlPlatform.java
Tue Aug 16 16:49:18 2016
@@ -36,6 +36,7 @@ import javax.transaction.Synchronization
import org.hibernate.ConnectionAcquisitionMode;
import org.hibernate.ConnectionReleaseMode;
import org.hibernate.HibernateException;
+import org.hibernate.TransactionException;
import org.hibernate.engine.transaction.spi.IsolationDelegate;
import org.hibernate.engine.transaction.spi.TransactionObserver;
import org.hibernate.jdbc.WorkExecutor;
@@ -50,15 +51,23 @@ import org.osgi.service.transaction.cont
import org.osgi.service.transaction.control.TransactionControl;
import org.osgi.service.transaction.control.TransactionStatus;
-public class HibernateTxControlPlatform implements
TransactionCoordinatorBuilder {
+public class HibernateTxControlPlatform implements
+ TransactionCoordinatorBuilder {
private static final long serialVersionUID = 1L;
- private final TransactionControl control;
+ private final ThreadLocal<TransactionControl> txControlToUse;
+ public HibernateTxControlPlatform(ThreadLocal<TransactionControl>
txControlToUse) {
+ this.txControlToUse = txControlToUse;
+ }
- public HibernateTxControlPlatform(TransactionControl control) {
- this.control = control;
+ public TransactionControl getTxControl() {
+ TransactionControl transactionControl = txControlToUse.get();
+ if(transactionControl == null) {
+ throw new TransactionException("A No Transaction
Context could not be created because there is no associated Transaction
Control");
+ }
+ return transactionControl;
}
@Override
@@ -102,7 +111,7 @@ public class HibernateTxControlPlatform
@Override
public void explicitJoin() {
if(!joined) {
- if(!control.activeTransaction()) {
+ if(!getTxControl().activeTransaction()) {
throw new
TransactionRequiredException("There is no transaction active to join");
}
@@ -111,7 +120,7 @@ public class HibernateTxControlPlatform
}
private void internalJoin() {
- TransactionContext currentContext =
control.getCurrentContext();
+ TransactionContext currentContext =
getTxControl().getCurrentContext();
currentContext.preCompletion(this::beforeCompletion);
currentContext.postCompletion(this::afterCompletion);
joined = true;
@@ -124,7 +133,7 @@ public class HibernateTxControlPlatform
@Override
public void pulse() {
- if (autoJoin && !joined && control.activeTransaction())
{
+ if (autoJoin && !joined &&
getTxControl().activeTransaction()) {
internalJoin();
}
}
@@ -141,7 +150,7 @@ public class HibernateTxControlPlatform
@Override
public boolean isActive() {
- return control.activeTransaction();
+ return getTxControl().activeTransaction();
}
@Override
@@ -176,7 +185,7 @@ public class HibernateTxControlPlatform
@Override
public void registerSynchronization(Synchronization
synchronization) {
- TransactionContext currentContext =
control.getCurrentContext();
+ TransactionContext currentContext =
getTxControl().getCurrentContext();
currentContext.preCompletion(synchronization::beforeCompletion);
currentContext.postCompletion(status ->
synchronization.afterCompletion(toIntStatus(status)));
}
@@ -186,7 +195,7 @@ public class HibernateTxControlPlatform
owner.beforeTransactionCompletion();
}
catch (RuntimeException re) {
- control.setRollbackOnly();
+ getTxControl().setRollbackOnly();
throw re;
}
finally {
@@ -218,29 +227,29 @@ public class HibernateTxControlPlatform
@Override
public void begin() {
- if(!control.activeTransaction()) {
+ if(!getTxControl().activeTransaction()) {
throw new IllegalStateException("There is no
existing active transaction scope");
}
}
@Override
public void commit() {
- if(!control.activeTransaction()) {
+ if(!getTxControl().activeTransaction()) {
throw new IllegalStateException("There is no
existing active transaction scope");
}
}
@Override
public void rollback() {
- if(!control.activeTransaction()) {
+ if(!getTxControl().activeTransaction()) {
throw new IllegalStateException("There is no
existing active transaction scope");
}
- control.setRollbackOnly();
+ getTxControl().setRollbackOnly();
}
@Override
public org.hibernate.resource.transaction.spi.TransactionStatus
getStatus() {
- TransactionStatus status =
control.getCurrentContext().getTransactionStatus();
+ TransactionStatus status =
getTxControl().getCurrentContext().getTransactionStatus();
switch(status) {
case ACTIVE:
return
org.hibernate.resource.transaction.spi.TransactionStatus.ACTIVE;
@@ -265,7 +274,7 @@ public class HibernateTxControlPlatform
@Override
public void markRollbackOnly() {
- control.setRollbackOnly();
+ getTxControl().setRollbackOnly();
}
@Override
@@ -283,9 +292,9 @@ public class HibernateTxControlPlatform
};
if(transacted) {
- return control.requiresNew(c);
+ return getTxControl().requiresNew(c);
} else {
- return control.notSupported(c);
+ return getTxControl().notSupported(c);
}
}
Modified:
aries/trunk/tx-control/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/DelayedJPAEntityManagerProvider.java
URL:
http://svn.apache.org/viewvc/aries/trunk/tx-control/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/DelayedJPAEntityManagerProvider.java?rev=1756532&r1=1756531&r2=1756532&view=diff
==============================================================================
---
aries/trunk/tx-control/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/DelayedJPAEntityManagerProvider.java
(original)
+++
aries/trunk/tx-control/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/DelayedJPAEntityManagerProvider.java
Tue Aug 16 16:49:18 2016
@@ -28,26 +28,23 @@ import org.osgi.service.transaction.cont
public class DelayedJPAEntityManagerProvider implements
JPAEntityManagerProvider {
- private final Function<TransactionControl, JPAEntityManagerProvider>
wireToTransactionControl;
+ private final Function<ThreadLocal<TransactionControl>,
JPAEntityManagerProvider> wireToTransactionControl;
+
+ private final ThreadLocal<TransactionControl> commonStore = new
ThreadLocal<>();
private JPAEntityManagerProvider delegate;
- private TransactionControl wiredTxControl;
-
- public DelayedJPAEntityManagerProvider(Function<TransactionControl,
JPAEntityManagerProvider> wireToTransactionControl) {
+ public
DelayedJPAEntityManagerProvider(Function<ThreadLocal<TransactionControl>,
+ JPAEntityManagerProvider> wireToTransactionControl) {
this.wireToTransactionControl = wireToTransactionControl;
}
@Override
public EntityManager getResource(TransactionControl txControl) throws
TransactionException {
synchronized (wireToTransactionControl) {
-
- if(wiredTxControl != null &&
!wiredTxControl.equals(txControl)) {
- throw new TransactionException("This
JPAEntityManagerProvider has already been wired to a different Transaction
Control service.");
- }
if(delegate == null) {
- delegate =
wireToTransactionControl.apply(txControl);
- wiredTxControl = txControl;
+ commonStore.set(txControl);
+ delegate =
wireToTransactionControl.apply(commonStore);
}
}
return delegate.getResource(txControl);
Modified:
aries/trunk/tx-control/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/JPAEntityManagerProviderFactoryImpl.java
URL:
http://svn.apache.org/viewvc/aries/trunk/tx-control/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/JPAEntityManagerProviderFactoryImpl.java?rev=1756532&r1=1756531&r2=1756532&view=diff
==============================================================================
---
aries/trunk/tx-control/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/JPAEntityManagerProviderFactoryImpl.java
(original)
+++
aries/trunk/tx-control/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/JPAEntityManagerProviderFactoryImpl.java
Tue Aug 16 16:49:18 2016
@@ -59,11 +59,11 @@ public class JPAEntityManagerProviderFac
} else {
toUse = jpaProperties;
}
- return tx.notSupported(() ->
internalBuilderCreate(emfb, toUse));
+ return tx.get().notSupported(() ->
internalBuilderCreate(emfb, toUse, tx));
});
}
- private Map<String, Object> enlistDataSource(TransactionControl tx,
Map<String, Object> jpaProperties) {
+ private Map<String, Object>
enlistDataSource(ThreadLocal<TransactionControl> tx, Map<String, Object>
jpaProperties) {
Map<String, Object> toReturn = new HashMap<>(jpaProperties);
DataSource ds = (DataSource)
jpaProperties.get("javax.persistence.jtaDataSource");
@@ -78,12 +78,12 @@ public class JPAEntityManagerProviderFac
}
private JPAEntityManagerProvider
internalBuilderCreate(EntityManagerFactoryBuilder emfb,
- Map<String, Object> jpaProperties) {
+ Map<String, Object> jpaProperties,
ThreadLocal<TransactionControl> tx) {
EntityManagerFactory emf =
emfb.createEntityManagerFactory(jpaProperties);
validateEMF(emf);
- return new JPAEntityManagerProviderImpl(emf);
+ return new JPAEntityManagerProviderImpl(emf, tx);
}
private void validateEMF(EntityManagerFactory emf) {
@@ -110,7 +110,7 @@ public class JPAEntityManagerProviderFac
checkEnlistment(resourceProviderProperties);
validateEMF(emf);
- return new JPAEntityManagerProviderImpl(emf);
+ return new JPAEntityManagerProviderImpl(emf, new
ThreadLocal<>());
}
private boolean checkEnlistment(Map<String, Object>
resourceProviderProperties) {
@@ -138,18 +138,26 @@ public class JPAEntityManagerProviderFac
}
}
- public class EnlistingDataSource implements DataSource {
-
- private final TransactionControl txControl;
+ public static class EnlistingDataSource implements DataSource {
private final DataSource delegate;
private final UUID resourceId = UUID.randomUUID();
- public EnlistingDataSource(TransactionControl txControl,
DataSource delegate) {
- this.txControl = txControl;
+ private final ThreadLocal<TransactionControl> txControlToUse;
+
+ public EnlistingDataSource(ThreadLocal<TransactionControl>
txControlToUse, DataSource delegate) {
+ this.txControlToUse = txControlToUse;
this.delegate = delegate;
}
+
+ public TransactionControl getTxControl() {
+ TransactionControl transactionControl =
txControlToUse.get();
+ if(transactionControl == null) {
+ throw new TransactionException("A No
Transaction Context could not be created because there is no associated
Transaction Control");
+ }
+ return transactionControl;
+ }
public PrintWriter getLogWriter() throws SQLException {
return delegate.getLogWriter();
@@ -188,7 +196,7 @@ public class JPAEntityManagerProviderFac
}
private Connection enlistedConnection(Callable<Connection>
supplier) {
- TransactionContext txContext =
txControl.getCurrentContext();
+ TransactionContext txContext =
getTxControl().getCurrentContext();
if (txContext == null) {
throw new TransactionException("The resource "
+ resourceId
Modified:
aries/trunk/tx-control/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/JPAEntityManagerProviderImpl.java
URL:
http://svn.apache.org/viewvc/aries/trunk/tx-control/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/JPAEntityManagerProviderImpl.java?rev=1756532&r1=1756531&r2=1756532&view=diff
==============================================================================
---
aries/trunk/tx-control/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/JPAEntityManagerProviderImpl.java
(original)
+++
aries/trunk/tx-control/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/JPAEntityManagerProviderImpl.java
Tue Aug 16 16:49:18 2016
@@ -33,12 +33,15 @@ public class JPAEntityManagerProviderImp
private final EntityManagerFactory emf;
- public JPAEntityManagerProviderImpl(EntityManagerFactory emf) {
+ private final ThreadLocal<TransactionControl> tx;
+
+ public JPAEntityManagerProviderImpl(EntityManagerFactory emf,
ThreadLocal<TransactionControl> tx) {
this.emf = emf;
+ this.tx = tx;
}
@Override
public EntityManager getResource(TransactionControl txControl) throws
TransactionException {
- return new XATxContextBindingEntityManager(txControl, emf,
uuid);
+ return new XATxContextBindingEntityManager(txControl, emf,
uuid, tx);
}
}
Modified:
aries/trunk/tx-control/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/ManagedJPAEMFLocator.java
URL:
http://svn.apache.org/viewvc/aries/trunk/tx-control/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/ManagedJPAEMFLocator.java?rev=1756532&r1=1756531&r2=1756532&view=diff
==============================================================================
---
aries/trunk/tx-control/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/ManagedJPAEMFLocator.java
(original)
+++
aries/trunk/tx-control/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/ManagedJPAEMFLocator.java
Tue Aug 16 16:49:18 2016
@@ -134,7 +134,7 @@ public class ManagedJPAEMFLocator implem
}
private void setupTransactionManager(Map<String, Object> props,
Map<String, Object> providerProps,
- TransactionControl txControl,
ServiceReference<EntityManagerFactoryBuilder> reference) {
+ ThreadLocal<TransactionControl> t,
ServiceReference<EntityManagerFactoryBuilder> reference) {
String provider = (String)
reference.getProperty(JPA_UNIT_PROVIDER);
ServiceReference<PersistenceProvider> providerRef =
getPersistenceProvider(provider);
@@ -164,8 +164,8 @@ public class ManagedJPAEMFLocator implem
ClassLoader pluginLoader =
getPluginLoader(providerBundle, txControlProviderBundle);
Class<?> pluginClazz =
pluginLoader.loadClass("org.apache.aries.tx.control.jpa.xa.hibernate.impl.HibernateTxControlPlatform");
- Object plugin =
pluginClazz.getConstructor(TransactionControl.class)
- .newInstance(txControl);
+ Object plugin =
pluginClazz.getConstructor(ThreadLocal.class)
+ .newInstance(t);
props.put("hibernate.transaction.coordinator_class", plugin);
@@ -174,8 +174,8 @@ public class ManagedJPAEMFLocator implem
ClassLoader pluginLoader =
getPluginLoader(providerBundle, txControlProviderBundle);
Class<?> pluginClazz =
pluginLoader.loadClass("org.apache.aries.tx.control.jpa.xa.openjpa.impl.OpenJPATxControlPlatform");
- Object plugin =
pluginClazz.getConstructor(TransactionControl.class)
- .newInstance(txControl);
+ Object plugin =
pluginClazz.getConstructor(ThreadLocal.class)
+ .newInstance(t);
props.put("openjpa.ManagedRuntime", plugin);
@@ -185,8 +185,8 @@ public class ManagedJPAEMFLocator implem
Class<?> pluginClazz =
pluginLoader.loadClass("org.apache.aries.tx.control.jpa.xa.eclipse.impl.EclipseTxControlPlatform");
- pluginClazz.getMethod("setTransactionControl",
TransactionControl.class)
- .invoke(null, txControl);
+ pluginClazz.getMethod("setTransactionControl",
ThreadLocal.class)
+ .invoke(null, t);
props.put("eclipselink.target-server",
pluginClazz.getName());
props.put("org.apache.aries.jpa.eclipselink.plugin.types", pluginClazz);
Modified:
aries/trunk/tx-control/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/XATxContextBindingEntityManager.java
URL:
http://svn.apache.org/viewvc/aries/trunk/tx-control/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/XATxContextBindingEntityManager.java?rev=1756532&r1=1756531&r2=1756532&view=diff
==============================================================================
---
aries/trunk/tx-control/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/XATxContextBindingEntityManager.java
(original)
+++
aries/trunk/tx-control/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/XATxContextBindingEntityManager.java
Tue Aug 16 16:49:18 2016
@@ -38,13 +38,15 @@ public class XATxContextBindingEntityMan
private final TransactionControl txControl;
private final UUID resourceId;
private final EntityManagerFactory emf;
+ private final ThreadLocal<TransactionControl> commonTxStore;
public XATxContextBindingEntityManager(TransactionControl txControl,
- EntityManagerFactory emf, UUID resourceId) {
+ EntityManagerFactory emf, UUID resourceId,
ThreadLocal<TransactionControl> commonTxStore) {
this.txControl = txControl;
this.emf = emf;
this.resourceId = resourceId;
+ this.commonTxStore = commonTxStore;
}
@Override
@@ -63,6 +65,9 @@ public class XATxContextBindingEntityMan
return existing;
}
+ TransactionControl previous = commonTxStore.get();
+ commonTxStore.set(txControl);
+
EntityManager toReturn;
EntityManager toClose;
@@ -79,6 +84,7 @@ public class XATxContextBindingEntityMan
"There is a transaction active,
but it does not support local participants");
}
} catch (Exception sqle) {
+ commonTxStore.set(previous);
throw new TransactionException(
"There was a problem getting hold of a
database connection",
sqle);
@@ -91,6 +97,7 @@ public class XATxContextBindingEntityMan
} catch (PersistenceException sqle) {
// TODO log this
}
+ commonTxStore.set(previous);
});
txContext.putScopedValue(resourceId, toReturn);
Modified:
aries/trunk/tx-control/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/openjpa/impl/OpenJPATxControlPlatform.java
URL:
http://svn.apache.org/viewvc/aries/trunk/tx-control/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/openjpa/impl/OpenJPATxControlPlatform.java?rev=1756532&r1=1756531&r2=1756532&view=diff
==============================================================================
---
aries/trunk/tx-control/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/openjpa/impl/OpenJPATxControlPlatform.java
(original)
+++
aries/trunk/tx-control/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/openjpa/impl/OpenJPATxControlPlatform.java
Tue Aug 16 16:49:18 2016
@@ -43,19 +43,33 @@ import javax.transaction.xa.XAResource;
import org.apache.openjpa.ee.ManagedRuntime;
import org.osgi.service.transaction.control.TransactionContext;
import org.osgi.service.transaction.control.TransactionControl;
+import org.osgi.service.transaction.control.TransactionException;
import org.osgi.service.transaction.control.TransactionStatus;
-public class OpenJPATxControlPlatform implements ManagedRuntime,
TransactionManager, Transaction {
+public class OpenJPATxControlPlatform implements ManagedRuntime,
+ TransactionManager, Transaction {
- private final TransactionControl txControl;
+ private final ThreadLocal<TransactionControl> txControlToUse;
- public OpenJPATxControlPlatform(TransactionControl txControl) {
- this.txControl = txControl;
+ public OpenJPATxControlPlatform(ThreadLocal<TransactionControl>
txControlToUse) {
+ this.txControlToUse = txControlToUse;
}
+
+ public TransactionControl getTxControl() {
+ TransactionControl transactionControl = txControlToUse.get();
+ if(transactionControl == null) {
+ throw new TransactionException("A No Transaction
Context could not be created because there is no associated Transaction
Control");
+ }
+ return transactionControl;
+ }
+
@Override
public void doNonTransactionalWork(Runnable arg0) throws
NotSupportedException {
- txControl.notSupported(() -> {
+
+ TransactionControl transactionControl = getTxControl();
+
+ transactionControl.notSupported(() -> {
arg0.run();
return null;
});
@@ -68,7 +82,7 @@ public class OpenJPATxControlPlatform im
@Override
public Object getTransactionKey() throws Exception, SystemException {
- return txControl.getCurrentContext().getTransactionKey();
+ return getTxControl().getCurrentContext().getTransactionKey();
}
@Override
@@ -78,17 +92,17 @@ public class OpenJPATxControlPlatform im
@Override
public void setRollbackOnly(Throwable arg0) throws Exception {
- txControl.setRollbackOnly();
+ getTxControl().setRollbackOnly();
}
@Override
public void setRollbackOnly() throws IllegalStateException,
SystemException {
- txControl.setRollbackOnly();
+ getTxControl().setRollbackOnly();
}
@Override
public int getStatus() throws SystemException {
- TransactionContext currentContext =
txControl.getCurrentContext();
+ TransactionContext currentContext =
getTxControl().getCurrentContext();
if(currentContext != null) {
return
toIntStatus(currentContext.getTransactionStatus());
}
@@ -132,14 +146,14 @@ public class OpenJPATxControlPlatform im
@Override
public boolean enlistResource(XAResource xaRes) throws
IllegalStateException, RollbackException, SystemException {
- txControl.getCurrentContext().registerXAResource(xaRes, null);
+ getTxControl().getCurrentContext().registerXAResource(xaRes,
null);
return true;
}
@Override
public void registerSynchronization(Synchronization synch)
throws IllegalStateException, RollbackException,
SystemException {
- TransactionContext currentContext =
txControl.getCurrentContext();
+ TransactionContext currentContext =
getTxControl().getCurrentContext();
currentContext.preCompletion(synch::beforeCompletion);
currentContext.postCompletion(status ->
synch.afterCompletion(toIntStatus(status)));
}
Modified:
aries/trunk/tx-control/tx-control-provider-jpa-xa/src/test/java/org/apache/aries/tx/control/jpa/xa/impl/XATxContextBindingEntityManagerTest.java
URL:
http://svn.apache.org/viewvc/aries/trunk/tx-control/tx-control-provider-jpa-xa/src/test/java/org/apache/aries/tx/control/jpa/xa/impl/XATxContextBindingEntityManagerTest.java?rev=1756532&r1=1756531&r2=1756532&view=diff
==============================================================================
---
aries/trunk/tx-control/tx-control-provider-jpa-xa/src/test/java/org/apache/aries/tx/control/jpa/xa/impl/XATxContextBindingEntityManagerTest.java
(original)
+++
aries/trunk/tx-control/tx-control-provider-jpa-xa/src/test/java/org/apache/aries/tx/control/jpa/xa/impl/XATxContextBindingEntityManagerTest.java
Tue Aug 16 16:49:18 2016
@@ -18,10 +18,11 @@
*/
package org.apache.aries.tx.control.jpa.xa.impl;
-
+import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.withSettings;
import static org.osgi.service.transaction.control.TransactionStatus.ACTIVE;
+import static org.osgi.service.transaction.control.TransactionStatus.COMMITTED;
import static
org.osgi.service.transaction.control.TransactionStatus.NO_TRANSACTION;
import java.sql.Connection;
@@ -29,6 +30,7 @@ import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
+import java.util.function.Consumer;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
@@ -39,12 +41,14 @@ import org.apache.aries.tx.control.jdbc.
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
import org.osgi.service.transaction.control.TransactionContext;
import org.osgi.service.transaction.control.TransactionControl;
import org.osgi.service.transaction.control.TransactionException;
+import org.osgi.service.transaction.control.TransactionStatus;
@RunWith(MockitoJUnitRunner.class)
public class XATxContextBindingEntityManagerTest {
@@ -70,6 +74,8 @@ public class XATxContextBindingEntityMan
XATxContextBindingEntityManager em;
+ ThreadLocal<TransactionControl> commonTxControl = new ThreadLocal<>();
+
@Before
public void setUp() throws SQLException {
Mockito.when(emf.createEntityManager()).thenReturn(rawEm).thenReturn(null);
@@ -79,7 +85,7 @@ public class XATxContextBindingEntityMan
Mockito.when(context.getScopedValue(Mockito.any()))
.thenAnswer(i -> variables.get(i.getArguments()[0]));
- em = new XATxContextBindingEntityManager(control, emf, id);
+ em = new XATxContextBindingEntityManager(control, emf, id,
commonTxControl);
}
private void setupNoTransaction() {
@@ -110,7 +116,18 @@ public class XATxContextBindingEntityMan
Mockito.verify(rawEm, times(0)).getTransaction();
Mockito.verify(context,
times(0)).registerXAResource(Mockito.any(), Mockito.anyString());
- Mockito.verify(context).postCompletion(Mockito.any());
+ checkPostCompletion(null);
+ }
+
+ private void checkPostCompletion(TransactionControl expectedAfter) {
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ ArgumentCaptor<Consumer<TransactionStatus>> captor =
+
(ArgumentCaptor)ArgumentCaptor.forClass(Consumer.class);
+ Mockito.verify(context).postCompletion(captor.capture());
+
+ captor.getValue().accept(COMMITTED);
+
+ assertEquals(expectedAfter, commonTxControl.get());
}
@Test
@@ -129,7 +146,7 @@ public class XATxContextBindingEntityMan
Mockito.verify(rawEm, times(2)).isOpen();
Mockito.verify(rawEm).joinTransaction();
- Mockito.verify(context).postCompletion(Mockito.any());
+ checkPostCompletion(null);
}
@Test
@@ -152,7 +169,7 @@ public class XATxContextBindingEntityMan
Mockito.verify(rawEm, times(2)).isOpen();
Mockito.verify(rawEm).joinTransaction();
- Mockito.verify(context).postCompletion(Mockito.any());
+ checkPostCompletion(null);
}
@Test
@@ -174,7 +191,7 @@ public class XATxContextBindingEntityMan
Mockito.verify(rawEm, times(2)).isOpen();
Mockito.verify(rawEm).joinTransaction();
- Mockito.verify(context).postCompletion(Mockito.any());
+ checkPostCompletion(null);
}
@Test
@@ -197,7 +214,7 @@ public class XATxContextBindingEntityMan
Mockito.verify(rawEm, times(2)).isOpen();
Mockito.verify(rawEm).joinTransaction();
- Mockito.verify(context).postCompletion(Mockito.any());
+ checkPostCompletion(null);
}
@Test(expected=TransactionException.class)
@@ -208,4 +225,24 @@ public class XATxContextBindingEntityMan
em.isOpen();
}
+ @Test
+ public void testActiveTransactionWithPreviousCommonTxControl() throws
SQLException {
+
+ TransactionControl previous =
Mockito.mock(TransactionControl.class);
+ Connection con = Mockito.mock(Connection.class,
withSettings().extraInterfaces(XAConnection.class));
+
Mockito.when(((XAConnection)con).getXAResource()).thenReturn(xaResource);
+
+ Mockito.when(rawEm.unwrap(Connection.class)).thenReturn(con);
+
+ setupActiveTransaction();
+ commonTxControl.set(previous);
+
+ em.isOpen();
+ em.isOpen();
+
+ Mockito.verify(rawEm, times(2)).isOpen();
+ Mockito.verify(rawEm).joinTransaction();
+
+ checkPostCompletion(previous);
+ }
}