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);
+       }
 }


Reply via email to