You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by ti...@apache.org on 2018/01/24 18:39:45 UTC

[aries-tx-control] branch master updated (2d64bd6 -> f6cb1ac)

This is an automated email from the ASF dual-hosted git repository.

timothyjward pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/aries-tx-control.git.


    from 2d64bd6  Tx Control spec compliance - avoid NPEs when null Maps are passed, throw thw correct exception from joinTransaction
     new 1a21dcc  Tx Control spec compliance ensure that passed in JDBC Resource providers are properly handled
     new 1317719  Tx Control spec compliance - handle null properties being passed to the local JPA Provider Factory
     new f6cb1ac  Tx Control spec compliance - support passed in JDBC resource providers in the local JPA implementation

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../impl/DelayedJPAEntityManagerProvider.java      |  3 +-
 .../jpa/common/impl/JPAResourceActivator.java      |  4 --
 .../common}/impl/ScopedConnectionDataSource.java   |  2 +-
 .../impl/JPAEntityManagerProviderFactoryImpl.java  | 48 ++++++++++++++++----
 .../local/impl/JPAEntityManagerProviderImpl.java   | 10 ++++-
 .../jpa/local/impl/ScopedConnectionIsolator.java}  | 33 +++++++++-----
 ...ContextBindingJDBCDelegatingEntityManager.java} | 43 +++++++++---------
 .../impl/TxContextBindingEntityManagerTest.java    |  2 +-
 ...extBindingJDBCDelegatingEntityManagerTest.java} | 51 ++++++++++++----------
 .../impl/JPAEntityManagerProviderFactoryImpl.java  | 18 +++++---
 .../tx/control/jpa/xa/impl/XAJPAEMFLocator.java    |  1 +
 11 files changed, 138 insertions(+), 77 deletions(-)
 rename tx-control-providers/jpa/{tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa => tx-control-provider-jpa-common/src/main/java/org/apache/aries/tx/control/jpa/common}/impl/DelayedJPAEntityManagerProvider.java (94%)
 rename tx-control-providers/jpa/{tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa => tx-control-provider-jpa-common/src/main/java/org/apache/aries/tx/control/jpa/common}/impl/ScopedConnectionDataSource.java (96%)
 copy tx-control-providers/{jdbc/tx-control-provider-jdbc-common/src/main/java/org/apache/aries/tx/control/jdbc/common/impl/ConnectionWrapper.java => jpa/tx-control-provider-jpa-local/src/main/java/org/apache/aries/tx/control/jpa/local/impl/ScopedConnectionIsolator.java} (93%)
 copy tx-control-providers/jpa/{tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/XATxContextBindingEntityManager.java => tx-control-provider-jpa-local/src/main/java/org/apache/aries/tx/control/jpa/local/impl/TxContextBindingJDBCDelegatingEntityManager.java} (76%)
 copy tx-control-providers/jpa/tx-control-provider-jpa-local/src/test/java/org/apache/aries/tx/control/jpa/local/impl/{TxContextBindingEntityManagerTest.java => TxContextBindingJDBCDelegatingEntityManagerTest.java} (74%)

-- 
To stop receiving notification emails like this one, please contact
timothyjward@apache.org.

[aries-tx-control] 03/03: Tx Control spec compliance - support passed in JDBC resource providers in the local JPA implementation

Posted by ti...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

timothyjward pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/aries-tx-control.git

commit f6cb1acfc2a529ef8538f4273ad353bd2f086de4
Author: Tim Ward <ti...@apache.org>
AuthorDate: Wed Jan 24 13:38:25 2018 -0500

    Tx Control spec compliance - support passed in JDBC resource providers in the local JPA implementation
---
 .../impl/DelayedJPAEntityManagerProvider.java      |   3 +-
 .../jpa/common/impl/JPAResourceActivator.java      |   4 -
 .../common}/impl/ScopedConnectionDataSource.java   |   2 +-
 .../impl/JPAEntityManagerProviderFactoryImpl.java  |  42 ++-
 .../local/impl/JPAEntityManagerProviderImpl.java   |  10 +-
 .../jpa/local/impl/ScopedConnectionIsolator.java   | 291 +++++++++++++++++++++
 ...xContextBindingJDBCDelegatingEntityManager.java | 111 ++++++++
 .../impl/TxContextBindingEntityManagerTest.java    |   2 +-
 ...extBindingJDBCDelegatingEntityManagerTest.java} |  51 ++--
 .../impl/JPAEntityManagerProviderFactoryImpl.java  |   2 +
 .../tx/control/jpa/xa/impl/XAJPAEMFLocator.java    |   1 +
 11 files changed, 482 insertions(+), 37 deletions(-)

diff --git a/tx-control-providers/jpa/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/DelayedJPAEntityManagerProvider.java b/tx-control-providers/jpa/tx-control-provider-jpa-common/src/main/java/org/apache/aries/tx/control/jpa/common/impl/DelayedJPAEntityManagerProvider.java
similarity index 94%
rename from tx-control-providers/jpa/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/DelayedJPAEntityManagerProvider.java
rename to tx-control-providers/jpa/tx-control-provider-jpa-common/src/main/java/org/apache/aries/tx/control/jpa/common/impl/DelayedJPAEntityManagerProvider.java
index 3c3d516..71a70f5 100644
--- a/tx-control-providers/jpa/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/DelayedJPAEntityManagerProvider.java
+++ b/tx-control-providers/jpa/tx-control-provider-jpa-common/src/main/java/org/apache/aries/tx/control/jpa/common/impl/DelayedJPAEntityManagerProvider.java
@@ -16,13 +16,12 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.aries.tx.control.jpa.xa.impl;
+package org.apache.aries.tx.control.jpa.common.impl;
 
 import java.util.function.Function;
 
 import javax.persistence.EntityManager;
 
-import org.apache.aries.tx.control.jpa.common.impl.AbstractJPAEntityManagerProvider;
 import org.osgi.service.transaction.control.TransactionControl;
 import org.osgi.service.transaction.control.TransactionException;
 
diff --git a/tx-control-providers/jpa/tx-control-provider-jpa-common/src/main/java/org/apache/aries/tx/control/jpa/common/impl/JPAResourceActivator.java b/tx-control-providers/jpa/tx-control-provider-jpa-common/src/main/java/org/apache/aries/tx/control/jpa/common/impl/JPAResourceActivator.java
index 1b3ef75..600923a 100644
--- a/tx-control-providers/jpa/tx-control-provider-jpa-common/src/main/java/org/apache/aries/tx/control/jpa/common/impl/JPAResourceActivator.java
+++ b/tx-control-providers/jpa/tx-control-provider-jpa-common/src/main/java/org/apache/aries/tx/control/jpa/common/impl/JPAResourceActivator.java
@@ -20,14 +20,10 @@ package org.apache.aries.tx.control.jpa.common.impl;
 
 import org.apache.aries.tx.control.resource.common.impl.ResourceActivator;
 import org.osgi.service.transaction.control.jpa.JPAEntityManagerProviderFactory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 public abstract class JPAResourceActivator extends
 	ResourceActivator<AbstractJPAEntityManagerProvider, ResourceTrackingJPAEntityManagerProviderFactory>{
 
-	private static final Logger LOG = LoggerFactory.getLogger(JPAResourceActivator.class);
-	
 	@Override
 	protected Class<JPAEntityManagerProviderFactory> getAdvertisedInterface() {
 		return JPAEntityManagerProviderFactory.class;
diff --git a/tx-control-providers/jpa/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/ScopedConnectionDataSource.java b/tx-control-providers/jpa/tx-control-provider-jpa-common/src/main/java/org/apache/aries/tx/control/jpa/common/impl/ScopedConnectionDataSource.java
similarity index 96%
rename from tx-control-providers/jpa/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/ScopedConnectionDataSource.java
rename to tx-control-providers/jpa/tx-control-provider-jpa-common/src/main/java/org/apache/aries/tx/control/jpa/common/impl/ScopedConnectionDataSource.java
index 11fcfa5..d52fbc2 100644
--- a/tx-control-providers/jpa/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/ScopedConnectionDataSource.java
+++ b/tx-control-providers/jpa/tx-control-provider-jpa-common/src/main/java/org/apache/aries/tx/control/jpa/common/impl/ScopedConnectionDataSource.java
@@ -1,4 +1,4 @@
-package org.apache.aries.tx.control.jpa.xa.impl;
+package org.apache.aries.tx.control.jpa.common.impl;
 
 import java.io.PrintWriter;
 import java.sql.Connection;
diff --git a/tx-control-providers/jpa/tx-control-provider-jpa-local/src/main/java/org/apache/aries/tx/control/jpa/local/impl/JPAEntityManagerProviderFactoryImpl.java b/tx-control-providers/jpa/tx-control-provider-jpa-local/src/main/java/org/apache/aries/tx/control/jpa/local/impl/JPAEntityManagerProviderFactoryImpl.java
index 9882e23..d02a3b3 100644
--- a/tx-control-providers/jpa/tx-control-provider-jpa-local/src/main/java/org/apache/aries/tx/control/jpa/local/impl/JPAEntityManagerProviderFactoryImpl.java
+++ b/tx-control-providers/jpa/tx-control-provider-jpa-local/src/main/java/org/apache/aries/tx/control/jpa/local/impl/JPAEntityManagerProviderFactoryImpl.java
@@ -21,20 +21,26 @@ package org.apache.aries.tx.control.jpa.local.impl;
 import static java.util.Optional.ofNullable;
 import static javax.persistence.spi.PersistenceUnitTransactionType.RESOURCE_LOCAL;
 import static org.osgi.service.transaction.control.jpa.JPAEntityManagerProviderFactory.LOCAL_ENLISTMENT_ENABLED;
+import static org.osgi.service.transaction.control.jpa.JPAEntityManagerProviderFactory.TRANSACTIONAL_DB_CONNECTION;
 import static org.osgi.service.transaction.control.jpa.JPAEntityManagerProviderFactory.XA_ENLISTMENT_ENABLED;
 
 import java.util.HashMap;
 import java.util.Map;
+import java.util.function.Function;
 
 import javax.persistence.EntityManagerFactory;
 import javax.persistence.spi.PersistenceUnitTransactionType;
 import javax.sql.DataSource;
 
 import org.apache.aries.tx.control.jpa.common.impl.AbstractJPAEntityManagerProvider;
+import org.apache.aries.tx.control.jpa.common.impl.DelayedJPAEntityManagerProvider;
 import org.apache.aries.tx.control.jpa.common.impl.InternalJPAEntityManagerProviderFactory;
 import org.apache.aries.tx.control.jpa.common.impl.JPADataSourceHelper;
+import org.apache.aries.tx.control.jpa.common.impl.ScopedConnectionDataSource;
 import org.osgi.service.jpa.EntityManagerFactoryBuilder;
+import org.osgi.service.transaction.control.TransactionControl;
 import org.osgi.service.transaction.control.TransactionException;
+import org.osgi.service.transaction.control.jdbc.JDBCConnectionProvider;
 
 import com.zaxxer.hikari.HikariDataSource;
 
@@ -44,7 +50,12 @@ public class JPAEntityManagerProviderFactoryImpl implements InternalJPAEntityMan
 	public AbstractJPAEntityManagerProvider getProviderFor(EntityManagerFactoryBuilder emfb, Map<String, Object> jpaProperties,
 			Map<String, Object> resourceProviderProperties) {
 		Map<String, Object> jpaPropsToUse = jpaProperties == null ? new HashMap<>() : new HashMap<>(jpaProperties);
-		checkEnlistment(resourceProviderProperties);
+		Map<String, Object> resourceProviderPropertiesToUse = resourceProviderProperties == null ? new HashMap<>() : new HashMap<>(resourceProviderProperties);
+		checkEnlistment(resourceProviderPropertiesToUse);
+		
+		if(resourceProviderPropertiesToUse.containsKey(TRANSACTIONAL_DB_CONNECTION)) {
+			return delegateTransactionality(emfb, jpaPropsToUse, resourceProviderPropertiesToUse);
+		}
 		
 		Object found = jpaPropsToUse.get("javax.persistence.dataSource");
 		
@@ -63,7 +74,7 @@ public class JPAEntityManagerProviderFactoryImpl implements InternalJPAEntityMan
 			throw new IllegalArgumentException("The object found when checking the javax.persistence.dataSource and javax.persistence.nonJtaDataSource properties was not a DataSource.");
 		}
 		
-		DataSource toUse = JPADataSourceHelper.poolIfNecessary(resourceProviderProperties, unpooled);
+		DataSource toUse = JPADataSourceHelper.poolIfNecessary(resourceProviderPropertiesToUse, unpooled);
 		jpaPropsToUse.put("javax.persistence.dataSource", toUse);
 		jpaPropsToUse.put("javax.persistence.nonJtaDataSource", toUse);
 		
@@ -71,7 +82,7 @@ public class JPAEntityManagerProviderFactoryImpl implements InternalJPAEntityMan
 		
 		validateEMF(emf);
 		
-		return new JPAEntityManagerProviderImpl(emf, () -> {
+		return new JPAEntityManagerProviderImpl(emf, false, () -> {
 				emf.close();
 				if (toUse instanceof HikariDataSource) {
 					((HikariDataSource)toUse).close();
@@ -79,6 +90,27 @@ public class JPAEntityManagerProviderFactoryImpl implements InternalJPAEntityMan
 			});
 	}
 
+	private AbstractJPAEntityManagerProvider delegateTransactionality(EntityManagerFactoryBuilder emfb, Map<String, Object> jpaPropsToUse, Map<String, Object> resourceProviderProperties) {
+		Function<ThreadLocal<TransactionControl>, AbstractJPAEntityManagerProvider> create;
+		JDBCConnectionProvider provider = (JDBCConnectionProvider) resourceProviderProperties.get(TRANSACTIONAL_DB_CONNECTION);
+		
+		create = tx -> {
+				DataSource ds = new ScopedConnectionDataSource(
+						new ScopedConnectionIsolator(provider.getResource(tx.get())));
+				jpaPropsToUse.put("javax.persistence.dataSource", ds);
+				jpaPropsToUse.put("javax.persistence.nonJtaDataSource", ds);
+				
+				EntityManagerFactory emf = emfb.createEntityManagerFactory(jpaPropsToUse);
+				
+				validateEMF(emf);
+				
+				return new JPAEntityManagerProviderImpl(emf, true, () -> {
+						emf.close();
+					});
+			};
+		return new DelayedJPAEntityManagerProvider(create);
+	}
+
 	public AbstractJPAEntityManagerProvider getProviderFor(EntityManagerFactoryBuilder emfb, 
 			Map<String, Object> jpaProperties, Map<String, Object> resourceProviderProperties, 
 			Runnable onClose) {
@@ -88,7 +120,7 @@ public class JPAEntityManagerProviderFactoryImpl implements InternalJPAEntityMan
 		
 		validateEMF(emf);
 		
-		return new JPAEntityManagerProviderImpl(emf, () -> {
+		return new JPAEntityManagerProviderImpl(emf, false, () -> {
 			try {
 				emf.close();
 			} catch (Exception e) {
@@ -123,7 +155,7 @@ public class JPAEntityManagerProviderFactoryImpl implements InternalJPAEntityMan
 		checkEnlistment(resourceProviderProperties);
 		validateEMF(emf);
 		
-		return new JPAEntityManagerProviderImpl(emf, null);
+		return new JPAEntityManagerProviderImpl(emf, false, null);
 	}
 
 	private void checkEnlistment(Map<String, Object> resourceProviderProperties) {
diff --git a/tx-control-providers/jpa/tx-control-provider-jpa-local/src/main/java/org/apache/aries/tx/control/jpa/local/impl/JPAEntityManagerProviderImpl.java b/tx-control-providers/jpa/tx-control-provider-jpa-local/src/main/java/org/apache/aries/tx/control/jpa/local/impl/JPAEntityManagerProviderImpl.java
index d0affaa..115a5ee 100644
--- a/tx-control-providers/jpa/tx-control-provider-jpa-local/src/main/java/org/apache/aries/tx/control/jpa/local/impl/JPAEntityManagerProviderImpl.java
+++ b/tx-control-providers/jpa/tx-control-provider-jpa-local/src/main/java/org/apache/aries/tx/control/jpa/local/impl/JPAEntityManagerProviderImpl.java
@@ -30,13 +30,19 @@ import org.osgi.service.transaction.control.TransactionException;
 public class JPAEntityManagerProviderImpl extends AbstractJPAEntityManagerProvider {
 
 	private final UUID					uuid	= UUID.randomUUID();
+	
+	private final boolean				delegateEnlistment;
 
-	public JPAEntityManagerProviderImpl(EntityManagerFactory emf, Runnable onClose) {
+	public JPAEntityManagerProviderImpl(EntityManagerFactory emf, 
+			boolean delegateEnlistment, Runnable onClose) {
 		super(emf, onClose);
+		this.delegateEnlistment = delegateEnlistment;
 	}
 
 	@Override
 	public EntityManager getResource(TransactionControl txControl) throws TransactionException {
-		return new TxContextBindingEntityManager(txControl, this, uuid);
+		return delegateEnlistment ? 
+				new TxContextBindingJDBCDelegatingEntityManager(txControl, this, uuid) :
+				new TxContextBindingEntityManager(txControl, this, uuid);
 	}
 }
diff --git a/tx-control-providers/jpa/tx-control-provider-jpa-local/src/main/java/org/apache/aries/tx/control/jpa/local/impl/ScopedConnectionIsolator.java b/tx-control-providers/jpa/tx-control-provider-jpa-local/src/main/java/org/apache/aries/tx/control/jpa/local/impl/ScopedConnectionIsolator.java
new file mode 100644
index 0000000..d1f9e0a
--- /dev/null
+++ b/tx-control-providers/jpa/tx-control-provider-jpa-local/src/main/java/org/apache/aries/tx/control/jpa/local/impl/ScopedConnectionIsolator.java
@@ -0,0 +1,291 @@
+/*
+ * 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 WARRANTIESOR 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.aries.tx.control.jpa.local.impl;
+
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.CallableStatement;
+import java.sql.Clob;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.NClob;
+import java.sql.PreparedStatement;
+import java.sql.SQLClientInfoException;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+import java.sql.SQLXML;
+import java.sql.Savepoint;
+import java.sql.Statement;
+import java.sql.Struct;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.Executor;
+
+public class ScopedConnectionIsolator implements Connection {
+
+	private final Connection connection;
+	
+	public ScopedConnectionIsolator(Connection connection) {
+		this.connection = connection;
+	}
+
+	public <T> T unwrap(Class<T> iface) throws SQLException {
+		return getDelegate().unwrap(iface);
+	}
+
+	public boolean isWrapperFor(Class< ? > iface) throws SQLException {
+		return getDelegate().isWrapperFor(iface);
+	}
+
+	public Statement createStatement() throws SQLException {
+		return getDelegate().createStatement();
+	}
+
+	public PreparedStatement prepareStatement(String sql) throws SQLException {
+		return getDelegate().prepareStatement(sql);
+	}
+
+	public CallableStatement prepareCall(String sql) throws SQLException {
+		return getDelegate().prepareCall(sql);
+	}
+
+	public String nativeSQL(String sql) throws SQLException {
+		return getDelegate().nativeSQL(sql);
+	}
+
+	public void setAutoCommit(boolean autoCommit) throws SQLException {
+		// This is a no-op
+	}
+
+	public boolean getAutoCommit() throws SQLException {
+		// This is a no-op
+		return false;
+	}
+
+	public void commit() throws SQLException {
+		// This is a no-op
+	}
+
+	public void rollback() throws SQLException {
+		// This is a no-op
+	}
+
+	public void close() throws SQLException {
+		getDelegate().close();
+	}
+
+	public boolean isClosed() throws SQLException {
+		return getDelegate().isClosed();
+	}
+
+	public DatabaseMetaData getMetaData() throws SQLException {
+		return getDelegate().getMetaData();
+	}
+
+	public void setReadOnly(boolean readOnly) throws SQLException {
+		getDelegate().setReadOnly(readOnly);
+	}
+
+	public boolean isReadOnly() throws SQLException {
+		return getDelegate().isReadOnly();
+	}
+
+	public void setCatalog(String catalog) throws SQLException {
+		getDelegate().setCatalog(catalog);
+	}
+
+	public String getCatalog() throws SQLException {
+		return getDelegate().getCatalog();
+	}
+
+	public void setTransactionIsolation(int level) throws SQLException {
+		getDelegate().setTransactionIsolation(level);
+	}
+
+	public int getTransactionIsolation() throws SQLException {
+		return getDelegate().getTransactionIsolation();
+	}
+
+	public SQLWarning getWarnings() throws SQLException {
+		return getDelegate().getWarnings();
+	}
+
+	public void clearWarnings() throws SQLException {
+		getDelegate().clearWarnings();
+	}
+
+	public Statement createStatement(int resultSetType,
+			int resultSetConcurrency) throws SQLException {
+		return getDelegate().createStatement(resultSetType, resultSetConcurrency);
+	}
+
+	public PreparedStatement prepareStatement(String sql, int resultSetType,
+			int resultSetConcurrency) throws SQLException {
+		return getDelegate().prepareStatement(sql, resultSetType,
+				resultSetConcurrency);
+	}
+
+	public CallableStatement prepareCall(String sql, int resultSetType,
+			int resultSetConcurrency) throws SQLException {
+		return getDelegate().prepareCall(sql, resultSetType, resultSetConcurrency);
+	}
+
+	public Map<String,Class< ? >> getTypeMap() throws SQLException {
+		return getDelegate().getTypeMap();
+	}
+
+	public void setTypeMap(Map<String,Class< ? >> map) throws SQLException {
+		getDelegate().setTypeMap(map);
+	}
+
+	public void setHoldability(int holdability) throws SQLException {
+		getDelegate().setHoldability(holdability);
+	}
+
+	public int getHoldability() throws SQLException {
+		return getDelegate().getHoldability();
+	}
+
+	public Savepoint setSavepoint() throws SQLException {
+		// This is a no-op
+		return null;
+	}
+
+	public Savepoint setSavepoint(String name) throws SQLException {
+		// This is a no-op
+		return null;
+	}
+
+	public void rollback(Savepoint savepoint) throws SQLException {
+		// This is a no-op
+	}
+
+	public void releaseSavepoint(Savepoint savepoint) throws SQLException {
+		// This is a no-op
+	}
+
+	public Statement createStatement(int resultSetType,
+			int resultSetConcurrency, int resultSetHoldability)
+					throws SQLException {
+		return getDelegate().createStatement(resultSetType, resultSetConcurrency,
+				resultSetHoldability);
+	}
+
+	public PreparedStatement prepareStatement(String sql, int resultSetType,
+			int resultSetConcurrency, int resultSetHoldability)
+					throws SQLException {
+		return getDelegate().prepareStatement(sql, resultSetType,
+				resultSetConcurrency, resultSetHoldability);
+	}
+
+	public CallableStatement prepareCall(String sql, int resultSetType,
+			int resultSetConcurrency, int resultSetHoldability)
+					throws SQLException {
+		return getDelegate().prepareCall(sql, resultSetType, resultSetConcurrency,
+				resultSetHoldability);
+	}
+
+	public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
+			throws SQLException {
+		return getDelegate().prepareStatement(sql, autoGeneratedKeys);
+	}
+
+	public PreparedStatement prepareStatement(String sql, int[] columnIndexes)
+			throws SQLException {
+		return getDelegate().prepareStatement(sql, columnIndexes);
+	}
+
+	public PreparedStatement prepareStatement(String sql, String[] columnNames)
+			throws SQLException {
+		return getDelegate().prepareStatement(sql, columnNames);
+	}
+
+	public Clob createClob() throws SQLException {
+		return getDelegate().createClob();
+	}
+
+	public Blob createBlob() throws SQLException {
+		return getDelegate().createBlob();
+	}
+
+	public NClob createNClob() throws SQLException {
+		return getDelegate().createNClob();
+	}
+
+	public SQLXML createSQLXML() throws SQLException {
+		return getDelegate().createSQLXML();
+	}
+
+	public boolean isValid(int timeout) throws SQLException {
+		return getDelegate().isValid(timeout);
+	}
+
+	public void setClientInfo(String name, String value)
+			throws SQLClientInfoException {
+		getDelegate().setClientInfo(name, value);
+	}
+
+	public void setClientInfo(Properties properties)
+			throws SQLClientInfoException {
+		getDelegate().setClientInfo(properties);
+	}
+
+	public String getClientInfo(String name) throws SQLException {
+		return getDelegate().getClientInfo(name);
+	}
+
+	public Properties getClientInfo() throws SQLException {
+		return getDelegate().getClientInfo();
+	}
+
+	public Array createArrayOf(String typeName, Object[] elements)
+			throws SQLException {
+		return getDelegate().createArrayOf(typeName, elements);
+	}
+
+	public Struct createStruct(String typeName, Object[] attributes)
+			throws SQLException {
+		return getDelegate().createStruct(typeName, attributes);
+	}
+
+	public void setSchema(String schema) throws SQLException {
+		getDelegate().setSchema(schema);
+	}
+
+	public String getSchema() throws SQLException {
+		return getDelegate().getSchema();
+	}
+
+	public void abort(Executor executor) throws SQLException {
+		getDelegate().abort(executor);
+	}
+
+	public void setNetworkTimeout(Executor executor, int milliseconds)
+			throws SQLException {
+		getDelegate().setNetworkTimeout(executor, milliseconds);
+	}
+
+	public int getNetworkTimeout() throws SQLException {
+		return getDelegate().getNetworkTimeout();
+	}
+
+	protected Connection getDelegate() {
+		return connection;
+	}
+}
\ No newline at end of file
diff --git a/tx-control-providers/jpa/tx-control-provider-jpa-local/src/main/java/org/apache/aries/tx/control/jpa/local/impl/TxContextBindingJDBCDelegatingEntityManager.java b/tx-control-providers/jpa/tx-control-provider-jpa-local/src/main/java/org/apache/aries/tx/control/jpa/local/impl/TxContextBindingJDBCDelegatingEntityManager.java
new file mode 100644
index 0000000..aac306d
--- /dev/null
+++ b/tx-control-providers/jpa/tx-control-provider-jpa-local/src/main/java/org/apache/aries/tx/control/jpa/local/impl/TxContextBindingJDBCDelegatingEntityManager.java
@@ -0,0 +1,111 @@
+/*
+ * 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 WARRANTIESOR 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.aries.tx.control.jpa.local.impl;
+
+import static org.osgi.service.transaction.control.TransactionStatus.NO_TRANSACTION;
+import static org.osgi.service.transaction.control.TransactionStatus.ROLLED_BACK;
+
+import java.util.UUID;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceException;
+
+import org.apache.aries.tx.control.jpa.common.impl.AbstractJPAEntityManagerProvider;
+import org.apache.aries.tx.control.jpa.common.impl.EntityManagerWrapper;
+import org.apache.aries.tx.control.jpa.common.impl.ScopedEntityManagerWrapper;
+import org.apache.aries.tx.control.jpa.common.impl.TxEntityManagerWrapper;
+import org.osgi.service.transaction.control.TransactionContext;
+import org.osgi.service.transaction.control.TransactionControl;
+import org.osgi.service.transaction.control.TransactionException;
+
+public class TxContextBindingJDBCDelegatingEntityManager extends EntityManagerWrapper {
+
+	private final TransactionControl				txControl;
+	private final UUID								resourceId;
+	private final AbstractJPAEntityManagerProvider	provider;
+
+	public TxContextBindingJDBCDelegatingEntityManager(TransactionControl txControl,
+			AbstractJPAEntityManagerProvider provider, UUID resourceId) {
+		this.txControl = txControl;
+		this.provider = provider;
+		this.resourceId = resourceId;
+	}
+
+	@Override
+	protected final EntityManager getRealEntityManager() {
+
+		TransactionContext txContext = txControl.getCurrentContext();
+
+		if (txContext == null) {
+			throw new TransactionException("The resource " + provider
+					+ " cannot be accessed outside of an active Transaction Context");
+		}
+
+		EntityManager existing = (EntityManager) txContext.getScopedValue(resourceId);
+
+		if (existing != null) {
+			return existing;
+		}
+
+		EntityManager toReturn;
+		EntityManager toClose;
+
+		try {
+			if (txContext.getTransactionStatus() == NO_TRANSACTION) {
+				toClose = provider.createEntityManager();
+				toReturn = new ScopedEntityManagerWrapper(toClose);
+			} else {
+				toClose = provider.createEntityManager();
+				toReturn = new TxEntityManagerWrapper(toClose);
+				
+				txContext.preCompletion(toClose::flush);
+				toClose.getTransaction().begin();
+			}
+		} catch (Exception sqle) {
+			throw new TransactionException(
+					"There was a problem getting hold of a database connection",
+					sqle);
+		}
+		
+		txContext.postCompletion(s -> {
+				try {
+					// Make sure that the transaction ends,
+					// and that the EntityManager gets the
+					// right cache invalidation based on
+					// commit/rollback
+					if(s == ROLLED_BACK) {
+						toClose.getTransaction().rollback();
+					} else {
+						toClose.getTransaction().commit();
+					}
+				} catch (PersistenceException sqle) {
+					// TODO log this
+				}
+				try {
+					toClose.close();
+				} catch (PersistenceException sqle) {
+					// TODO log this
+				}
+			});
+		
+		txContext.putScopedValue(resourceId, toReturn);
+		
+		return toReturn;
+	}
+}
diff --git a/tx-control-providers/jpa/tx-control-provider-jpa-local/src/test/java/org/apache/aries/tx/control/jpa/local/impl/TxContextBindingEntityManagerTest.java b/tx-control-providers/jpa/tx-control-provider-jpa-local/src/test/java/org/apache/aries/tx/control/jpa/local/impl/TxContextBindingEntityManagerTest.java
index e99edb4..406cd96 100644
--- a/tx-control-providers/jpa/tx-control-provider-jpa-local/src/test/java/org/apache/aries/tx/control/jpa/local/impl/TxContextBindingEntityManagerTest.java
+++ b/tx-control-providers/jpa/tx-control-provider-jpa-local/src/test/java/org/apache/aries/tx/control/jpa/local/impl/TxContextBindingEntityManagerTest.java
@@ -82,7 +82,7 @@ public class TxContextBindingEntityManagerTest {
 		Mockito.when(context.getScopedValue(Mockito.any()))
 			.thenAnswer(i -> variables.get(i.getArguments()[0]));
 		
-		provider = new JPAEntityManagerProviderImpl(emf, null);
+		provider = new JPAEntityManagerProviderImpl(emf, false, null);
 		
 		em = new TxContextBindingEntityManager(control, provider, id);
 	}
diff --git a/tx-control-providers/jpa/tx-control-provider-jpa-local/src/test/java/org/apache/aries/tx/control/jpa/local/impl/TxContextBindingEntityManagerTest.java b/tx-control-providers/jpa/tx-control-provider-jpa-local/src/test/java/org/apache/aries/tx/control/jpa/local/impl/TxContextBindingJDBCDelegatingEntityManagerTest.java
similarity index 74%
copy from tx-control-providers/jpa/tx-control-provider-jpa-local/src/test/java/org/apache/aries/tx/control/jpa/local/impl/TxContextBindingEntityManagerTest.java
copy to tx-control-providers/jpa/tx-control-provider-jpa-local/src/test/java/org/apache/aries/tx/control/jpa/local/impl/TxContextBindingJDBCDelegatingEntityManagerTest.java
index e99edb4..1570af2 100644
--- a/tx-control-providers/jpa/tx-control-provider-jpa-local/src/test/java/org/apache/aries/tx/control/jpa/local/impl/TxContextBindingEntityManagerTest.java
+++ b/tx-control-providers/jpa/tx-control-provider-jpa-local/src/test/java/org/apache/aries/tx/control/jpa/local/impl/TxContextBindingJDBCDelegatingEntityManagerTest.java
@@ -21,12 +21,15 @@ package org.apache.aries.tx.control.jpa.local.impl;
 
 import static org.mockito.Mockito.times;
 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 static org.osgi.service.transaction.control.TransactionStatus.ROLLED_BACK;
 
 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;
@@ -40,13 +43,13 @@ import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.runners.MockitoJUnitRunner;
-import org.osgi.service.transaction.control.LocalResource;
 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 TxContextBindingEntityManagerTest {
+public class TxContextBindingJDBCDelegatingEntityManagerTest {
 
 	@Mock
 	TransactionControl control;
@@ -69,7 +72,7 @@ public class TxContextBindingEntityManagerTest {
 	
 	AbstractJPAEntityManagerProvider provider;
 	
-	TxContextBindingEntityManager em;
+	TxContextBindingJDBCDelegatingEntityManager em;
 	
 	@Before
 	public void setUp() throws SQLException {
@@ -82,9 +85,9 @@ public class TxContextBindingEntityManagerTest {
 		Mockito.when(context.getScopedValue(Mockito.any()))
 			.thenAnswer(i -> variables.get(i.getArguments()[0]));
 		
-		provider = new JPAEntityManagerProviderImpl(emf, null);
+		provider = new JPAEntityManagerProviderImpl(emf, true, null);
 		
-		em = new TxContextBindingEntityManager(control, provider, id);
+		em = new TxContextBindingJDBCDelegatingEntityManager(control, provider, id);
 	}
 	
 	private void setupNoTransaction() {
@@ -118,6 +121,7 @@ public class TxContextBindingEntityManagerTest {
 		Mockito.verify(context).postCompletion(Mockito.any());
 	}
 
+	@SuppressWarnings("unchecked")
 	@Test
 	public void testActiveTransactionCommit() throws SQLException {
 		setupActiveTransaction();
@@ -125,22 +129,28 @@ public class TxContextBindingEntityManagerTest {
 		em.isOpen();
 		em.isOpen();
 		
-		ArgumentCaptor<LocalResource> captor = ArgumentCaptor.forClass(LocalResource.class);
-
+		ArgumentCaptor<Runnable> captor = ArgumentCaptor.forClass(Runnable.class);
+		@SuppressWarnings("rawtypes")
+		ArgumentCaptor captor2 = ArgumentCaptor.forClass(Consumer.class);
+		
 		Mockito.verify(rawEm, times(2)).isOpen();
 		Mockito.verify(et).begin();
 		Mockito.verify(et, times(0)).commit();
 		Mockito.verify(et, times(0)).rollback();
-		Mockito.verify(context).registerLocalResource(captor.capture());
+		Mockito.verify(context).preCompletion(captor.capture());
 		
-		Mockito.verify(context).postCompletion(Mockito.any());
+		Mockito.verify(context).postCompletion((Consumer<TransactionStatus>) captor2.capture());
 		
-		captor.getValue().commit();
+		captor.getValue().run();
+		Mockito.verify(rawEm).flush();
+		
+		((Consumer<TransactionStatus>)captor2.getValue()).accept(COMMITTED);
 		
 		Mockito.verify(et).commit();
 		Mockito.verify(et, times(0)).rollback();
 	}
 
+	@SuppressWarnings("unchecked")
 	@Test
 	public void testActiveTransactionRollback() throws SQLException {
 		setupActiveTransaction();
@@ -148,31 +158,28 @@ public class TxContextBindingEntityManagerTest {
 		em.isOpen();
 		em.isOpen();
 		
-		ArgumentCaptor<LocalResource> captor = ArgumentCaptor.forClass(LocalResource.class);
+		ArgumentCaptor<Runnable> captor = ArgumentCaptor.forClass(Runnable.class);
+		@SuppressWarnings("rawtypes")
+		ArgumentCaptor captor2 = ArgumentCaptor.forClass(Consumer.class);
 		
 		Mockito.verify(rawEm, times(2)).isOpen();
 		Mockito.verify(et).begin();
 		Mockito.verify(et, times(0)).commit();
 		Mockito.verify(et, times(0)).rollback();
-		Mockito.verify(context).registerLocalResource(captor.capture());
+		Mockito.verify(context).preCompletion(captor.capture());
 		
-		Mockito.verify(context).postCompletion(Mockito.any());
+		Mockito.verify(context).postCompletion((Consumer<TransactionStatus>) captor2.capture());
+		
+		captor.getValue().run();
+		Mockito.verify(rawEm).flush();
 		
-		captor.getValue().rollback();
+		((Consumer<TransactionStatus>)captor2.getValue()).accept(ROLLED_BACK);
 		
 		Mockito.verify(et).rollback();
 		Mockito.verify(et, times(0)).commit();
 	}
 
 	@Test(expected=TransactionException.class)
-	public void testActiveTransactionNoLocal() throws SQLException {
-		setupActiveTransaction();
-		
-		Mockito.when(context.supportsLocal()).thenReturn(false);
-		em.isOpen();
-	}
-
-	@Test(expected=TransactionException.class)
 	public void testClosedProvider() throws SQLException {
 		setupActiveTransaction();
 		
diff --git a/tx-control-providers/jpa/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/JPAEntityManagerProviderFactoryImpl.java b/tx-control-providers/jpa/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/JPAEntityManagerProviderFactoryImpl.java
index 218e66f..51c112c 100644
--- a/tx-control-providers/jpa/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/JPAEntityManagerProviderFactoryImpl.java
+++ b/tx-control-providers/jpa/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/JPAEntityManagerProviderFactoryImpl.java
@@ -55,8 +55,10 @@ import org.apache.aries.tx.control.jdbc.common.impl.TxConnectionWrapper;
 import org.apache.aries.tx.control.jdbc.xa.connection.impl.XAConnectionWrapper;
 import org.apache.aries.tx.control.jdbc.xa.connection.impl.XADataSourceMapper;
 import org.apache.aries.tx.control.jpa.common.impl.AbstractJPAEntityManagerProvider;
+import org.apache.aries.tx.control.jpa.common.impl.DelayedJPAEntityManagerProvider;
 import org.apache.aries.tx.control.jpa.common.impl.InternalJPAEntityManagerProviderFactory;
 import org.apache.aries.tx.control.jpa.common.impl.JPADataSourceHelper;
+import org.apache.aries.tx.control.jpa.common.impl.ScopedConnectionDataSource;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.wiring.BundleWire;
diff --git a/tx-control-providers/jpa/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/XAJPAEMFLocator.java b/tx-control-providers/jpa/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/XAJPAEMFLocator.java
index 4b1a1b5..20686d2 100644
--- a/tx-control-providers/jpa/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/XAJPAEMFLocator.java
+++ b/tx-control-providers/jpa/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/XAJPAEMFLocator.java
@@ -23,6 +23,7 @@ import java.util.Map;
 
 import org.apache.aries.tx.control.jpa.common.impl.AbstractJPAEntityManagerProvider;
 import org.apache.aries.tx.control.jpa.common.impl.AbstractManagedJPAEMFLocator;
+import org.apache.aries.tx.control.jpa.common.impl.DelayedJPAEntityManagerProvider;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;

-- 
To stop receiving notification emails like this one, please contact
timothyjward@apache.org.

[aries-tx-control] 01/03: Tx Control spec compliance ensure that passed in JDBC Resource providers are properly handled

Posted by ti...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

timothyjward pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/aries-tx-control.git

commit 1a21dcc51e843bc80b1de9b52853fda40db60094
Author: Tim Ward <ti...@apache.org>
AuthorDate: Wed Jan 24 10:51:50 2018 -0500

    Tx Control spec compliance ensure that passed in JDBC Resource providers are properly handled
---
 .../jpa/xa/impl/JPAEntityManagerProviderFactoryImpl.java | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/tx-control-providers/jpa/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/JPAEntityManagerProviderFactoryImpl.java b/tx-control-providers/jpa/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/JPAEntityManagerProviderFactoryImpl.java
index fec6bb8..218e66f 100644
--- a/tx-control-providers/jpa/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/JPAEntityManagerProviderFactoryImpl.java
+++ b/tx-control-providers/jpa/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/JPAEntityManagerProviderFactoryImpl.java
@@ -25,6 +25,7 @@ import static org.apache.aries.tx.control.jpa.xa.impl.XAJPADataSourceSetup.NON_J
 import static org.osgi.service.transaction.control.TransactionStatus.NO_TRANSACTION;
 import static org.osgi.service.transaction.control.jpa.JPAEntityManagerProviderFactory.LOCAL_ENLISTMENT_ENABLED;
 import static org.osgi.service.transaction.control.jpa.JPAEntityManagerProviderFactory.PRE_ENLISTED_DB_CONNECTION;
+import static org.osgi.service.transaction.control.jpa.JPAEntityManagerProviderFactory.TRANSACTIONAL_DB_CONNECTION;
 import static org.osgi.service.transaction.control.jpa.JPAEntityManagerProviderFactory.XA_ENLISTMENT_ENABLED;
 
 import java.io.ByteArrayOutputStream;
@@ -88,13 +89,16 @@ public class JPAEntityManagerProviderFactoryImpl implements InternalJPAEntityMan
 			new HashMap<>(jpaProperties);
 		jpaPropsToUse.put(TRANSACTION_TYPE, JTA.name());
 		
+		Map<String, Object> resourceProviderPropsToUse = resourceProviderProperties == null ? new HashMap<>() :
+			new HashMap<>(resourceProviderProperties);
+		
 		Function<ThreadLocal<TransactionControl>, AbstractJPAEntityManagerProvider> create;
-		if(jpaPropsToUse.containsKey("osgi.jdbc.provider")) {
-			create = handleJDBCResourceProvider(emfb, resourceProviderProperties, jpaPropsToUse);			
+		if(resourceProviderPropsToUse.containsKey(TRANSACTIONAL_DB_CONNECTION)) {
+			create = handleJDBCResourceProvider(emfb, resourceProviderPropsToUse, jpaPropsToUse);			
 		} else if(toBoolean(jpaPropsToUse, PRE_ENLISTED_DB_CONNECTION, false)) {
-			create = handlePreEnlistedConnection(emfb, resourceProviderProperties, jpaPropsToUse);
+			create = handlePreEnlistedConnection(emfb, resourceProviderPropsToUse, jpaPropsToUse);
 		} else {
-			create = handleNormalDataSource(emfb, resourceProviderProperties, jpaPropsToUse);
+			create = handleNormalDataSource(emfb, resourceProviderPropsToUse, jpaPropsToUse);
 		}
 			
 		return new DelayedJPAEntityManagerProvider(create);
@@ -104,12 +108,12 @@ public class JPAEntityManagerProviderFactoryImpl implements InternalJPAEntityMan
 			EntityManagerFactoryBuilder emfb, Map<String, Object> resourceProviderProperties,
 			Map<String, Object> jpaPropsToUse) {
 		Function<ThreadLocal<TransactionControl>, AbstractJPAEntityManagerProvider> create;
-		JDBCConnectionProvider provider = (JDBCConnectionProvider) jpaPropsToUse.get("osgi.jdbc.provider");
+		JDBCConnectionProvider provider = (JDBCConnectionProvider) resourceProviderProperties.get(TRANSACTIONAL_DB_CONNECTION);
 		
 		create = tx -> {
 				jpaPropsToUse.put(JTA_DATA_SOURCE, 
 					new ScopedConnectionDataSource(provider.getResource(tx.get())));
-				jpaPropsToUse.put(PRE_ENLISTED_DB_CONNECTION, Boolean.TRUE);
+				resourceProviderProperties.put(PRE_ENLISTED_DB_CONNECTION, Boolean.TRUE);
 				
 				return getProviderFor(emfb, jpaPropsToUse, resourceProviderProperties, tx, null); 
 			};

-- 
To stop receiving notification emails like this one, please contact
timothyjward@apache.org.

[aries-tx-control] 02/03: Tx Control spec compliance - handle null properties being passed to the local JPA Provider Factory

Posted by ti...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

timothyjward pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/aries-tx-control.git

commit 13177193cfe29e8552eda89bd193f9106556bb4f
Author: Tim Ward <ti...@apache.org>
AuthorDate: Wed Jan 24 11:18:29 2018 -0500

    Tx Control spec compliance - handle null properties being passed to the local JPA Provider Factory
---
 .../control/jpa/local/impl/JPAEntityManagerProviderFactoryImpl.java | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/tx-control-providers/jpa/tx-control-provider-jpa-local/src/main/java/org/apache/aries/tx/control/jpa/local/impl/JPAEntityManagerProviderFactoryImpl.java b/tx-control-providers/jpa/tx-control-provider-jpa-local/src/main/java/org/apache/aries/tx/control/jpa/local/impl/JPAEntityManagerProviderFactoryImpl.java
index 4f6673a..9882e23 100644
--- a/tx-control-providers/jpa/tx-control-provider-jpa-local/src/main/java/org/apache/aries/tx/control/jpa/local/impl/JPAEntityManagerProviderFactoryImpl.java
+++ b/tx-control-providers/jpa/tx-control-provider-jpa-local/src/main/java/org/apache/aries/tx/control/jpa/local/impl/JPAEntityManagerProviderFactoryImpl.java
@@ -43,12 +43,13 @@ public class JPAEntityManagerProviderFactoryImpl implements InternalJPAEntityMan
 	@Override
 	public AbstractJPAEntityManagerProvider getProviderFor(EntityManagerFactoryBuilder emfb, Map<String, Object> jpaProperties,
 			Map<String, Object> resourceProviderProperties) {
+		Map<String, Object> jpaPropsToUse = jpaProperties == null ? new HashMap<>() : new HashMap<>(jpaProperties);
 		checkEnlistment(resourceProviderProperties);
 		
-		Object found = jpaProperties.get("javax.persistence.dataSource");
+		Object found = jpaPropsToUse.get("javax.persistence.dataSource");
 		
 		if(found == null) {
-			found = jpaProperties.get("javax.persistence.nonJtaDataSource");
+			found = jpaPropsToUse.get("javax.persistence.nonJtaDataSource");
 		}
 		
 		if(found == null) {
@@ -62,7 +63,6 @@ public class JPAEntityManagerProviderFactoryImpl implements InternalJPAEntityMan
 			throw new IllegalArgumentException("The object found when checking the javax.persistence.dataSource and javax.persistence.nonJtaDataSource properties was not a DataSource.");
 		}
 		
-		Map<String, Object> jpaPropsToUse = new HashMap<>(jpaProperties);
 		DataSource toUse = JPADataSourceHelper.poolIfNecessary(resourceProviderProperties, unpooled);
 		jpaPropsToUse.put("javax.persistence.dataSource", toUse);
 		jpaPropsToUse.put("javax.persistence.nonJtaDataSource", toUse);

-- 
To stop receiving notification emails like this one, please contact
timothyjward@apache.org.