Replace bitronix and eclipselink in persistence

Replaced bitronix transaction manager, which is not intended for production,
with jboss transaction manager.
Eliminated eclipselink so that only hibernate is used for
persistence for both JPA and drools-persistence.
Added more test cases to EntityMgrTrans to provide coverage for
various exception types.
Moved object store to features/session-persistence/jta.
Wrapped RuntimeException in specific type.
Modified test to throw specific exception type.
Converted GenSchema from an @Test to a main().
Logged caught exceptions in junit tests.

Change-Id: I4b02efc8da43d20b2dbb3c0b25adc382e80474ec
Issue-ID: POLICY-191
Signed-off-by: Jim Hahn <jrh3@att.com>
diff --git a/feature-session-persistence/src/main/feature/config/feature-session-persistence.properties b/feature-session-persistence/src/main/feature/config/feature-session-persistence.properties
index 6204b5e..0f15e3a 100644
--- a/feature-session-persistence/src/main/feature/config/feature-session-persistence.properties
+++ b/feature-session-persistence/src/main/feature/config/feature-session-persistence.properties
@@ -22,7 +22,8 @@
 javax.persistence.jdbc.url=jdbc:mariadb://${{SQL_HOST}}:3306/sessionpersistence
 javax.persistence.jdbc.user=${{SQL_USER}}
 javax.persistence.jdbc.password=${{SQL_PASSWORD}}
-hibernate.dataSource=org.mariadb.jdbc.MySQLDataSource
 
 #Seconds timeout - 15 minutes
-persistence.sessioninfo.timeout=900
\ No newline at end of file
+persistence.sessioninfo.timeout=900
+
+persistence.objectstore.dir=features/session-persistence/jta
diff --git a/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/DroolsPersistenceProperties.java b/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/DroolsPersistenceProperties.java
index 1c935b0..42a638a 100644
--- a/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/DroolsPersistenceProperties.java
+++ b/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/DroolsPersistenceProperties.java
@@ -27,10 +27,9 @@
 	 * feature-session-persistence.properties parameter key values
 	 */
 	public static final String DB_DRIVER = "javax.persistence.jdbc.driver";
-	public static final String DB_DATA_SOURCE = "hibernate.dataSource";
 	public static final String DB_URL = "javax.persistence.jdbc.url";
 	public static final String DB_USER = "javax.persistence.jdbc.user";
 	public static final String DB_PWD = "javax.persistence.jdbc.password";
-	public static final String DB_SESSIONINFO_TIMEOUT =
-									"persistence.sessioninfo.timeout";
+	public static final String DB_SESSIONINFO_TIMEOUT = "persistence.sessioninfo.timeout";
+	public static final String JTA_OBJECTSTORE_DIR = "persistence.objectstore.dir";
 }
diff --git a/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/DroolsSessionEntity.java b/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/DroolsSessionEntity.java
index e9c5b33..b3616c4 100644
--- a/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/DroolsSessionEntity.java
+++ b/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/DroolsSessionEntity.java
@@ -35,53 +35,53 @@
 public class DroolsSessionEntity implements Serializable, DroolsSession {
 
 	private static final long serialVersionUID = -5495057038819948709L;
-		
+
 	@Id
-	@Column(name="sessionName", nullable=false)
+	@Column(name = "sessionName", nullable = false)
 	private String sessionName = "-1";
-	
-	@Column(name="sessionId", nullable=false)
+
+	@Column(name = "sessionId", nullable = false)
 	private long sessionId = -1L;
-	
+
 	@Temporal(TemporalType.TIMESTAMP)
-	@Column(name="createdDate", nullable=false)
+	@Column(name = "createdDate", nullable = false)
 	private Date createdDate;
-	
+
 	@Temporal(TemporalType.TIMESTAMP)
-	@Column(name="updatedDate", nullable=false)
+	@Column(name = "updatedDate", nullable = false)
 	private Date updatedDate;
-	
-	
+
 	public DroolsSessionEntity() {
-		
+
 	}
-	
-	public DroolsSessionEntity(String sessionName,
-								long sessionId) {
+
+	public DroolsSessionEntity(String sessionName, long sessionId) {
 		this.sessionName = sessionName;
 		this.sessionId = sessionId;
-		
+
 	}
-	
+
 	@PrePersist
-	public void	prePersist() {
+	public void prePersist() {
 		this.createdDate = new Date();
 		this.updatedDate = new Date();
 	}
-	
+
 	@PreUpdate
 	public void preUpdate() {
 		this.updatedDate = new Date();
 	}
-	
+
 	@Override
 	public String getSessionName() {
 		return sessionName;
 	}
+
 	@Override
 	public void setSessionName(String sessionName) {
 		this.sessionName = sessionName;
 	}
+
 	@Override
 	public long getSessionId() {
 		return sessionId;
@@ -92,7 +92,7 @@
 		this.sessionId = sessionId;
 	}
 
-	@Override	
+	@Override
 	public Date getCreatedDate() {
 		return createdDate;
 	}
@@ -112,17 +112,16 @@
 		this.updatedDate = updatedDate;
 	}
 
-
 	@Override
-	public boolean equals(Object other){
-		if(other instanceof DroolsSession){
+	public boolean equals(Object other) {
+		if (other instanceof DroolsSession) {
 			DroolsSession p = (DroolsSession) other;
 			return this.getSessionName().equals(p.getSessionName());
-		}else{
+		} else {
 			return false;
 		}
 	}
-	
+
 	@Override
 	public int hashCode() {
 		final int prime = 31;
@@ -130,12 +129,10 @@
 		result = prime * result + getSessionName().hashCode();
 		return result;
 	}
-	
+
 	@Override
 	public String toString() {
-		return "{name=" + getSessionName()
-				+ ", id=" + getSessionId() + "}";
+		return "{name=" + getSessionName() + ", id=" + getSessionId() + "}";
 	}
 
-
 }
diff --git a/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/EntityMgrCloser.java b/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/EntityMgrCloser.java
deleted file mode 100644
index 5829211..0000000
--- a/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/EntityMgrCloser.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * feature-session-persistence
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *      http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-package org.onap.policy.drools.persistence;
-
-import javax.persistence.EntityManager;
-
-/**
- * Wrapper for an <i>EntityManager</i>, providing auto-close functionality.
- */
-public class EntityMgrCloser implements AutoCloseable {
-
-	/**
-	 * The wrapper manager.
-	 */
-	private final EntityManager em;
-
-	/**
-	 * 
-	 * @param em
-	 *            manager to be auto-closed
-	 */
-	public EntityMgrCloser(EntityManager em) {
-		this.em = em;
-	}
-
-	@Override
-	public void close() {
-		em.close();
-	}
-
-}
diff --git a/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/EntityMgrTrans.java b/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/EntityMgrTrans.java
index 79b620d..9bb26ac 100644
--- a/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/EntityMgrTrans.java
+++ b/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/EntityMgrTrans.java
@@ -21,10 +21,18 @@
 package org.onap.policy.drools.persistence;
 
 import javax.persistence.EntityManager;
-import javax.persistence.EntityTransaction;
+import javax.transaction.HeuristicMixedException;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.NotSupportedException;
+import javax.transaction.RollbackException;
+import javax.transaction.Status;
+import javax.transaction.SystemException;
+import javax.transaction.UserTransaction;
+
+import org.onap.policy.common.utils.jpa.EntityMgrCloser;
 
 /**
- * Wrapper for an <i>EntityManager</i> that creates a transaction that is
+ * Wrapper for an <i>EntityManager</i> that creates a JTA transaction that is
  * auto-rolled back when closed.
  */
 public class EntityMgrTrans extends EntityMgrCloser {
@@ -32,7 +40,7 @@
 	/**
 	 * Transaction to be rolled back.
 	 */
-	private EntityTransaction trans;
+	private static UserTransaction userTrans = com.arjuna.ats.jta.UserTransaction.userTransaction();
 
 	/**
 	 * 
@@ -43,39 +51,94 @@
 		super(em);
 
 		try {
-			trans = em.getTransaction();
-			trans.begin();
+			userTrans.begin();
+			em.joinTransaction();
 
 		} catch (RuntimeException e) {
 			em.close();
-			throw e;
+			throw new EntityMgrException(e);
+
+		} catch (NotSupportedException | SystemException e) {
+			em.close();
+			throw new EntityMgrException(e);
 		}
 	}
 
 	/**
+	 * Gets the user transaction. For use by junit tests.
+	 * 
+	 * @return the user transaction
+	 */
+	protected static UserTransaction getUserTrans() {
+		return userTrans;
+	}
+
+	/**
+	 * Sets the user transaction. For use by junit tests.
+	 * 
+	 * @param userTrans
+	 *            the new user transaction
+	 */
+	protected static void setUserTrans(UserTransaction userTrans) {
+		EntityMgrTrans.userTrans = userTrans;
+	}
+
+	/**
 	 * Commits the transaction.
 	 */
 	public void commit() {
-		trans.commit();
+		try {
+			userTrans.commit();
+
+		} catch (SecurityException | IllegalStateException | RollbackException | HeuristicMixedException
+				| HeuristicRollbackException | SystemException e) {
+
+			throw new EntityMgrException(e);
+		}
 	}
 
 	/**
 	 * Rolls back the transaction.
 	 */
 	public void rollback() {
-		trans.rollback();
+		try {
+			userTrans.rollback();
+
+		} catch (IllegalStateException | SecurityException | SystemException e) {
+			throw new EntityMgrException(e);
+		}
 	}
 
 	@Override
 	public void close() {
 		try {
-			if (trans.isActive()) {
-				trans.rollback();
+			if (userTrans.getStatus() == Status.STATUS_ACTIVE) {
+				userTrans.rollback();
 			}
 
+		} catch (IllegalStateException | SecurityException | SystemException e) {
+			throw new EntityMgrException(e);
+
 		} finally {
 			super.close();
 		}
 	}
 
+	/**
+	 * Runtime exceptions generated by this class. Wraps exceptions generated by
+	 * delegated operations, particularly when they are not, themselves, Runtime
+	 * exceptions.
+	 */
+	public static class EntityMgrException extends RuntimeException {
+		private static final long serialVersionUID = 1L;
+
+		/**
+		 * 
+		 * @param e
+		 *            exception to be wrapped
+		 */
+		public EntityMgrException(Exception e) {
+			super(e);
+		}
+	}
 }
diff --git a/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/JpaDroolsSessionConnector.java b/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/JpaDroolsSessionConnector.java
index 76c0968..cd76ae8 100644
--- a/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/JpaDroolsSessionConnector.java
+++ b/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/JpaDroolsSessionConnector.java
@@ -26,14 +26,12 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-
 public class JpaDroolsSessionConnector implements DroolsSessionConnector {
 
 	private static Logger logger = LoggerFactory.getLogger(JpaDroolsSessionConnector.class);
-		
+
 	private final EntityManagerFactory emf;
-	
-	
+
 	public JpaDroolsSessionConnector(EntityManagerFactory emf) {
 		this.emf = emf;
 	}
@@ -43,11 +41,11 @@
 
 		EntityManager em = emf.createEntityManager();
 		DroolsSessionEntity s = null;
-		
-		try(EntityMgrTrans trans = new EntityMgrTrans(em)) {
-			
+
+		try (EntityMgrTrans trans = new EntityMgrTrans(em)) {
+
 			s = em.find(DroolsSessionEntity.class, sessName);
-			if(s != null) {
+			if (s != null) {
 				em.refresh(s);
 			}
 
@@ -60,57 +58,59 @@
 	@Override
 	public void replace(DroolsSession sess) {
 		String sessName = sess.getSessionName();
-		
+
 		logger.info("replace: Entering and manually updating session name= {}", sessName);
-		
+
 		EntityManager em = emf.createEntityManager();
-		
-		try(EntityMgrTrans trans = new EntityMgrTrans(em)) {
-			
-			if( ! update(em, sess)) {
+
+		try (EntityMgrTrans trans = new EntityMgrTrans(em)) {
+
+			if (!update(em, sess)) {
 				add(em, sess);
 			}
-		
+
 			trans.commit();
 		}
-		
+
 		logger.info("replace: Exiting");
 	}
 
 	/**
 	 * Adds a session to the persistent store.
-	 * @param em	entity manager
-	 * @param sess	session to be added
+	 * 
+	 * @param em
+	 *            entity manager
+	 * @param sess
+	 *            session to be added
 	 */
 	private void add(EntityManager em, DroolsSession sess) {
 		logger.info("add: Inserting session id={}", sess.getSessionId());
 
-		DroolsSessionEntity ent =
-				new DroolsSessionEntity(
-						sess.getSessionName(),
-						sess.getSessionId());
-		
+		DroolsSessionEntity ent = new DroolsSessionEntity(sess.getSessionName(), sess.getSessionId());
+
 		em.persist(ent);
 	}
-	
+
 	/**
 	 * Updates a session, if it exists within the persistent store.
-	 * @param em	entity manager
-	 * @param sess	session data to be persisted
-	 * @return {@code true} if a record was updated, {@code false} if it
-	 * 			was not found
+	 * 
+	 * @param em
+	 *            entity manager
+	 * @param sess
+	 *            session data to be persisted
+	 * @return {@code true} if a record was updated, {@code false} if it was not
+	 *         found
 	 */
 	private boolean update(EntityManager em, DroolsSession sess) {
-		
-		DroolsSessionEntity s =
-				em.find(DroolsSessionEntity.class, sess.getSessionName());
-		if(s == null) {
+
+		DroolsSessionEntity s = em.find(DroolsSessionEntity.class, sess.getSessionName());
+		if (s == null) {
 			return false;
 		}
 
 		logger.info("update: Updating session id to {}", sess.getSessionId());
-		s.setSessionId( sess.getSessionId());
-		
+		s.setSessionId(sess.getSessionId());
+
 		return true;
 	}
 }
diff --git a/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/PersistenceFeature.java b/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/PersistenceFeature.java
index db33d05..032383b 100644
--- a/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/PersistenceFeature.java
+++ b/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/PersistenceFeature.java
@@ -21,10 +21,7 @@
 package org.onap.policy.drools.persistence;
 
 import java.io.IOException;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
 import java.sql.Connection;
-import java.sql.DriverManager;
 import java.sql.PreparedStatement;
 import java.sql.SQLException;
 import java.util.HashMap;
@@ -35,8 +32,12 @@
 
 import javax.persistence.EntityManagerFactory;
 import javax.persistence.Persistence;
+import javax.transaction.TransactionManager;
+import javax.transaction.TransactionSynchronizationRegistry;
+import javax.transaction.UserTransaction;
 
-import org.eclipse.persistence.config.PersistenceUnitProperties;
+import org.apache.commons.dbcp2.BasicDataSource;
+import org.apache.commons.dbcp2.BasicDataSourceFactory;
 import org.kie.api.KieServices;
 import org.kie.api.runtime.Environment;
 import org.kie.api.runtime.EnvironmentName;
@@ -52,11 +53,6 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import bitronix.tm.BitronixTransactionManager;
-import bitronix.tm.Configuration;
-import bitronix.tm.TransactionManagerServices;
-import bitronix.tm.resource.jdbc.PoolingDataSource;
-
 /**
  * If this feature is supported, there is a single instance of it. It adds
  * persistence to Drools sessions. In addition, if an active-standby feature
@@ -71,7 +67,6 @@
 
 	private static final Logger logger = LoggerFactory.getLogger(PersistenceFeature.class);
 
-
 	/**
 	 * Standard factory used to get various items.
 	 */
@@ -88,11 +83,6 @@
 	private KieServices kieSvcFact;
 
 	/**
-	 * Host name.
-	 */
-	private String hostName;
-
-	/**
 	 * Persistence properties.
 	 */
 	private Properties persistProps;
@@ -159,10 +149,8 @@
 	 */
 	@Override
 	public void globalInit(String args[], String configDir) {
-		
-		kieSvcFact = fact.getKieServices();
 
-		initHostName();
+		kieSvcFact = fact.getKieServices();
 
 		try {
 			persistProps = fact.loadProperties(configDir + "/feature-session-persistence.properties");
@@ -172,10 +160,6 @@
 		}
 
 		sessionInfoTimeoutMs = getPersistenceTimeout();
-
-		Configuration bitronixConfiguration = fact.getTransMgrConfig();
-		bitronixConfiguration.setJournal(null);
-		bitronixConfiguration.setServerId(hostName);
 	}
 
 	/**
@@ -199,6 +183,7 @@
 	 */
 	@Override
 	public PolicySession.ThreadModel selectThreadModel(PolicySession session) {
+
 		PolicyContainer policyContainer = session.getPolicyContainer();
 		if (isPersistenceEnabled(policyContainer, session.getName())) {
 			return new PersistentThreadModel(session, getProperties(policyContainer));
@@ -211,10 +196,10 @@
 	 */
 	@Override
 	public void disposeKieSession(PolicySession policySession) {
-		
+
 		ContainerAdjunct contAdj = (ContainerAdjunct) policySession.getPolicyContainer().getAdjunct(this);
-		if(contAdj != null) {
-			contAdj.disposeKieSession( policySession.getName());
+		if (contAdj != null) {
+			contAdj.disposeKieSession(policySession.getName());
 		}
 	}
 
@@ -225,8 +210,8 @@
 	public void destroyKieSession(PolicySession policySession) {
 
 		ContainerAdjunct contAdj = (ContainerAdjunct) policySession.getPolicyContainer().getAdjunct(this);
-		if(contAdj != null) {
-			contAdj.destroyKieSession( policySession.getName());
+		if (contAdj != null) {
+			contAdj.destroyKieSession(policySession.getName());
 		}
 	}
 
@@ -291,25 +276,12 @@
 
 		} catch (NumberFormatException e) {
 			logger.error("Invalid value for Drools persistence property persistence.sessioninfo.timeout: {}",
-					 timeoutString, e);
+					timeoutString, e);
 		}
 
 		return -1;
 	}
 
-	/**
-	 * Initializes {@link #hostName}.
-	 */
-	private void initHostName() {
-
-		try {
-			hostName = fact.getHostName();
-
-		} catch (UnknownHostException e) {
-			throw new RuntimeException("cannot determine local hostname", e);
-		}
-	}
-
 	/* ============================================================ */
 
 	/**
@@ -322,11 +294,11 @@
 		 * 'PolicyContainer' instance that this adjunct is extending.
 		 */
 		private PolicyContainer policyContainer;
-		
+
 		/**
 		 * Maps a KIE session name to its data source.
 		 */
-		private Map<String,PoolingDataSource> name2ds = new HashMap<>();
+		private Map<String, DsEmf> name2ds = new HashMap<>();
 
 		/**
 		 * Constructor - initialize a new 'ContainerAdjunct'
@@ -352,89 +324,48 @@
 		 */
 		private KieSession newPersistentKieSession(String name, String kieBaseName) {
 
-			long desiredSessionId;
+			configureSysProps();
 
-			DroolsSessionConnector conn = getDroolsSessionConnector("onapPU");
+			BasicDataSource ds = fact.makeDataSource(getDataSourceProperties());
+			DsEmf dsemf = new DsEmf(ds);
 
-			desiredSessionId = getSessionId(conn, name);
+			try {
+				EntityManagerFactory emf = dsemf.emf;
+				DroolsSessionConnector conn = fact.makeJpaConnector(emf);
 
-			logger.info("\n\nThis controller is primary... coming up with session {} \n\n", desiredSessionId);
+				long desiredSessionId = getSessionId(conn, name);
 
-			// session does not exist -- attempt to create one
-			logger.info("getPolicySession:session does not exist -- attempt to create one with name {}", name);
+				logger.info("\n\nThis controller is primary... coming up with session {} \n\n", desiredSessionId);
 
-			System.getProperties().put("java.naming.factory.initial", "bitronix.tm.jndi.BitronixInitialContextFactory");
+				// session does not exist -- attempt to create one
+				logger.info("getPolicySession:session does not exist -- attempt to create one with name {}", name);
 
-			Environment env = kieSvcFact.newEnvironment();
-			String dsName = loadDataSource(name);
+				Environment env = kieSvcFact.newEnvironment();
 
-			configureKieEnv(name, env, dsName);
+				configureKieEnv(env, emf);
 
-			KieSessionConfiguration kConf = kieSvcFact.newKieSessionConfiguration();
+				KieSessionConfiguration kConf = kieSvcFact.newKieSessionConfiguration();
 
-			KieSession kieSession = desiredSessionId >= 0 ? loadKieSession(kieBaseName, desiredSessionId, env, kConf)
-					: null;
+				KieSession kieSession = (desiredSessionId >= 0
+						? loadKieSession(kieBaseName, desiredSessionId, env, kConf) : null);
 
-			if (kieSession == null) {
-				// loadKieSession() returned null or desiredSessionId < 0
-				logger.info("LOADING We cannot load session {}. Going to create a new one", desiredSessionId);
+				if (kieSession == null) {
+					// loadKieSession() returned null or desiredSessionId < 0
+					logger.info("LOADING We cannot load session {}. Going to create a new one", desiredSessionId);
 
-				kieSession = newKieSession(kieBaseName, env);
+					kieSession = newKieSession(kieBaseName, env);
+				}
+
+				replaceSession(conn, name, kieSession);
+
+				name2ds.put(name, dsemf);
+
+				return kieSession;
+
+			} catch (RuntimeException e) {
+				dsemf.close();
+				throw e;
 			}
-
-			replaceSession(conn, name, kieSession);
-
-			return kieSession;
-		}
-
-		/**
-		 * Loads a data source into {@link #name2ds}, if one doesn't exist
-		 * yet.
-		 * @param sessName		session name
-		 * @return the unique data source name
-		 */
-		private String loadDataSource(String sessName) {
-			PoolingDataSource ds = name2ds.get(sessName);
-			
-			if(ds == null) {
-				Properties props = new Properties();
-				addOptProp(props, "URL", persistProps.getProperty(DroolsPersistenceProperties.DB_URL));
-				addOptProp(props, "user", persistProps.getProperty(DroolsPersistenceProperties.DB_USER));
-				addOptProp(props, "password", persistProps.getProperty(DroolsPersistenceProperties.DB_PWD));
-
-				ds = fact.makePoolingDataSource();
-				ds.setUniqueName("jdbc/BitronixJTADataSource/" + sessName);
-				ds.setClassName(persistProps.getProperty(DroolsPersistenceProperties.DB_DATA_SOURCE));
-				ds.setMaxPoolSize(3);
-				ds.setIsolationLevel("SERIALIZABLE");
-				ds.setAllowLocalTransactions(true);
-				ds.getDriverProperties().putAll(props);
-				ds.init();
-				
-				name2ds.put(sessName, ds);
-			}
-			
-			return ds.getUniqueName();
-		}
-
-		/**
-		 * Configures a Kie Environment
-		 * 
-		 * @param name
-		 * 				session name
-		 * @param env
-		 * 				environment to be configured
-		 * @param dsName 
-		 * 				data source name
-		 */
-		private void configureKieEnv(String name, Environment env, String dsName) {
-			Properties emfProperties = new Properties();
-			emfProperties.setProperty(PersistenceUnitProperties.JTA_DATASOURCE, dsName);
-			
-			EntityManagerFactory emfact = fact.makeEntMgrFact("onapsessionsPU", emfProperties);
-
-			env.set(EnvironmentName.ENTITY_MANAGER_FACTORY, emfact);
-			env.set(EnvironmentName.TRANSACTION_MANAGER, fact.getTransMgr());
 		}
 
 		/**
@@ -487,7 +418,9 @@
 
 		/**
 		 * Closes the data source associated with a session.
-		 * @param name	name of the session being destroyed
+		 * 
+		 * @param name
+		 *            name of the session being destroyed
 		 */
 		private void destroyKieSession(String name) {
 			closeDataSource(name);
@@ -495,7 +428,9 @@
 
 		/**
 		 * Closes the data source associated with a session.
-		 * @param name	name of the session being disposed of
+		 * 
+		 * @param name
+		 *            name of the session being disposed of
 		 */
 		private void disposeKieSession(String name) {
 			closeDataSource(name);
@@ -503,11 +438,13 @@
 
 		/**
 		 * Closes the data source associated with a session.
-		 * @param name	name of the session whose data source is to be closed
+		 * 
+		 * @param name
+		 *            name of the session whose data source is to be closed
 		 */
 		private void closeDataSource(String name) {
-			PoolingDataSource ds = name2ds.remove(name);
-			if(ds != null) {
+			DsEmf ds = name2ds.remove(name);
+			if (ds != null) {
 				ds.close();
 			}
 		}
@@ -516,6 +453,53 @@
 	/* ============================================================ */
 
 	/**
+	 * Configures java system properties for JPA/JTA.
+	 */
+	private void configureSysProps() {
+		System.setProperty("com.arjuna.ats.arjuna.coordinator.defaultTimeout", "60");
+		System.setProperty("com.arjuna.ats.arjuna.objectstore.objectStoreDir",
+				persistProps.getProperty(DroolsPersistenceProperties.JTA_OBJECTSTORE_DIR));
+		System.setProperty("ObjectStoreEnvironmentBean.objectStoreDir",
+				persistProps.getProperty(DroolsPersistenceProperties.JTA_OBJECTSTORE_DIR));
+	}
+
+	/**
+	 * Gets the data source properties.
+	 * 
+	 * @return the data source properties
+	 */
+	private Properties getDataSourceProperties() {
+		Properties props = new Properties();
+		props.put("driverClassName", persistProps.getProperty(DroolsPersistenceProperties.DB_DRIVER));
+		props.put("url", persistProps.getProperty(DroolsPersistenceProperties.DB_URL));
+		props.put("username", persistProps.getProperty(DroolsPersistenceProperties.DB_USER));
+		props.put("password", persistProps.getProperty(DroolsPersistenceProperties.DB_PWD));
+		props.put("maxActive", "3");
+		props.put("maxIdle", "1");
+		props.put("maxWait", "120000");
+		props.put("whenExhaustedAction", "2");
+		props.put("testOnBorrow", "false");
+		props.put("poolPreparedStatements", "true");
+
+		return props;
+	}
+
+	/**
+	 * Configures a Kie Environment
+	 * 
+	 * @param env
+	 *            environment to be configured
+	 * @param emf
+	 *            entity manager factory
+	 */
+	private void configureKieEnv(Environment env, EntityManagerFactory emf) {
+		env.set(EnvironmentName.ENTITY_MANAGER_FACTORY, emf);
+		env.set(EnvironmentName.TRANSACTION, fact.getUserTrans());
+		env.set(EnvironmentName.TRANSACTION_SYNCHRONIZATION_REGISTRY, fact.getTransSyncReg());
+		env.set(EnvironmentName.TRANSACTION_MANAGER, fact.getTransMgr());
+	}
+
+	/**
 	 * Removes "old" Drools 'sessioninfo' records, so they aren't used to
 	 * restore data to Drools sessions. This also has the useful side-effect of
 	 * removing abandoned records as well.
@@ -534,21 +518,15 @@
 				return;
 			}
 
-			// get DB connection properties
-			String url = persistProps.getProperty(DroolsPersistenceProperties.DB_URL);
-			String user = persistProps.getProperty(DroolsPersistenceProperties.DB_USER);
-			String password = persistProps.getProperty(DroolsPersistenceProperties.DB_PWD);
-
-			if (url == null || user == null || password == null) {
-				logger.error("Missing DB properties for clean up of sessioninfo table");
-				return;
-			}
-
 			// now do the record deletion
-			try (Connection connection = fact.makeDbConnection(url, user, password);
+			try (BasicDataSource ds = fact.makeDataSource(getDataSourceProperties());
+					Connection connection = ds.getConnection();
 					PreparedStatement statement = connection.prepareStatement(
 							"DELETE FROM sessioninfo WHERE timestampdiff(second,lastmodificationdate,now()) > ?")) {
-				statement.setLong(1, sessionInfoTimeoutMs/1000);
+
+				connection.setAutoCommit(true);
+
+				statement.setLong(1, sessionInfoTimeoutMs / 1000);
 
 				int count = statement.executeUpdate();
 				logger.info("Cleaning up sessioninfo table -- {} records removed", count);
@@ -565,40 +543,6 @@
 	}
 
 	/**
-	 * Gets a connector for manipulating DroolsSession objects within the
-	 * persistent store.
-	 * 
-	 * @param pu
-	 * @return a connector for DroolsSession objects
-	 */
-	private DroolsSessionConnector getDroolsSessionConnector(String pu) {
-
-		Properties propMap = new Properties();
-		addOptProp(propMap, "javax.persistence.jdbc.driver",
-				persistProps.getProperty(DroolsPersistenceProperties.DB_DRIVER));
-		addOptProp(propMap, "javax.persistence.jdbc.url", persistProps.getProperty(DroolsPersistenceProperties.DB_URL));
-		addOptProp(propMap, "javax.persistence.jdbc.user",
-				persistProps.getProperty(DroolsPersistenceProperties.DB_USER));
-		addOptProp(propMap, "javax.persistence.jdbc.password",
-				persistProps.getProperty(DroolsPersistenceProperties.DB_PWD));
-
-		return fact.makeJpaConnector(pu, propMap);
-	}
-
-	/**
-	 * Adds an optional property to a set of properties.
-	 * @param propMap	map into which the property should be added
-	 * @param name		property name
-	 * @param value		property value, or {@code null} if it should not
-	 * 					be added
-	 */
-	private void addOptProp(Properties propMap, String name, String value) {
-		if (value != null) {
-			propMap.put(name, value);
-		}
-	}
-
-	/**
 	 * Gets a session's ID from the persistent store.
 	 * 
 	 * @param conn
@@ -613,8 +557,8 @@
 	}
 
 	/**
-	 * Replaces a session within the persistent store, if it exists.  Adds
-	 * it otherwise.
+	 * Replaces a session within the persistent store, if it exists. Adds it
+	 * otherwise.
 	 * 
 	 * @param conn
 	 *            persistence connector
@@ -665,7 +609,7 @@
 	 */
 	private Properties getProperties(PolicyContainer container) {
 		try {
-			return fact.getPolicyContainer(container).getProperties();
+			return fact.getPolicyController(container).getProperties();
 		} catch (IllegalArgumentException e) {
 			logger.error("getProperties exception: ", e);
 			return null;
@@ -705,7 +649,7 @@
 	 * compatible with persistence.
 	 */
 	public class PersistentThreadModel implements Runnable, PolicySession.ThreadModel {
-		
+
 		/**
 		 * Session associated with this persistent thread.
 		 */
@@ -715,22 +659,22 @@
 		 * The session thread.
 		 */
 		private final Thread thread;
-		
+
 		/**
 		 * Used to indicate that processing should stop.
 		 */
 		private final CountDownLatch stopped = new CountDownLatch(1);
-		
+
 		/**
-		 * Minimum time, in milli-seconds, that the thread should sleep
-		 * before firing rules again.
+		 * Minimum time, in milli-seconds, that the thread should sleep before
+		 * firing rules again.
 		 */
 		long minSleepTime = 100;
-		
+
 		/**
-		 * Maximum time, in milli-seconds, that the thread should sleep
-		 * before firing rules again.  This is a "half" time, so that
-		 * we can multiply it by two without overflowing the word size.
+		 * Maximum time, in milli-seconds, that the thread should sleep before
+		 * firing rules again. This is a "half" time, so that we can multiply it
+		 * by two without overflowing the word size.
 		 */
 		long halfMaxSleepTime = 5000L / 2L;
 
@@ -745,11 +689,11 @@
 		public PersistentThreadModel(PolicySession session, Properties properties) {
 			this.session = session;
 			this.thread = new Thread(this, getThreadName());
-			
+
 			if (properties == null) {
 				return;
 			}
-			
+
 			// extract 'minSleepTime' and/or 'maxSleepTime'
 			String name = session.getName();
 
@@ -782,8 +726,8 @@
 				minSleepTime = maxSleepTime;
 				maxSleepTime = tmp;
 			}
-			
-			halfMaxSleepTime = Math.max(1, maxSleepTime/2);
+
+			halfMaxSleepTime = Math.max(1, maxSleepTime / 2);
 		}
 
 		/**
@@ -812,18 +756,18 @@
 		public void stop() {
 			// tell the thread to stop
 			stopped.countDown();
-			
+
 			// wait up to 10 seconds for the thread to stop
 			try {
 				thread.join(10000);
-				
+
 			} catch (InterruptedException e) {
 				logger.error("stopThread exception: ", e);
 				Thread.currentThread().interrupt();
 			}
-			
+
 			// verify that it's done
-			if(thread.isAlive()) {
+			if (thread.isAlive()) {
 				logger.error("stopThread: still running");
 			}
 		}
@@ -847,7 +791,7 @@
 		@Override
 		public void run() {
 			logger.info("PersistentThreadModel running");
-			
+
 			// set thread local variable
 			session.setPolicySession();
 
@@ -856,33 +800,34 @@
 
 			// We want to continue, despite any exceptions that occur
 			// while rules are fired.
-			
-			for(;;) {
-			
+
+			for (;;) {
+
 				try {
 					if (kieSession.fireAllRules() > 0) {
 						// some rules fired -- reduce poll delay
-						sleepTime = Math.max(minSleepTime, sleepTime/2);
+						sleepTime = Math.max(minSleepTime, sleepTime / 2);
 					} else {
 						// no rules fired -- increase poll delay
 						sleepTime = 2 * Math.min(halfMaxSleepTime, sleepTime);
 					}
+
 				} catch (Exception | LinkageError e) {
 					logger.error("Exception during kieSession.fireAllRules", e);
-				}				
-			
+				}
+
 				try {
-					if(stopped.await(sleepTime, TimeUnit.MILLISECONDS)) {
+					if (stopped.await(sleepTime, TimeUnit.MILLISECONDS)) {
 						break;
 					}
-					
+
 				} catch (InterruptedException e) {
 					logger.error("startThread exception: ", e);
 					Thread.currentThread().interrupt();
 					break;
 				}
 			}
-			
+
 			logger.info("PersistentThreadModel completed");
 		}
 	}
@@ -890,26 +835,95 @@
 	/* ============================================================ */
 
 	/**
+	 * DataSource-EntityManagerFactory pair.
+	 */
+	private class DsEmf {
+		private BasicDataSource bds;
+		private EntityManagerFactory emf;
+
+		/**
+		 * Makes an entity manager factory for the given data source.
+		 * 
+		 * @param bds
+		 *            pooled data source
+		 */
+		public DsEmf(BasicDataSource bds) {
+			try {
+				Map<String, Object> props = new HashMap<>();
+				props.put(org.hibernate.cfg.Environment.JPA_JTA_DATASOURCE, bds);
+
+				this.bds = bds;
+				this.emf = fact.makeEntMgrFact(props);
+
+			} catch (RuntimeException e) {
+				closeDataSource();
+				throw e;
+			}
+		}
+
+		/**
+		 * Closes the entity manager factory and the data source.
+		 */
+		public void close() {
+			try {
+				emf.close();
+
+			} catch (RuntimeException e) {
+				closeDataSource();
+				throw e;
+			}
+
+			closeDataSource();
+		}
+
+		/**
+		 * Closes the data source only.
+		 */
+		private void closeDataSource() {
+			try {
+				bds.close();
+
+			} catch (SQLException e) {
+				throw new PersistenceFeatureException(e);
+			}
+
+		}
+	}
+
+	private static class SingletonRegistry {
+		private static final TransactionSynchronizationRegistry transreg = new com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionSynchronizationRegistryImple();
+	}
+
+	/**
 	 * Factory for various items. Methods can be overridden for junit testing.
 	 */
 	protected static class Factory {
 
 		/**
-		 * Gets the configuration for the transaction manager.
-		 * 
-		 * @return the configuration for the transaction manager
-		 */
-		public Configuration getTransMgrConfig() {
-			return TransactionManagerServices.getConfiguration();
-		}
-
-		/**
 		 * Gets the transaction manager.
 		 * 
 		 * @return the transaction manager
 		 */
-		public BitronixTransactionManager getTransMgr() {
-			return TransactionManagerServices.getTransactionManager();
+		public TransactionManager getTransMgr() {
+			return com.arjuna.ats.jta.TransactionManager.transactionManager();
+		}
+
+		/**
+		 * Gets the user transaction.
+		 * 
+		 * @return the user transaction
+		 */
+		public UserTransaction getUserTrans() {
+			return com.arjuna.ats.jta.UserTransaction.userTransaction();
+		}
+
+		/**
+		 * Gets the transaction synchronization registry.
+		 * 
+		 * @return the transaction synchronization registry
+		 */
+		public TransactionSynchronizationRegistry getTransSyncReg() {
+			return SingletonRegistry.transreg;
 		}
 
 		/**
@@ -922,17 +936,6 @@
 		}
 
 		/**
-		 * Gets the current host name.
-		 * 
-		 * @return the current host name, associated with the IP address of the
-		 *         local machine
-		 * @throws UnknownHostException
-		 */
-		public String getHostName() throws UnknownHostException {
-			return InetAddress.getLocalHost().getHostName();
-		}
-
-		/**
 		 * Loads properties from a file.
 		 * 
 		 * @param filenm
@@ -946,58 +949,41 @@
 		}
 
 		/**
-		 * Makes a connection to the DB.
+		 * Makes a Data Source.
 		 * 
-		 * @param url
-		 *            DB URL
-		 * @param user
-		 *            user name
-		 * @param pass
-		 *            password
-		 * @return a new DB connection
-		 * @throws SQLException
+		 * @param dsProps
+		 *            data source properties
+		 * @return a new data source
 		 */
-		public Connection makeDbConnection(String url, String user, String pass) throws SQLException {
+		public BasicDataSource makeDataSource(Properties dsProps) {
+			try {
+				return BasicDataSourceFactory.createDataSource(dsProps);
 
-			return DriverManager.getConnection(url, user, pass);
-		}
-
-		/**
-		 * Makes a new pooling data source.
-		 * 
-		 * @return a new pooling data source
-		 */
-		public PoolingDataSource makePoolingDataSource() {
-			return new PoolingDataSource();
+			} catch (Exception e) {
+				throw new PersistenceFeatureException(e);
+			}
 		}
 
 		/**
 		 * Makes a new JPA connector for drools sessions.
 		 * 
-		 * @param pu
-		 *            PU for the entity manager factory
-		 * @param propMap
-		 *            properties with which the factory should be configured
+		 * @param emf
+		 *            entity manager factory
 		 * @return a new JPA connector for drools sessions
 		 */
-		public DroolsSessionConnector makeJpaConnector(String pu, Properties propMap) {
-
-			EntityManagerFactory emf = makeEntMgrFact(pu, propMap);
-
+		public DroolsSessionConnector makeJpaConnector(EntityManagerFactory emf) {
 			return new JpaDroolsSessionConnector(emf);
 		}
 
 		/**
 		 * Makes a new entity manager factory.
 		 * 
-		 * @param pu
-		 *            PU for the entity manager factory
-		 * @param propMap
+		 * @param props
 		 *            properties with which the factory should be configured
 		 * @return a new entity manager factory
 		 */
-		public EntityManagerFactory makeEntMgrFact(String pu, Properties propMap) {
-			return Persistence.createEntityManagerFactory(pu, propMap);
+		public EntityManagerFactory makeEntMgrFact(Map<String, Object> props) {
+			return Persistence.createEntityManagerFactory("onapsessionsPU", props);
 		}
 
 		/**
@@ -1007,8 +993,26 @@
 		 *            container whose controller is to be retrieved
 		 * @return the container's controller
 		 */
-		public PolicyController getPolicyContainer(PolicyContainer container) {
+		public PolicyController getPolicyController(PolicyContainer container) {
 			return PolicyController.factory.get(container.getGroupId(), container.getArtifactId());
 		}
 	}
+
+	/**
+	 * Runtime exceptions generated by this class. Wraps exceptions generated by
+	 * delegated operations, particularly when they are not, themselves, Runtime
+	 * exceptions.
+	 */
+	public static class PersistenceFeatureException extends RuntimeException {
+		private static final long serialVersionUID = 1L;
+
+		/**
+		 * 
+		 * @param e
+		 *            exception to be wrapped
+		 */
+		public PersistenceFeatureException(Exception e) {
+			super(e);
+		}
+	}
 }
diff --git a/feature-session-persistence/src/main/resources/META-INF/persistence.xml b/feature-session-persistence/src/main/resources/META-INF/persistence.xml
index 7ddd2fd..6b8345c 100644
--- a/feature-session-persistence/src/main/resources/META-INF/persistence.xml
+++ b/feature-session-persistence/src/main/resources/META-INF/persistence.xml
@@ -23,20 +23,10 @@
 	xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
 
-	<persistence-unit name="onapPU" transaction-type="RESOURCE_LOCAL">
-	<!-- This is for database access by non-drools methods -->
-		<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
-		<class>org.onap.policy.drools.persistence.DroolsSessionEntity</class>
-		<class>org.drools.persistence.info.SessionInfo</class>
-		<class>org.drools.persistence.info.WorkItemInfo</class>
-		<properties>
-			<!-- Properties are passed in -->
-        </properties>
-	</persistence-unit>
-	
 	<persistence-unit name="onapsessionsPU" transaction-type="JTA">
 	<!-- Used for drools session data access -->
-		<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>		
+		<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
+		<class>org.onap.policy.drools.persistence.DroolsSessionEntity</class>
 		<class>org.drools.persistence.info.SessionInfo</class>
 		<class>org.drools.persistence.info.WorkItemInfo</class>
 		<properties>
@@ -44,18 +34,19 @@
 			<property name="hibernate.max_fetch_depth" value="3" />
 			<property name="hibernate.hbm2ddl.auto" value="update" />
 			<property name="hibernate.show_sql" value="false" />
-			<property name="hibernate.transaction.manager_lookup_class"
-				value="org.hibernate.transaction.BTMTransactionManagerLookup" />
+			<property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.JTATransactionFactory" />
+			<property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup" />
 		</properties>
 	</persistence-unit>
 	
 	<persistence-unit name="schemaDroolsPU" transaction-type="RESOURCE_LOCAL">
 	<!-- Limited use for generating the DB and schema files for drools DB - uses eclipselink for convenience -->
-		<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
+		<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
 		<class>org.onap.policy.drools.persistence.DroolsSessionEntity</class>
 		<class>org.drools.persistence.info.SessionInfo</class>
 		<class>org.drools.persistence.info.WorkItemInfo</class>
 		<properties>
+			<property name="hibernate.dialect" value="org.hibernate.dialect.MariaDBDialect" />
 			<property name="javax.persistence.schema-generation.scripts.action" value="drop-and-create"/> 
             <property name="javax.persistence.schema-generation.scripts.create-target" value="sql/generatedCreateDrools.ddl"/>
             <property name="javax.persistence.schema-generation.scripts.drop-target" value="sql/generatedDropDrools.ddl"/>
diff --git a/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/DroolsSessionEntityTest.java b/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/DroolsSessionEntityTest.java
index c7fa848..7624d04 100644
--- a/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/DroolsSessionEntityTest.java
+++ b/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/DroolsSessionEntityTest.java
@@ -36,28 +36,28 @@
 		DroolsSessionEntity e = makeEnt("mynameA", 1);
 
 		DroolsSessionEntity e2 = makeEnt("mynameA", 2);
-		
+
 		// session id is not part of hash code
 		assertTrue(e.hashCode() == e2.hashCode());
-		
+
 		// diff sess name
 		e2 = makeEnt("mynameB", 1);
 		assertTrue(e.hashCode() != e2.hashCode());
 	}
 
 	/**
-	 * Ensures that hashCode() functions as expected when the getXxx methods
-	 * are overridden.
+	 * Ensures that hashCode() functions as expected when the getXxx methods are
+	 * overridden.
 	 */
 	@Test
 	public void testHashCode_Subclass() {
 		DroolsSessionEntity e = makeEnt2("mynameA", 1);
 
 		DroolsSessionEntity e2 = makeEnt("mynameA", 2);
-		
+
 		// session id is not part of hash code
 		assertTrue(e.hashCode() == e2.hashCode());
-		
+
 		// diff sess name
 		e2 = makeEnt("mynameB", 1);
 		assertTrue(e.hashCode() != e2.hashCode());
@@ -68,10 +68,10 @@
 		DroolsSessionEntity e = makeEnt("mynameZ", 1);
 
 		assertEquals("mynameZ", e.getSessionName());
-		
+
 		e.setSessionName("another");
 		assertEquals("another", e.getSessionName());
-		
+
 		// others unchanged
 		assertEquals(1, e.getSessionId());
 	}
@@ -81,10 +81,10 @@
 		DroolsSessionEntity e = makeEnt("mynameA", 1);
 
 		assertEquals(1, e.getSessionId());
-		
+
 		e.setSessionId(20);
 		assertEquals(20, e.getSessionId());
-		
+
 		// others unchanged
 		assertEquals("mynameA", e.getSessionName());
 	}
@@ -92,13 +92,13 @@
 	@Test
 	public void testGetCreatedDate_testSetCreatedDate_testGetUpdatedDate_testSetUpdatedDate() {
 		DroolsSessionEntity e = new DroolsSessionEntity();
-		
+
 		Date crtdt = new Date(System.currentTimeMillis() - 100);
 		e.setCreatedDate(crtdt);
 
 		Date updt = new Date(System.currentTimeMillis() - 200);
 		e.setUpdatedDate(updt);
-		
+
 		assertEquals(crtdt, e.getCreatedDate());
 		assertEquals(updt, e.getUpdatedDate());
 	}
@@ -106,16 +106,16 @@
 	@Test
 	public void testEqualsObject() {
 		DroolsSessionEntity e = makeEnt("mynameA", 1);
-		
+
 		// reflexive
 		assertTrue(e.equals(e));
 
 		DroolsSessionEntity e2 = makeEnt("mynameA", 2);
-		
+
 		// session id is not part of hash code
 		assertTrue(e.equals(e2));
 		assertTrue(e.equals(e2));
-		
+
 		// diff sess name
 		e2 = makeEnt("mynameB", 1);
 		assertFalse(e.equals(e2));
@@ -123,22 +123,22 @@
 	}
 
 	/**
-	 * Ensures that equals() functions as expected when the getXxx methods
-	 * are overridden.
+	 * Ensures that equals() functions as expected when the getXxx methods are
+	 * overridden.
 	 */
 	@Test
 	public void testEqualsObject_Subclass() {
 		DroolsSessionEntity e = makeEnt2("mynameA", 1);
-		
+
 		// reflexive
 		assertTrue(e.equals(e));
 
 		DroolsSessionEntity e2 = makeEnt("mynameA", 2);
-		
+
 		// session id is not part of hash code
 		assertTrue(e.equals(e2));
 		assertTrue(e.equals(e2));
-		
+
 		// diff sess name
 		e2 = makeEnt("mynameB", 1);
 		assertFalse(e.equals(e2));
@@ -148,34 +148,39 @@
 	@Test
 	public void testToString() {
 		DroolsSessionEntity e = makeEnt("mynameA", 23);
-		
+
 		assertEquals("{name=mynameA, id=23}", e.toString());
 	}
 
 	/**
-	 * Makes a session Entity.  The parameters are stored into the Entity
-	 * object via the setXxx methods.
-	 * @param sessnm	session name
-	 * @param sessid	session id
+	 * Makes a session Entity. The parameters are stored into the Entity object
+	 * via the setXxx methods.
+	 * 
+	 * @param sessnm
+	 *            session name
+	 * @param sessid
+	 *            session id
 	 * @return a new session Entity
 	 */
 	private DroolsSessionEntity makeEnt(String sessnm, long sessid) {
 
 		DroolsSessionEntity e = new DroolsSessionEntity();
-		
+
 		e.setSessionName(sessnm);
 		e.setSessionId(sessid);
-		
+
 		return e;
 	}
-	
+
 	/**
-	 * Makes a session Entity that overrides the getXxx methods.  The
-	 * parameters that are provided are returned by the overridden methods,
-	 * but they are <i>not</i> stored into the Entity object via the setXxx
-	 * methods.
-	 * @param sessnm	session name
-	 * @param sessid	session id
+	 * Makes a session Entity that overrides the getXxx methods. The parameters
+	 * that are provided are returned by the overridden methods, but they are
+	 * <i>not</i> stored into the Entity object via the setXxx methods.
+	 * 
+	 * @param sessnm
+	 *            session name
+	 * @param sessid
+	 *            session id
 	 * @return a new session Entity
 	 */
 	@SuppressWarnings("serial")
diff --git a/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/EntityMgrCloserTest.java b/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/EntityMgrCloserTest.java
deleted file mode 100644
index 7350a7f..0000000
--- a/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/EntityMgrCloserTest.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * feature-session-persistence
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *      http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-package org.onap.policy.drools.persistence;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-
-import javax.persistence.EntityManager;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.onap.policy.drools.persistence.EntityMgrCloser;
-
-public class EntityMgrCloserTest {
-	
-	private EntityManager mgr;
-	
-
-	@Before
-	public void setUp() throws Exception {
-		mgr = mock(EntityManager.class);
-	}
-
-
-	/**
-	 * Verifies that the constructor does not do anything extra before
-	 * being closed.
-	 */
-	@Test
-	public void testEntityMgrCloser() {
-		EntityMgrCloser c = new EntityMgrCloser(mgr);
-
-		// verify not closed yet
-		verify(mgr, never()).close();
-		
-		c.close();
-	}
-	
-	/**
-	 * Verifies that the manager gets closed when close() is invoked.
-	 */
-	@Test
-	public void testClose() {
-		EntityMgrCloser c = new EntityMgrCloser(mgr);
-		
-		c.close();
-		
-		// should be closed
-		verify(mgr).close();
-	}
-
-	/**
-	 * Ensures that the manager gets closed when "try" block exits normally.
-	 */
-	@Test
-	public void testClose_TryWithoutExcept() {
-		try(EntityMgrCloser c = new EntityMgrCloser(mgr)) {
-			
-		}
-		
-		verify(mgr).close();
-	}
-
-	/**
-	 * Ensures that the manager gets closed when "try" block throws an
-	 * exception.
-	 */
-	@Test
-	public void testClose_TryWithExcept() {
-		try {
-			try(EntityMgrCloser c = new EntityMgrCloser(mgr)) {
-				throw new Exception("expected exception");
-			}
-			
-		} catch (Exception e) {
-		}
-		
-		verify(mgr).close();
-	}
-
-}
diff --git a/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/EntityMgrTransTest.java b/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/EntityMgrTransTest.java
index 0165b1e..9c9a30b 100644
--- a/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/EntityMgrTransTest.java
+++ b/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/EntityMgrTransTest.java
@@ -25,37 +25,69 @@
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.doThrow;
 
 import javax.persistence.EntityManager;
-import javax.persistence.EntityTransaction;
+import javax.transaction.HeuristicMixedException;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.NotSupportedException;
+import javax.transaction.RollbackException;
+import javax.transaction.Status;
+import javax.transaction.SystemException;
+import javax.transaction.UserTransaction;
 
+import org.junit.AfterClass;
 import org.junit.Before;
+import org.junit.BeforeClass;
 import org.junit.Test;
-import org.onap.policy.drools.persistence.EntityMgrTrans;
+import org.onap.policy.drools.persistence.EntityMgrTrans.EntityMgrException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class EntityMgrTransTest {
-	
-	private EntityTransaction trans;
+
+	private static final Logger logger = LoggerFactory.getLogger(PersistenceFeatureTest.class);
+
+	private static UserTransaction savetrans;
+
+	private UserTransaction trans;
 	private EntityManager mgr;
 
+	@BeforeClass
+	public static void setUpBeforeClass() {
+		System.setProperty("com.arjuna.ats.arjuna.objectstore.objectStoreDir", "target/tm");
+		System.setProperty("ObjectStoreEnvironmentBean.objectStoreDir", "target/tm");
+
+		savetrans = EntityMgrTrans.getUserTrans();
+	}
+
+	@AfterClass
+	public static void tearDownAfterClass() {
+		EntityMgrTrans.setUserTrans(savetrans);
+	}
+
 	@Before
 	public void setUp() throws Exception {
-		trans = mock(EntityTransaction.class);
+		trans = mock(UserTransaction.class);
 		mgr = mock(EntityManager.class);
-		
-		when(mgr.getTransaction()).thenReturn(trans);
+
+		EntityMgrTrans.setUserTrans(trans);
 	}
 
-
-
 	/**
 	 * Verifies that the constructor starts a transaction, but does not do
 	 * anything extra before being closed.
+	 * 
+	 * @throws Exception
 	 */
 	@Test
-	public void testEntityMgrTrans() {
+	public void testEntityMgrTrans() throws Exception {
+
+		when(trans.getStatus()).thenReturn(Status.STATUS_ACTIVE);
+
 		EntityMgrTrans t = new EntityMgrTrans(mgr);
-		
+
 		// verify that transaction was started
 		verify(trans).begin();
 
@@ -63,20 +95,50 @@
 		verify(trans, never()).commit();
 		verify(trans, never()).rollback();
 		verify(mgr, never()).close();
-		
+
 		t.close();
 	}
 
+	@Test(expected = EntityMgrException.class)
+	public void testEntityMgrTrans_RtEx() throws Exception {
+
+		doThrow(new IllegalArgumentException("expected exception")).when(trans).begin();
+
+		try (EntityMgrTrans t = new EntityMgrTrans(mgr)) {
+
+		}
+	}
+
+	@Test(expected = EntityMgrException.class)
+	public void testEntityMgrTrans_NotSuppEx() throws Exception {
+
+		doThrow(new NotSupportedException("expected exception")).when(trans).begin();
+
+		try (EntityMgrTrans t = new EntityMgrTrans(mgr)) {
+
+		}
+	}
+
+	@Test(expected = EntityMgrException.class)
+	public void testEntityMgrTrans_SysEx() throws Exception {
+
+		doThrow(new SystemException("expected exception")).when(trans).begin();
+
+		try (EntityMgrTrans t = new EntityMgrTrans(mgr)) {
+
+		}
+	}
+
 	/**
-	 * Verifies that the transaction is rolled back and the manager is
-	 * closed when and a transaction is active.
+	 * Verifies that the transaction is rolled back and the manager is closed
+	 * when and a transaction is active.
 	 */
 	@Test
-	public void testClose_Active() {
+	public void testClose_Active() throws Exception {
 		EntityMgrTrans t = new EntityMgrTrans(mgr);
 
-		when(trans.isActive()).thenReturn(true);
-		
+		when(trans.getStatus()).thenReturn(Status.STATUS_ACTIVE);
+
 		t.close();
 
 		// closed and rolled back, but not committed
@@ -87,14 +149,14 @@
 
 	/**
 	 * Verifies that the manager is closed, but that the transaction is
-	 * <i>not</i> rolled back and when and no transaction is active.
+	 * <i>not</i> rolled back when and no transaction is active.
 	 */
 	@Test
-	public void testClose_Inactive() {
+	public void testClose_Inactive() throws Exception {
 		EntityMgrTrans t = new EntityMgrTrans(mgr);
 
-		when(trans.isActive()).thenReturn(false);
-		
+		when(trans.getStatus()).thenReturn(Status.STATUS_NO_TRANSACTION);
+
 		t.close();
 
 		// closed, but not committed or rolled back
@@ -103,16 +165,49 @@
 		verify(trans, never()).rollback();
 	}
 
+	@Test(expected = EntityMgrException.class)
+	public void testClose_IllStateEx() throws Exception {
+
+		when(trans.getStatus()).thenReturn(Status.STATUS_ACTIVE);
+		doThrow(new IllegalStateException("expected exception")).when(trans).rollback();
+
+		try (EntityMgrTrans t = new EntityMgrTrans(mgr)) {
+
+		}
+	}
+
+	@Test(expected = EntityMgrException.class)
+	public void testClose_SecEx() throws Exception {
+
+		when(trans.getStatus()).thenReturn(Status.STATUS_ACTIVE);
+		doThrow(new SecurityException("expected exception")).when(trans).rollback();
+
+		try (EntityMgrTrans t = new EntityMgrTrans(mgr)) {
+
+		}
+	}
+
+	@Test(expected = EntityMgrException.class)
+	public void testClose_SysEx() throws Exception {
+
+		when(trans.getStatus()).thenReturn(Status.STATUS_ACTIVE);
+		doThrow(new SystemException("expected exception")).when(trans).rollback();
+
+		try (EntityMgrTrans t = new EntityMgrTrans(mgr)) {
+
+		}
+	}
+
 	/**
-	 * Verifies that the manager is closed and the transaction rolled back
-	 * when "try" block exits normally and a transaction is active.
+	 * Verifies that the manager is closed and the transaction rolled back when
+	 * "try" block exits normally and a transaction is active.
 	 */
 	@Test
-	public void testClose_TryWithoutExcept_Active() {
-		when(trans.isActive()).thenReturn(true);
-		
-		try(EntityMgrTrans t = new EntityMgrTrans(mgr)) {
-			
+	public void testClose_TryWithoutExcept_Active() throws Exception {
+		when(trans.getStatus()).thenReturn(Status.STATUS_ACTIVE);
+
+		try (EntityMgrTrans t = new EntityMgrTrans(mgr)) {
+
 		}
 
 		// closed and rolled back, but not committed
@@ -123,15 +218,16 @@
 
 	/**
 	 * Verifies that the manager is closed, but that the transaction is
-	 * <i>not</i> rolled back when "try" block exits normally and no
-	 * transaction is active.
+	 * <i>not</i> rolled back when "try" block exits normally and no transaction
+	 * is active.
 	 */
 	@Test
-	public void testClose_TryWithoutExcept_Inactive() {
-		when(trans.isActive()).thenReturn(false);
-		
-		try(EntityMgrTrans t = new EntityMgrTrans(mgr)) {
-			
+	public void testClose_TryWithoutExcept_Inactive() throws Exception {
+
+		when(trans.getStatus()).thenReturn(Status.STATUS_NO_TRANSACTION);
+
+		try (EntityMgrTrans t = new EntityMgrTrans(mgr)) {
+
 		}
 
 		// closed, but not rolled back or committed
@@ -141,19 +237,21 @@
 	}
 
 	/**
-	 * Verifies that the manager is closed and the transaction rolled back
-	 * when "try" block throws an exception and a transaction is active.
+	 * Verifies that the manager is closed and the transaction rolled back when
+	 * "try" block throws an exception and a transaction is active.
 	 */
 	@Test
-	public void testClose_TryWithExcept_Active() {
-		when(trans.isActive()).thenReturn(true);
-		
+	public void testClose_TryWithExcept_Active() throws Exception {
+
+		when(trans.getStatus()).thenReturn(Status.STATUS_ACTIVE);
+
 		try {
-			try(EntityMgrTrans t = new EntityMgrTrans(mgr)) {
-				throw new Exception("expected exception");
+			try (EntityMgrTrans t = new EntityMgrTrans(mgr)) {
+				throw new SystemException("expected exception");
 			}
-			
+
 		} catch (Exception e) {
+			logger.trace("expected exception", e);
 		}
 
 		// closed and rolled back, but not committed
@@ -168,15 +266,17 @@
 	 * transaction is active.
 	 */
 	@Test
-	public void testClose_TryWithExcept_Inactive() {
-		when(trans.isActive()).thenReturn(false);
-		
+	public void testClose_TryWithExcept_Inactive() throws Exception {
+
+		when(trans.getStatus()).thenReturn(Status.STATUS_NO_TRANSACTION);
+
 		try {
-			try(EntityMgrTrans t = new EntityMgrTrans(mgr)) {
-				throw new Exception("expected exception");
+			try (EntityMgrTrans t = new EntityMgrTrans(mgr)) {
+				throw new SystemException("expected exception");
 			}
-			
+
 		} catch (Exception e) {
+			logger.trace("expected exception", e);
 		}
 
 		// closed, but not rolled back or committed
@@ -186,20 +286,23 @@
 	}
 
 	/**
-	 * Verifies that commit() only commits, and that the subsequent close()
-	 * does not re-commit.
+	 * Verifies that commit() only commits, and that the subsequent close() does
+	 * not re-commit.
 	 */
 	@Test
-	public void testCommit() {
+	public void testCommit() throws Exception {
 		EntityMgrTrans t = new EntityMgrTrans(mgr);
-		
+		when(trans.getStatus()).thenReturn(Status.STATUS_ACTIVE);
+
 		t.commit();
-		
+
+		when(trans.getStatus()).thenReturn(Status.STATUS_COMMITTED);
+
 		// committed, but not closed or rolled back
 		verify(trans).commit();
 		verify(trans, never()).rollback();
 		verify(mgr, never()).close();
-		
+
 		// closed, but not re-committed
 		t.close();
 
@@ -207,21 +310,90 @@
 		verify(mgr).close();
 	}
 
+	@Test(expected = EntityMgrException.class)
+	public void testCommit_SecEx() throws Exception {
+
+		when(trans.getStatus()).thenReturn(Status.STATUS_ACTIVE);
+		doThrow(new SecurityException("expected exception")).when(trans).commit();
+
+		try (EntityMgrTrans t = new EntityMgrTrans(mgr)) {
+			t.commit();
+		}
+	}
+
+	@Test(expected = EntityMgrException.class)
+	public void testCommit_IllStateEx() throws Exception {
+
+		when(trans.getStatus()).thenReturn(Status.STATUS_ACTIVE);
+		doThrow(new IllegalStateException("expected exception")).when(trans).commit();
+
+		try (EntityMgrTrans t = new EntityMgrTrans(mgr)) {
+			t.commit();
+		}
+	}
+
+	@Test(expected = EntityMgrException.class)
+	public void testCommit_RbEx() throws Exception {
+
+		when(trans.getStatus()).thenReturn(Status.STATUS_ACTIVE);
+		doThrow(new RollbackException("expected exception")).when(trans).commit();
+
+		try (EntityMgrTrans t = new EntityMgrTrans(mgr)) {
+			t.commit();
+		}
+	}
+
+	@Test(expected = EntityMgrException.class)
+	public void testCommit_HmEx() throws Exception {
+
+		when(trans.getStatus()).thenReturn(Status.STATUS_ACTIVE);
+		doThrow(new HeuristicMixedException("expected exception")).when(trans).commit();
+
+		try (EntityMgrTrans t = new EntityMgrTrans(mgr)) {
+			t.commit();
+		}
+	}
+
+	@Test(expected = EntityMgrException.class)
+	public void testCommit_HrbEx() throws Exception {
+
+		when(trans.getStatus()).thenReturn(Status.STATUS_ACTIVE);
+		doThrow(new HeuristicRollbackException("expected exception")).when(trans).commit();
+
+		try (EntityMgrTrans t = new EntityMgrTrans(mgr)) {
+			t.commit();
+		}
+	}
+
+	@Test(expected = EntityMgrException.class)
+	public void testCommit_SysEx() throws Exception {
+
+		when(trans.getStatus()).thenReturn(Status.STATUS_ACTIVE);
+		doThrow(new SystemException("expected exception")).when(trans).commit();
+
+		try (EntityMgrTrans t = new EntityMgrTrans(mgr)) {
+			t.commit();
+		}
+	}
+
 	/**
-	 * Verifies that rollback() only rolls back, and that the subsequent
-	 * close() does not re-roll back.
+	 * Verifies that rollback() only rolls back, and that the subsequent close()
+	 * does not re-roll back.
 	 */
 	@Test
-	public void testRollback() {
+	public void testRollback() throws Exception {
 		EntityMgrTrans t = new EntityMgrTrans(mgr);
-		
+		when(trans.getStatus()).thenReturn(Status.STATUS_ACTIVE);
+
 		t.rollback();
-		
+
+		when(trans.getStatus()).thenReturn(Status.STATUS_ROLLEDBACK);
+
 		// rolled back, but not closed or committed
 		verify(trans, never()).commit();
 		verify(trans).rollback();
 		verify(mgr, never()).close();
-		
+
 		// closed, but not re-rolled back
 		t.close();
 
@@ -229,4 +401,45 @@
 		verify(mgr).close();
 	}
 
+	@Test(expected = EntityMgrException.class)
+	public void testRollback_IllStateEx() throws Exception {
+
+		when(trans.getStatus()).thenReturn(Status.STATUS_ACTIVE);
+		doThrow(new IllegalStateException("expected exception")).when(trans).rollback();
+
+		try (EntityMgrTrans t = new EntityMgrTrans(mgr)) {
+			t.rollback();
+		}
+	}
+
+	@Test(expected = EntityMgrException.class)
+	public void testRollback_SecEx() throws Exception {
+
+		when(trans.getStatus()).thenReturn(Status.STATUS_ACTIVE);
+		doThrow(new SecurityException("expected exception")).when(trans).rollback();
+
+		try (EntityMgrTrans t = new EntityMgrTrans(mgr)) {
+			t.rollback();
+		}
+	}
+
+	@Test(expected = EntityMgrException.class)
+	public void testRollback_SysEx() throws Exception {
+
+		when(trans.getStatus()).thenReturn(Status.STATUS_ACTIVE);
+		doThrow(new SystemException("expected exception")).when(trans).rollback();
+
+		try (EntityMgrTrans t = new EntityMgrTrans(mgr)) {
+			t.rollback();
+		}
+	}
+
+	@Test
+	public void testEntityMgrException() {
+		SecurityException secex = new SecurityException("expected exception");
+		EntityMgrException ex = new EntityMgrException(secex);
+
+		assertEquals(secex, ex.getCause());
+
+	}
 }
diff --git a/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/GenSchemaTest.java b/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/GenSchema.java
similarity index 65%
rename from feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/GenSchemaTest.java
rename to feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/GenSchema.java
index d9e25b2..a0af2e6 100644
--- a/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/GenSchemaTest.java
+++ b/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/GenSchema.java
@@ -26,31 +26,44 @@
 import javax.persistence.EntityManagerFactory;
 import javax.persistence.Persistence;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 /**
  * Generates the schema DDL files.
  */
-public class GenSchemaTest {
-	
-	private EntityManagerFactory emf;
-	
+public class GenSchema {
 
-	/*
-	 * This is a JUnit which is provided as a utility for producing a basic
-	 * ddl schema file in the sql directory.  
+	private static final Logger logger = LoggerFactory.getLogger(PersistenceFeatureTest.class);
+
+	private EntityManagerFactory emf;
+
+	/**
+	 * Opens the EMF, which generates the schema, as a side-effect.
 	 * 
-	 * To run this simple add @Test ahead of the method and then run this
-	 * as a JUnit.
+	 * @throws Exception
 	 */
-	public void generate() throws Exception {
+	private GenSchema() throws Exception {
 		Map<String, Object> propMap = new HashMap<>();
 
 		propMap.put("javax.persistence.jdbc.driver", "org.h2.Driver");
-		propMap.put("javax.persistence.jdbc.url",
-						"jdbc:h2:mem:JpaDroolsSessionConnectorTest");
-		
-		emf = Persistence.createEntityManagerFactory(
-								"schemaDroolsPU", propMap);
-		
+		propMap.put("javax.persistence.jdbc.url", "jdbc:h2:mem:JpaDroolsSessionConnectorTest");
+
+		emf = Persistence.createEntityManagerFactory("schemaDroolsPU", propMap);
+
 		emf.close();
 	}
+
+	/**
+	 * This is is provided as a utility for producing a basic ddl schema file in
+	 * the sql directory.
+	 */
+	public static void main(String[] args) {
+		try {
+			new GenSchema();
+
+		} catch (Exception e) {
+			logger.error("failed to generate schema", e);
+		}
+	}
 }
diff --git a/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/JpaDroolsSessionConnectorTest.java b/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/JpaDroolsSessionConnectorTest.java
index 792e6f8..dd601dd 100644
--- a/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/JpaDroolsSessionConnectorTest.java
+++ b/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/JpaDroolsSessionConnectorTest.java
@@ -37,31 +37,35 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.BeforeClass;
 import org.junit.Test;
 import org.onap.policy.drools.persistence.DroolsSessionEntity;
 import org.onap.policy.drools.persistence.EntityMgrTrans;
 import org.onap.policy.drools.persistence.JpaDroolsSessionConnector;
 
 public class JpaDroolsSessionConnectorTest {
-	
+
 	private EntityManagerFactory emf;
 	private JpaDroolsSessionConnector conn;
-	
+
+	@BeforeClass
+	public static void setUpBeforeClass() {
+		System.setProperty("com.arjuna.ats.arjuna.objectstore.objectStoreDir", "target/tm");
+		System.setProperty("ObjectStoreEnvironmentBean.objectStoreDir", "target/tm");
+	}
 
 	@Before
 	public void setUp() throws Exception {
 		Map<String, Object> propMap = new HashMap<>();
 
 		propMap.put("javax.persistence.jdbc.driver", "org.h2.Driver");
-		propMap.put("javax.persistence.jdbc.url",
-						"jdbc:h2:mem:JpaDroolsSessionConnectorTest");
-		
-		emf = Persistence.createEntityManagerFactory(
-								"junitDroolsSessionEntityPU", propMap);
-		
+		propMap.put("javax.persistence.jdbc.url", "jdbc:h2:mem:JpaDroolsSessionConnectorTest");
+
+		emf = Persistence.createEntityManagerFactory("junitDroolsSessionEntityPU", propMap);
+
 		conn = new JpaDroolsSessionConnector(emf);
 	}
-	
+
 	@After
 	public void tearDown() {
 		// this will cause the memory db to be dropped
@@ -73,60 +77,57 @@
 		/*
 		 * Load up the DB with some data.
 		 */
-		
+
 		addSession("nameA", 10);
 		addSession("nameY", 20);
-		
-		
+
 		/*
 		 * Now test the functionality.
 		 */
-		
+
 		// not found
-		assertNull( conn.get("unknown"));
-		
-		assertEquals("{name=nameA, id=10}",
-						conn.get("nameA").toString());
-		
-		assertEquals("{name=nameY, id=20}",
-						conn.get("nameY").toString());
+		assertNull(conn.get("unknown"));
+
+		assertEquals("{name=nameA, id=10}", conn.get("nameA").toString());
+
+		assertEquals("{name=nameY, id=20}", conn.get("nameY").toString());
 	}
-	
-	@Test(expected = RuntimeException.class)
+
+	@Test(expected = IllegalArgumentException.class)
 	public void testGet_NewEx() {
 		EntityManagerFactory emf = mock(EntityManagerFactory.class);
 		EntityManager em = mock(EntityManager.class);
-		
+
 		when(emf.createEntityManager()).thenReturn(em);
-		when(em.getTransaction()).thenThrow(new RuntimeException("expected exception"));
+		when(em.find(any(), any())).thenThrow(new IllegalArgumentException("expected exception"));
 
 		conn = new JpaDroolsSessionConnector(emf);
 		conn.get("xyz");
 	}
-	
-	@Test(expected = RuntimeException.class)
+
+	@Test(expected = IllegalArgumentException.class)
 	public void testGet_FindEx() {
 		EntityManagerFactory emf = mock(EntityManagerFactory.class);
 		EntityManager em = mock(EntityManager.class);
 		EntityTransaction tr = mock(EntityTransaction.class);
-		
+
 		when(emf.createEntityManager()).thenReturn(em);
 		when(em.getTransaction()).thenReturn(tr);
-		when(em.find(any(), any())).thenThrow(new RuntimeException("expected exception"));
+		when(em.find(any(), any())).thenThrow(new IllegalArgumentException("expected exception"));
 
 		new JpaDroolsSessionConnector(emf).get("xyz");
 	}
-	
-	@Test(expected = RuntimeException.class)
+
+	@Test(expected = IllegalArgumentException.class)
 	public void testGet_FindEx_CloseEx() {
 		EntityManagerFactory emf = mock(EntityManagerFactory.class);
 		EntityManager em = mock(EntityManager.class);
 		EntityTransaction tr = mock(EntityTransaction.class);
-		
+
 		when(emf.createEntityManager()).thenReturn(em);
 		when(em.getTransaction()).thenReturn(tr);
-		when(em.find(any(), any())).thenThrow(new RuntimeException("expected exception"));
-		doThrow(new RuntimeException("expected exception #2")).when(em).close();
+		when(em.find(any(), any())).thenThrow(new IllegalArgumentException("expected exception"));
+		doThrow(new IllegalArgumentException("expected exception #2")).when(em).close();
 
 		new JpaDroolsSessionConnector(emf).get("xyz");
 	}
@@ -134,70 +135,64 @@
 	@Test
 	public void testReplace_Existing() {
 		addSession("nameA", 10);
-		
-		DroolsSessionEntity sess =
-				new DroolsSessionEntity("nameA", 30);
-		
+
+		DroolsSessionEntity sess = new DroolsSessionEntity("nameA", 30);
+
 		conn.replace(sess);
 
 		// id should be changed
-		assertEquals(sess.toString(),
-						conn.get("nameA").toString());
+		assertEquals(sess.toString(), conn.get("nameA").toString());
 	}
 
 	@Test
 	public void testReplace_New() {
-		DroolsSessionEntity sess =
-				new DroolsSessionEntity("nameA", 30);
-		
+		DroolsSessionEntity sess = new DroolsSessionEntity("nameA", 30);
+
 		conn.replace(sess);
 
-		assertEquals(sess.toString(),
-						conn.get("nameA").toString());
+		assertEquals(sess.toString(), conn.get("nameA").toString());
 	}
 
 	@Test
 	public void testAdd() {
-		DroolsSessionEntity sess =
-				new DroolsSessionEntity("nameA", 30);
-		
+		DroolsSessionEntity sess = new DroolsSessionEntity("nameA", 30);
+
 		conn.replace(sess);
 
-		assertEquals(sess.toString(),
-						conn.get("nameA").toString());
+		assertEquals(sess.toString(), conn.get("nameA").toString());
 	}
 
 	@Test
 	public void testUpdate() {
 		addSession("nameA", 10);
-		
-		DroolsSessionEntity sess =
-				new DroolsSessionEntity("nameA", 30);
-		
+
+		DroolsSessionEntity sess = new DroolsSessionEntity("nameA", 30);
+
 		conn.replace(sess);
 
 		// id should be changed
-		assertEquals("{name=nameA, id=30}",
-						conn.get("nameA").toString());
+		assertEquals("{name=nameA, id=30}", conn.get("nameA").toString());
 	}
 
-
 	/**
 	 * Adds a session to the DB.
-	 * @param sessnm	session name
-	 * @param sessid	session id
+	 * 
+	 * @param sessnm
+	 *            session name
+	 * @param sessid
+	 *            session id
 	 */
 	private void addSession(String sessnm, int sessid) {
 		EntityManager em = emf.createEntityManager();
-		
-		try(EntityMgrTrans trans = new EntityMgrTrans(em)) {
+
+		try (EntityMgrTrans trans = new EntityMgrTrans(em)) {
 			DroolsSessionEntity ent = new DroolsSessionEntity();
-			
+
 			ent.setSessionName(sessnm);
 			ent.setSessionId(sessid);
-			
+
 			em.persist(ent);
-		
+
 			trans.commit();
 		}
 	}
diff --git a/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/PersistenceFeatureTest.java b/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/PersistenceFeatureTest.java
index e73031d..a7c33ab 100644
--- a/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/PersistenceFeatureTest.java
+++ b/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/PersistenceFeatureTest.java
@@ -24,8 +24,9 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.anyLong;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.mock;
@@ -33,11 +34,11 @@
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.doThrow;
 
 import java.io.FileNotFoundException;
 import java.io.FileReader;
 import java.io.IOException;
-import java.net.UnknownHostException;
 import java.sql.Connection;
 import java.sql.DriverManager;
 import java.sql.PreparedStatement;
@@ -46,12 +47,19 @@
 import java.sql.Timestamp;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 import java.util.Properties;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 
+import javax.persistence.EntityManager;
 import javax.persistence.EntityManagerFactory;
+import javax.transaction.TransactionManager;
+import javax.transaction.TransactionSynchronizationRegistry;
+import javax.transaction.UserTransaction;
 
+import org.apache.commons.dbcp2.BasicDataSource;
 import org.junit.After;
-import org.junit.AfterClass;
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
@@ -64,34 +72,32 @@
 import org.kie.api.runtime.KieSession;
 import org.kie.api.runtime.KieSessionConfiguration;
 import org.mockito.ArgumentCaptor;
-import org.onap.policy.drools.persistence.DroolsPersistenceProperties;
-import org.onap.policy.drools.persistence.DroolsSession;
-import org.onap.policy.drools.persistence.DroolsSessionConnector;
-import org.onap.policy.drools.persistence.PersistenceFeature;
 import org.onap.policy.drools.core.PolicyContainer;
 import org.onap.policy.drools.core.PolicySession;
+import org.onap.policy.drools.core.PolicySession.ThreadModel;
+import org.onap.policy.drools.persistence.PersistenceFeature.PersistenceFeatureException;
+import org.onap.policy.drools.persistence.PersistenceFeature.PersistentThreadModel;
 import org.onap.policy.drools.system.PolicyController;
-
-import bitronix.tm.BitronixTransactionManager;
-import bitronix.tm.Configuration;
-import bitronix.tm.resource.jdbc.PoolingDataSource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class PersistenceFeatureTest {
 
-	private static final String JDBC_DATASRC = "fake.datasource";
+	private static final Logger logger = LoggerFactory.getLogger(PersistenceFeatureTest.class);
+
 	private static final String JDBC_DRIVER = "fake.driver";
 	private static final String JDBC_URL = "fake.url";
 	private static final String JDBC_USER = "fake.user";
 	private static final String JDBC_PASSWD = "fake.password";
+	private static final String JTA_OSDIR = "target";
 	private static final String SRC_TEST_RESOURCES = "src/test/resources";
 
 	private static Properties stdprops;
 
-	private DroolsSessionConnector jpa;
+	private JpaDroolsSessionConnector jpa;
 	private DroolsSession sess;
-	private PoolingDataSource pds;
 	private KieSession kiesess;
-	private Properties dsprops;
+	private BasicDataSource bds;
 	private EntityManagerFactory emf;
 	private Connection conn;
 	private Properties props;
@@ -101,40 +107,38 @@
 	private KieBase kiebase;
 	private KieStoreServices kiestore;
 	private KieContainer kiecont;
-	private Configuration bitcfg;
-	private BitronixTransactionManager bittrans;
+	private TransactionManager transmgr;
+	private UserTransaction usertrans;
+	private TransactionSynchronizationRegistry transreg;
 	private PolicyController polctlr;
 	private PolicyContainer polcont;
 	private PolicySession polsess;
 	private PersistenceFeature.Factory fact;
-	
+
 	private PersistenceFeature feat;
-	
 
 	@BeforeClass
 	public static void setUpBeforeClass() throws Exception {
 		stdprops = new Properties();
 
-		stdprops.put(DroolsPersistenceProperties.DB_DATA_SOURCE, JDBC_DATASRC);
 		stdprops.put(DroolsPersistenceProperties.DB_DRIVER, JDBC_DRIVER);
 		stdprops.put(DroolsPersistenceProperties.DB_URL, JDBC_URL);
 		stdprops.put(DroolsPersistenceProperties.DB_USER, JDBC_USER);
 		stdprops.put(DroolsPersistenceProperties.DB_PWD, JDBC_PASSWD);
+		stdprops.put(DroolsPersistenceProperties.JTA_OBJECTSTORE_DIR, JTA_OSDIR);
 		stdprops.put(DroolsPersistenceProperties.DB_SESSIONINFO_TIMEOUT, "50");
-	}
 
-	@AfterClass
-	public static void tearDownAfterClass() throws Exception {
+		System.setProperty("com.arjuna.ats.arjuna.objectstore.objectStoreDir", "target/tm");
+		System.setProperty("ObjectStoreEnvironmentBean.objectStoreDir", "target/tm");
 	}
 
 	@Before
 	public void setUp() throws Exception {
-		jpa = mock(DroolsSessionConnector.class);
+		jpa = mock(JpaDroolsSessionConnector.class);
 		sess = mock(DroolsSession.class);
-		pds = mock(PoolingDataSource.class);
+		bds = mock(BasicDataSource.class);
+		emf = mock(EntityManagerFactory.class);
 		kiesess = mock(KieSession.class);
-		dsprops = new Properties();
-		emf = null;
 		conn = null;
 		props = new Properties();
 		kiesvc = mock(KieServices.class);
@@ -143,45 +147,56 @@
 		kiebase = mock(KieBase.class);
 		kiestore = mock(KieStoreServices.class);
 		kiecont = mock(KieContainer.class);
-		bitcfg = mock(Configuration.class);
-		bittrans = mock(BitronixTransactionManager.class);
+		transmgr = mock(TransactionManager.class);
+		usertrans = mock(UserTransaction.class);
+		transreg = mock(TransactionSynchronizationRegistry.class);
 		polcont = mock(PolicyContainer.class);
 		polctlr = mock(PolicyController.class);
 		polsess = mock(PolicySession.class);
 		fact = mock(PersistenceFeature.Factory.class);
-		
+
 		feat = new PersistenceFeature();
 		feat.setFactory(fact);
-		
+
 		props.putAll(stdprops);
-		
-		when(pds.getUniqueName()).thenReturn("myds");
-		
+
+		System.setProperty("com.arjuna.ats.arjuna.objectstore.objectStoreDir", "target/tm");
+		System.setProperty("ObjectStoreEnvironmentBean.objectStoreDir", "target/tm");
+
 		when(fact.getKieServices()).thenReturn(kiesvc);
-		when(fact.getTransMgrConfig()).thenReturn(bitcfg);
-		when(fact.getTransMgr()).thenReturn(bittrans);
+		when(fact.getTransMgr()).thenReturn(transmgr);
+		when(fact.getUserTrans()).thenReturn(usertrans);
+		when(fact.getTransSyncReg()).thenReturn(transreg);
 		when(fact.loadProperties(anyString())).thenReturn(props);
-		
+
 		when(kiesvc.newEnvironment()).thenReturn(kieenv);
 		when(kiesvc.getStoreServices()).thenReturn(kiestore);
 		when(kiesvc.newKieSessionConfiguration()).thenReturn(kiecfg);
-		
+
 		when(polcont.getKieContainer()).thenReturn(kiecont);
-		
+
 		when(polsess.getPolicyContainer()).thenReturn(polcont);
-		
+
 		when(kiecont.getKieBase(anyString())).thenReturn(kiebase);
 	}
 
 	@After
 	public void tearDown() {
 		// this will cause the in-memory test DB to be dropped
-		if(conn != null) {
-			try { conn.close(); } catch (SQLException e) { }
+		if (conn != null) {
+			try {
+				conn.close();
+			} catch (SQLException e) {
+				logger.warn("failed to close connection", e);
+			}
 		}
 
-		if(emf != null) {
-			try { emf.close(); } catch (Exception e) { }
+		if (emf != null) {
+			try {
+				emf.close();
+			} catch (IllegalArgumentException e) {
+				logger.trace("ignored exception", e);
+			}
 		}
 	}
 
@@ -196,12 +211,12 @@
 		// force getContainerAdjunct() to be invoked
 		feat.activatePolicySession(polcont, "myname", "mybase");
 
-		ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap =
-				ArgumentCaptor.forClass(PersistenceFeature.ContainerAdjunct.class);
+		ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap = ArgumentCaptor
+				.forClass(PersistenceFeature.ContainerAdjunct.class);
 
 		verify(polcont, times(1)).setAdjunct(any(), adjcap.capture());
-		
-		assertNotNull( adjcap.getValue());
+
+		assertNotNull(adjcap.getValue());
 	}
 
 	@Test
@@ -215,41 +230,66 @@
 		// force getContainerAdjunct() to be invoked
 		feat.activatePolicySession(polcont, "myname", "mybase");
 
-		ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap =
-				ArgumentCaptor.forClass(PersistenceFeature.ContainerAdjunct.class);
+		ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap = ArgumentCaptor
+				.forClass(PersistenceFeature.ContainerAdjunct.class);
 
 		verify(polcont, times(1)).setAdjunct(any(), adjcap.capture());
-		
+
 		// return adjunct on next call
-		when(polcont.getAdjunct(any())).thenReturn( adjcap.getValue());
+		when(polcont.getAdjunct(any())).thenReturn(adjcap.getValue());
 
 		// force getContainerAdjunct() to be invoked again
 		setUpKie("myname2", 999L, true);
 		feat.activatePolicySession(polcont, "myname2", "mybase");
-		
+
 		// ensure it isn't invoked again
 		verify(polcont, times(1)).setAdjunct(any(), any());
 	}
 
 	@Test
+	public void testGetContainerAdjunct_WrongType() throws Exception {
+
+		feat.globalInit(null, SRC_TEST_RESOURCES);
+
+		mockDbConn(5);
+		setUpKie("myname", 999L, true);
+
+		// return false adjunct on next call
+		when(polcont.getAdjunct(any())).thenReturn("not-a-real-adjunct");
+
+		// force getContainerAdjunct() to be invoked
+		setUpKie("myname2", 999L, true);
+		feat.activatePolicySession(polcont, "myname2", "mybase");
+
+		ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap = ArgumentCaptor
+				.forClass(PersistenceFeature.ContainerAdjunct.class);
+
+		verify(polcont, times(1)).setAdjunct(any(), adjcap.capture());
+
+		assertNotNull(adjcap.getValue());
+	}
+
+	@Test
 	public void testGetSequenceNumber() {
 		assertEquals(1, feat.getSequenceNumber());
 	}
 
 	@Test
 	public void testGlobalInit() throws Exception {
-		when(fact.getHostName()).thenReturn("myhost");
-		
+
 		feat.globalInit(null, SRC_TEST_RESOURCES);
-		
+
 		// verify that various factory methods were invoked
-		verify(fact).getHostName();
 		verify(fact).getKieServices();
-		verify(fact).getTransMgrConfig();
 		verify(fact).loadProperties("src/test/resources/feature-session-persistence.properties");
+	}
+
+	@Test(expected = NullPointerException.class)
+	public void testGlobalInit_IOEx() throws Exception {
 		
-		verify(bitcfg).setJournal(null);
-		verify(bitcfg).setServerId("myhost");
+		when(fact.loadProperties(anyString())).thenThrow(new IOException("expected exception"));
+
+		feat.globalInit(null, SRC_TEST_RESOURCES);
 	}
 
 	@Test
@@ -259,21 +299,18 @@
 
 		feat.globalInit(null, SRC_TEST_RESOURCES);
 		feat.beforeActivate(null);
-		
-		KieSession s =
-				feat.activatePolicySession(polcont, "myname", "mybase");
+
+		KieSession s = feat.activatePolicySession(polcont, "myname", "mybase");
 
 		verify(kiestore).loadKieSession(anyLong(), any(), any(), any());
 		verify(kiestore, never()).newKieSession(any(), any(), any());
-		
+
 		assertEquals(s, kiesess);
-		
+
 		verify(ps).executeUpdate();
 
-		verify(kieenv, times(2)).set(anyString(), any());
-		verify(pds).init();
-		assertFalse( dsprops.isEmpty());
-		
+		verify(kieenv, times(4)).set(anyString(), any());
+
 		verify(jpa).get("myname");
 		verify(jpa).replace(any());
 	}
@@ -284,12 +321,12 @@
 
 		PreparedStatement ps = mockDbConn(5);
 		setUpKie("myname", 999L, true);
-		
+
 		props.remove("persistence.type");
-		
+
 		feat.beforeStart(null);
-		
-		assertNull( feat.activatePolicySession(polcont, "myname", "mybase"));
+
+		assertNull(feat.activatePolicySession(polcont, "myname", "mybase"));
 
 		verify(ps, never()).executeUpdate();
 		verify(kiestore, never()).loadKieSession(anyLong(), any(), any(), any());
@@ -298,7 +335,7 @@
 
 	/**
 	 * Verifies that a new KIE session is created when there is no existing
-	 * session entity. 
+	 * session entity.
 	 */
 	@Test
 	public void testActivatePolicySession_New() throws Exception {
@@ -306,27 +343,23 @@
 
 		mockDbConn(5);
 		setUpKie("noName", 999L, true);
-		
-		
-		KieSession s =
-				feat.activatePolicySession(polcont, "myname", "mybase");
+
+		KieSession s = feat.activatePolicySession(polcont, "myname", "mybase");
 
 		verify(kiestore, never()).loadKieSession(anyLong(), any(), any(), any());
 		verify(kiestore).newKieSession(any(), any(), any());
-		
+
 		assertEquals(s, kiesess);
 
-		verify(kieenv, times(2)).set(anyString(), any());
-		verify(pds).init();
-		assertFalse( dsprops.isEmpty());
+		verify(kieenv, times(4)).set(anyString(), any());
 
 		verify(jpa).get("myname");
 		verify(jpa).replace(any());
 	}
 
 	/**
-	 * Verifies that a new KIE session is created when there KIE fails
-	 * to load an existing session.
+	 * Verifies that a new KIE session is created when there KIE fails to load
+	 * an existing session.
 	 */
 	@Test
 	public void testActivatePolicySession_LoadFailed() throws Exception {
@@ -334,64 +367,88 @@
 
 		mockDbConn(5);
 		setUpKie("myname", 999L, false);
-		
-		
-		KieSession s =
-				feat.activatePolicySession(polcont, "myname", "mybase");
+
+		KieSession s = feat.activatePolicySession(polcont, "myname", "mybase");
 
 		verify(kiestore).loadKieSession(anyLong(), any(), any(), any());
 		verify(kiestore).newKieSession(any(), any(), any());
-		
+
 		assertEquals(s, kiesess);
 
-		verify(kieenv, times(2)).set(anyString(), any());
-		verify(pds).init();
-		assertFalse( dsprops.isEmpty());
+		verify(kieenv, times(4)).set(anyString(), any());
 
 		verify(jpa).get("myname");
-		
-		ArgumentCaptor<DroolsSession> d =
-				ArgumentCaptor.forClass(DroolsSession.class);
-		verify(jpa).replace( d.capture());
-		
+
+		ArgumentCaptor<DroolsSession> d = ArgumentCaptor.forClass(DroolsSession.class);
+		verify(jpa).replace(d.capture());
+
 		assertEquals("myname", d.getValue().getSessionName());
 		assertEquals(100L, d.getValue().getSessionId());
 	}
 
 	@Test
+	public void testLoadDataSource() throws Exception {
+		feat.globalInit(null, SRC_TEST_RESOURCES);
+
+		mockDbConn(5);
+		setUpKie("myname", 999L, false);
+
+		feat.activatePolicySession(polcont, "myname", "mybase");
+
+		verify(fact).makeEntMgrFact(any());
+	}
+
+	@Test
+	public void testConfigureSysProps() throws Exception {
+		feat.globalInit(null, SRC_TEST_RESOURCES);
+
+		mockDbConn(5);
+		setUpKie("myname", 999L, false);
+
+		feat.activatePolicySession(polcont, "myname", "mybase");
+
+		assertEquals("60", System.getProperty("com.arjuna.ats.arjuna.coordinator.defaultTimeout"));
+		assertEquals(JTA_OSDIR, System.getProperty("com.arjuna.ats.arjuna.objectstore.objectStoreDir"));
+		assertEquals(JTA_OSDIR, System.getProperty("ObjectStoreEnvironmentBean.objectStoreDir"));
+	}
+
+	@Test
 	public void testConfigureKieEnv() throws Exception {
 		feat.globalInit(null, SRC_TEST_RESOURCES);
 
 		mockDbConn(5);
 		setUpKie("myname", 999L, false);
-		
+
 		feat.activatePolicySession(polcont, "myname", "mybase");
 
-		verify(kieenv, times(2)).set(any(), any());
-		
+		verify(kieenv, times(4)).set(any(), any());
+
 		verify(kieenv).set(EnvironmentName.ENTITY_MANAGER_FACTORY, emf);
-		verify(kieenv).set(EnvironmentName.TRANSACTION_MANAGER, bittrans);
+		verify(kieenv).set(EnvironmentName.TRANSACTION, usertrans);
+		verify(kieenv).set(EnvironmentName.TRANSACTION_MANAGER, transmgr);
+		verify(kieenv).set(EnvironmentName.TRANSACTION_SYNCHRONIZATION_REGISTRY, transreg);
+		
+		verify(bds, times(1)).close();
 	}
 
 	@Test
-	public void testInitDataSource() throws Exception {
+	public void testConfigureKieEnv_RtEx() throws Exception {
 		feat.globalInit(null, SRC_TEST_RESOURCES);
 
 		mockDbConn(5);
 		setUpKie("myname", 999L, false);
 		
-		feat.activatePolicySession(polcont, "myname", "mybase");
-		
-		assertEquals(JDBC_URL, dsprops.getProperty("URL"));
-		assertEquals(JDBC_USER, dsprops.getProperty("user"));
-		assertEquals(JDBC_PASSWD, dsprops.getProperty("password"));
-		
-		verify(pds).setUniqueName("jdbc/BitronixJTADataSource/myname");
-		verify(pds).setClassName(JDBC_DATASRC);
-		verify(pds).setMaxPoolSize(anyInt());
-		verify(pds).setIsolationLevel("SERIALIZABLE");
-		verify(pds).setAllowLocalTransactions(true);
-		verify(pds).init();
+		when(fact.getUserTrans()).thenThrow(new IllegalArgumentException("expected exception"));
+
+		try {
+			feat.activatePolicySession(polcont, "myname", "mybase");
+			fail("missing exception");
+			
+		} catch(IllegalArgumentException ex) {
+			logger.trace("expected exception", ex);
+		}
+
+		verify(bds, times(2)).close();
 	}
 
 	@Test
@@ -400,14 +457,12 @@
 
 		mockDbConn(5);
 		setUpKie("myname", 999L, true);
-		
-		
-		KieSession s =
-				feat.activatePolicySession(polcont, "myname", "mybase");
+
+		KieSession s = feat.activatePolicySession(polcont, "myname", "mybase");
 
 		verify(kiestore).loadKieSession(999L, kiebase, kiecfg, kieenv);
 		verify(kiestore, never()).newKieSession(any(), any(), any());
-		
+
 		assertEquals(s, kiesess);
 	}
 
@@ -421,17 +476,15 @@
 
 		mockDbConn(5);
 		setUpKie("myname", 999L, false);
-		
+
 		when(kiestore.loadKieSession(anyLong(), any(), any(), any()))
-				.thenThrow( new RuntimeException("expected exception"));
-		
-		
-		KieSession s =
-				feat.activatePolicySession(polcont, "myname", "mybase");
+				.thenThrow(new IllegalArgumentException("expected exception"));
+
+		KieSession s = feat.activatePolicySession(polcont, "myname", "mybase");
 
 		verify(kiestore).loadKieSession(anyLong(), any(), any(), any());
 		verify(kiestore).newKieSession(any(), any(), any());
-		
+
 		assertEquals(s, kiesess);
 	}
 
@@ -441,39 +494,15 @@
 
 		mockDbConn(5);
 		setUpKie("myname", 999L, false);
-		
-		
-		KieSession s =
-				feat.activatePolicySession(polcont, "myname", "mybase");
+
+		KieSession s = feat.activatePolicySession(polcont, "myname", "mybase");
 
 		verify(kiestore).newKieSession(kiebase, null, kieenv);
-		
+
 		assertEquals(s, kiesess);
 	}
 
 	@Test
-	public void testLoadDataSource_RepeatSameSession() throws Exception {
-		feat.globalInit(null, SRC_TEST_RESOURCES);
-
-		mockDbConn(5);
-		setUpKie("myname", 999L, false);
-
-		feat.activatePolicySession(polcont, "myname", "mybase");
-
-		ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap =
-				ArgumentCaptor.forClass(PersistenceFeature.ContainerAdjunct.class);
-		
-		verify(polcont).setAdjunct(any(), adjcap.capture());
-		
-		when(polcont.getAdjunct(any())).thenReturn( adjcap.getValue());
-		
-		// invoke it again
-		feat.activatePolicySession(polcont, "myname", "mybase");
-		
-		verify(fact, times(1)).makePoolingDataSource();
-	}
-
-	@Test
 	public void testLoadDataSource_DiffSession() throws Exception {
 		feat.globalInit(null, SRC_TEST_RESOURCES);
 
@@ -481,50 +510,83 @@
 		setUpKie("myname", 999L, false);
 		feat.activatePolicySession(polcont, "myname", "mybase");
 
-		ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap =
-				ArgumentCaptor.forClass(PersistenceFeature.ContainerAdjunct.class);
-		
+		ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap = ArgumentCaptor
+				.forClass(PersistenceFeature.ContainerAdjunct.class);
+
 		verify(polcont).setAdjunct(any(), adjcap.capture());
-		
-		when(polcont.getAdjunct(any())).thenReturn( adjcap.getValue());
+
+		when(polcont.getAdjunct(any())).thenReturn(adjcap.getValue());
 
 		setUpKie("myname2", 999L, false);
-		
+
 		// invoke it again
 		feat.activatePolicySession(polcont, "myname2", "mybase");
+
+		verify(fact, times(2)).makeEntMgrFact(any());
+	}
+	
+	@Test
+	public void testSelectThreadModel_Persistent() throws Exception {
+		setUpKie("myname", 999L, true);
 		
-		verify(fact, times(2)).makePoolingDataSource();
+		ThreadModel m = feat.selectThreadModel(polsess);
+		assertNotNull(m);
+		assertTrue(m instanceof PersistentThreadModel);
+		
+	}
+	
+	@Test
+	public void testSelectThreadModel_NotPersistent() throws Exception {
+		when(fact.getPolicyController(any())).thenReturn(polctlr);
+		assertNull(feat.selectThreadModel(polsess));
+		
+	}
+	
+	@Test
+	public void testSelectThreadModel_Start__Run_Update_Stop() throws Exception {
+		setUpKie("myname", 999L, true);
+		
+		ThreadModel m = feat.selectThreadModel(polsess);
+		assertNotNull(m);
+		assertTrue(m instanceof PersistentThreadModel);
+		
+		when(polsess.getKieSession()).thenReturn(kiesess);
+		
+		m.start();
+		new CountDownLatch(1).await(10, TimeUnit.MILLISECONDS);
+		m.updated();
+		m.stop();
 	}
 
 	@Test
 	public void testDisposeKieSession() throws Exception {
 		feat.globalInit(null, SRC_TEST_RESOURCES);
 
-		ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap =
-				ArgumentCaptor.forClass(PersistenceFeature.ContainerAdjunct.class);
+		ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap = ArgumentCaptor
+				.forClass(PersistenceFeature.ContainerAdjunct.class);
 
 		mockDbConn(5);
 		setUpKie("myname", 999L, false);
-		
+
 		feat.activatePolicySession(polcont, "myname", "mybase");
-		
-		verify(pds, never()).close();
+
+		verify(emf, never()).close();
 		verify(polcont).setAdjunct(any(), adjcap.capture());
-		
-		when(polcont.getAdjunct(any())).thenReturn( adjcap.getValue());
-		
+
+		when(polcont.getAdjunct(any())).thenReturn(adjcap.getValue());
+
 		feat.disposeKieSession(polsess);
 
 		// call twice to ensure it isn't re-closed
 		feat.disposeKieSession(polsess);
-		
-		verify(pds, times(1)).close();
+
+		verify(emf, times(1)).close();
 	}
 
 	@Test
 	public void testDisposeKieSession_NoAdjunct() throws Exception {
 		feat.globalInit(null, SRC_TEST_RESOURCES);
-		
+
 		feat.disposeKieSession(polsess);
 	}
 
@@ -532,56 +594,56 @@
 	public void testDisposeKieSession_NoPersistence() throws Exception {
 		feat.globalInit(null, SRC_TEST_RESOURCES);
 
-		ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap =
-				ArgumentCaptor.forClass(PersistenceFeature.ContainerAdjunct.class);
+		ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap = ArgumentCaptor
+				.forClass(PersistenceFeature.ContainerAdjunct.class);
 
 		mockDbConn(5);
 		setUpKie("myname", 999L, false);
-		
+
 		feat.activatePolicySession(polcont, "myname", "mybase");
-		
-		verify(pds, never()).close();
+
+		verify(emf, never()).close();
 		verify(polcont).setAdjunct(any(), adjcap.capture());
-		
-		when(polcont.getAdjunct(any())).thenReturn( adjcap.getValue());
+
+		when(polcont.getAdjunct(any())).thenReturn(adjcap.getValue());
 
 		// specify a session that was never loaded
 		when(polsess.getName()).thenReturn("anotherName");
-		
+
 		feat.disposeKieSession(polsess);
-		
-		verify(pds, never()).close();
+
+		verify(emf, never()).close();
 	}
 
 	@Test
 	public void testDestroyKieSession() throws Exception {
 		feat.globalInit(null, SRC_TEST_RESOURCES);
 
-		ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap =
-				ArgumentCaptor.forClass(PersistenceFeature.ContainerAdjunct.class);
+		ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap = ArgumentCaptor
+				.forClass(PersistenceFeature.ContainerAdjunct.class);
 
 		mockDbConn(5);
 		setUpKie("myname", 999L, false);
-		
+
 		feat.activatePolicySession(polcont, "myname", "mybase");
-		
-		verify(pds, never()).close();
+
+		verify(emf, never()).close();
 		verify(polcont).setAdjunct(any(), adjcap.capture());
-		
-		when(polcont.getAdjunct(any())).thenReturn( adjcap.getValue());
-		
+
+		when(polcont.getAdjunct(any())).thenReturn(adjcap.getValue());
+
 		feat.destroyKieSession(polsess);
 
 		// call twice to ensure it isn't re-closed
 		feat.destroyKieSession(polsess);
-		
-		verify(pds, times(1)).close();
+
+		verify(emf, times(1)).close();
 	}
 
 	@Test
 	public void testDestroyKieSession_NoAdjunct() throws Exception {
 		feat.globalInit(null, SRC_TEST_RESOURCES);
-		
+
 		feat.destroyKieSession(polsess);
 	}
 
@@ -589,105 +651,105 @@
 	public void testDestroyKieSession_NoPersistence() throws Exception {
 		feat.globalInit(null, SRC_TEST_RESOURCES);
 
-		ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap =
-				ArgumentCaptor.forClass(PersistenceFeature.ContainerAdjunct.class);
+		ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap = ArgumentCaptor
+				.forClass(PersistenceFeature.ContainerAdjunct.class);
 
 		mockDbConn(5);
 		setUpKie("myname", 999L, false);
-		
+
 		feat.activatePolicySession(polcont, "myname", "mybase");
-		
-		verify(pds, never()).close();
+
+		verify(emf, never()).close();
 		verify(polcont).setAdjunct(any(), adjcap.capture());
-		
-		when(polcont.getAdjunct(any())).thenReturn( adjcap.getValue());
+
+		when(polcont.getAdjunct(any())).thenReturn(adjcap.getValue());
 
 		// specify a session that was never loaded
 		when(polsess.getName()).thenReturn("anotherName");
-		
+
 		feat.destroyKieSession(polsess);
 
-		verify(pds, never()).close();
+		verify(emf, never()).close();
 	}
 
 	@Test
 	public void testAfterStart() {
-		assertFalse( feat.afterStart(null));
+		assertFalse(feat.afterStart(null));
 	}
 
 	@Test
 	public void testBeforeStart() {
-		assertFalse( feat.beforeStart(null));
+		assertFalse(feat.beforeStart(null));
 	}
 
 	@Test
 	public void testBeforeShutdown() {
-		assertFalse( feat.beforeShutdown(null));
+		assertFalse(feat.beforeShutdown(null));
 	}
 
 	@Test
 	public void testAfterShutdown() {
-		assertFalse( feat.afterShutdown(null));
+		assertFalse(feat.afterShutdown(null));
 	}
 
 	@Test
 	public void testBeforeConfigure() {
-		assertFalse( feat.beforeConfigure(null, null));
+		assertFalse(feat.beforeConfigure(null, null));
 	}
 
 	@Test
 	public void testAfterConfigure() {
-		assertFalse( feat.afterConfigure(null));
+		assertFalse(feat.afterConfigure(null));
 	}
 
 	@Test
 	public void testBeforeActivate() {
-		assertFalse( feat.beforeActivate(null));
+		assertFalse(feat.beforeActivate(null));
 	}
 
 	@Test
 	public void testAfterActivate() {
-		assertFalse( feat.afterActivate(null));
+		assertFalse(feat.afterActivate(null));
 	}
 
 	@Test
 	public void testBeforeDeactivate() {
-		assertFalse( feat.beforeDeactivate(null));
+		assertFalse(feat.beforeDeactivate(null));
 	}
 
 	@Test
 	public void testAfterDeactivate() {
-		assertFalse( feat.afterDeactivate(null));
+		assertFalse(feat.afterDeactivate(null));
 	}
 
 	@Test
 	public void testBeforeStop() {
-		assertFalse( feat.beforeStop(null));
+		assertFalse(feat.beforeStop(null));
 	}
 
 	@Test
 	public void testAfterStop() {
-		assertFalse( feat.afterStop(null));
+		assertFalse(feat.afterStop(null));
 	}
 
 	@Test
 	public void testBeforeLock() {
-		assertFalse( feat.beforeLock(null));
+		assertFalse(feat.beforeLock(null));
 	}
 
 	@Test
 	public void testAfterLock() {
-		assertFalse( feat.afterLock(null));
+		assertFalse(feat.afterLock(null));
 	}
 
 	@Test
 	public void testBeforeUnlock() {
-		assertFalse( feat.beforeUnlock(null));
+		assertFalse(feat.beforeUnlock(null));
 	}
 
 	@Test
 	public void testAfterUnlock() {
-		assertFalse( feat.afterUnlock(null));
+		assertFalse(feat.afterUnlock(null));
 	}
 
 	@Test
@@ -697,25 +759,25 @@
 		feat.globalInit(null, SRC_TEST_RESOURCES);
 
 		setUpKie("myname", 999L, true);
-		
+
 		feat.activatePolicySession(polcont, "myname", "mybase");
-		
+
 		verify(s).executeUpdate();
 	}
 
 	@Test
 	public void testGetPersistenceTimeout_Missing() throws Exception {
-		
+
 		props.remove(DroolsPersistenceProperties.DB_SESSIONINFO_TIMEOUT);
-		
+
 		PreparedStatement s = mockDbConn(0);
 
 		feat.globalInit(null, SRC_TEST_RESOURCES);
 
 		setUpKie("myname", 999L, true);
-		
+
 		feat.activatePolicySession(polcont, "myname", "mybase");
-		
+
 		verify(s, never()).executeUpdate();
 	}
 
@@ -727,46 +789,31 @@
 		feat.globalInit(null, SRC_TEST_RESOURCES);
 
 		setUpKie("myname", 999L, true);
-		
+
 		feat.activatePolicySession(polcont, "myname", "mybase");
-		
+
 		verify(s, never()).executeUpdate();
 	}
 
 	@Test
-	public void testInitHostName() throws Exception {
-		when(fact.getHostName()).thenReturn("myhost");
-		
-		feat.globalInit(null, SRC_TEST_RESOURCES);
-		
-		verify(bitcfg).setServerId("myhost");
-	}
-
-	@Test(expected = RuntimeException.class)
-	public void testInitHostName_Ex() throws Exception {
-		when(fact.getHostName())
-				.thenThrow(
-						new UnknownHostException("expected exception"));
-		
-		feat.globalInit(null, SRC_TEST_RESOURCES);
-	}
-
-	@Test
 	public void testCleanUpSessionInfo() throws Exception {
 		setUpKie("myname", 999L, true);
-		
+
 		// use a real DB so we can verify that the "delete" works correctly
 		fact = new PartialFactory();
 		feat.setFactory(fact);
-		
+
 		makeSessionInfoTbl(20000);
 
-		
+		// create mock entity manager for use by JPA connector
+		EntityManager em = mock(EntityManager.class);
+		when(emf.createEntityManager()).thenReturn(em);
+
 		feat.globalInit(null, SRC_TEST_RESOURCES);
-		
+
 		feat.beforeStart(null);
 		feat.activatePolicySession(polcont, "myname", "mybase");
-		
+
 		assertEquals("[1, 4, 5]", getSessions().toString());
 	}
 
@@ -777,10 +824,10 @@
 		feat.globalInit(null, SRC_TEST_RESOURCES);
 
 		setUpKie("myname", 999L, true);
-		
+
 		// reset
 		feat.beforeStart(null);
-		
+
 		feat.activatePolicySession(polcont, "myname", "mybase");
 		verify(s, times(1)).executeUpdate();
 
@@ -788,11 +835,10 @@
 		feat.activatePolicySession(polcont, "myname", "mybase");
 		feat.activatePolicySession(polcont, "myname", "mybase");
 		verify(s, times(1)).executeUpdate();
-		
 
 		// reset
 		feat.beforeStart(null);
-		
+
 		feat.activatePolicySession(polcont, "myname", "mybase");
 		verify(s, times(2)).executeUpdate();
 
@@ -809,10 +855,10 @@
 		feat.globalInit(null, SRC_TEST_RESOURCES);
 
 		setUpKie("myname", 999L, true);
-		
+
 		// reset
 		feat.beforeActivate(null);
-		
+
 		feat.activatePolicySession(polcont, "myname", "mybase");
 		verify(s, times(1)).executeUpdate();
 
@@ -820,11 +866,10 @@
 		feat.activatePolicySession(polcont, "myname", "mybase");
 		feat.activatePolicySession(polcont, "myname", "mybase");
 		verify(s, times(1)).executeUpdate();
-		
 
 		// reset
 		feat.beforeActivate(null);
-		
+
 		feat.activatePolicySession(polcont, "myname", "mybase");
 		verify(s, times(2)).executeUpdate();
 
@@ -838,60 +883,75 @@
 	public void testCleanUpSessionInfo_NoTimeout() throws Exception {
 
 		props.remove(DroolsPersistenceProperties.DB_SESSIONINFO_TIMEOUT);
-		
+
 		PreparedStatement s = mockDbConn(0);
 
 		feat.globalInit(null, SRC_TEST_RESOURCES);
 
 		setUpKie("myname", 999L, true);
-		
+
 		feat.activatePolicySession(polcont, "myname", "mybase");
-		
+
 		verify(s, never()).executeUpdate();
 	}
 
 	@Test
 	public void testCleanUpSessionInfo_NoUrl() throws Exception {
 		PreparedStatement s = mockDbConn(0);
-		
+
 		props.remove(DroolsPersistenceProperties.DB_URL);
 
 		feat.globalInit(null, SRC_TEST_RESOURCES);
 
 		setUpKie("myname", 999L, true);
-		
-		feat.activatePolicySession(polcont, "myname", "mybase");
-		
+
+		try {
+			feat.activatePolicySession(polcont, "myname", "mybase");
+			fail("missing exception");
+		} catch (RuntimeException e) {
+			logger.trace("expected exception", e);
+		}
+
 		verify(s, never()).executeUpdate();
 	}
 
 	@Test
 	public void testCleanUpSessionInfo_NoUser() throws Exception {
 		PreparedStatement s = mockDbConn(0);
-		
+
 		props.remove(DroolsPersistenceProperties.DB_USER);
 
 		feat.globalInit(null, SRC_TEST_RESOURCES);
 
 		setUpKie("myname", 999L, true);
-		
-		feat.activatePolicySession(polcont, "myname", "mybase");
-		
+
+		try {
+			feat.activatePolicySession(polcont, "myname", "mybase");
+			fail("missing exception");
+		} catch (RuntimeException e) {
+			logger.trace("expected exception", e);
+		}
+
 		verify(s, never()).executeUpdate();
 	}
 
 	@Test
 	public void testCleanUpSessionInfo_NoPassword() throws Exception {
 		PreparedStatement s = mockDbConn(0);
-		
+
 		props.remove(DroolsPersistenceProperties.DB_PWD);
 
 		feat.globalInit(null, SRC_TEST_RESOURCES);
 
 		setUpKie("myname", 999L, true);
-		
-		feat.activatePolicySession(polcont, "myname", "mybase");
-		
+
+		try {
+			feat.activatePolicySession(polcont, "myname", "mybase");
+			fail("missing exception");
+		} catch (RuntimeException e) {
+			logger.trace("expected exception", e);
+		}
+
 		verify(s, never()).executeUpdate();
 	}
 
@@ -902,9 +962,9 @@
 		feat.globalInit(null, SRC_TEST_RESOURCES);
 
 		setUpKie("myname", 999L, true);
-		
+
 		feat.activatePolicySession(polcont, "myname", "mybase");
-		
+
 		verify(s).executeUpdate();
 	}
 
@@ -914,51 +974,29 @@
 
 		mockDbConn(5);
 		setUpKie("myname", 999L, true);
-		
-		
+
 		feat.activatePolicySession(polcont, "myname", "mybase");
 
-
-		ArgumentCaptor<Properties> propcap =
-				ArgumentCaptor.forClass(Properties.class);
-		
-		verify(fact).makeJpaConnector(anyString(), propcap.capture());
-		
-		Properties p = propcap.getValue();
-		assertNotNull(p);
-		
-		assertEquals(JDBC_DRIVER,
-				p.getProperty("javax.persistence.jdbc.driver"));
-		
-		assertEquals(JDBC_URL,
-				p.getProperty("javax.persistence.jdbc.url"));
-		
-		assertEquals(JDBC_USER,
-				p.getProperty("javax.persistence.jdbc.user"));
-		
-		assertEquals(JDBC_PASSWD,
-				p.getProperty("javax.persistence.jdbc.password"));
+		verify(fact).makeJpaConnector(emf);
 	}
 
 	@Test
 	public void testReplaceSession() throws Exception {
 		feat.globalInit(null, SRC_TEST_RESOURCES);
 
-		ArgumentCaptor<DroolsSession> sesscap =
-				ArgumentCaptor.forClass(DroolsSession.class);
+		ArgumentCaptor<DroolsSession> sesscap = ArgumentCaptor.forClass(DroolsSession.class);
 
 		mockDbConn(5);
 		setUpKie("myname", 999L, true);
-		
-		
+
 		feat.activatePolicySession(polcont, "myname", "mybase");
-		
-		verify(jpa).replace( sesscap.capture());
-		
+
+		verify(jpa).replace(sesscap.capture());
+
 		assertEquals("myname", sesscap.getValue().getSessionName());
 		assertEquals(999L, sesscap.getValue().getSessionId());
 	}
-	
+
 	@Test
 	public void testIsPersistenceEnabled_Auto() throws Exception {
 		feat.globalInit(null, SRC_TEST_RESOURCES);
@@ -967,10 +1005,10 @@
 		setUpKie("myname", 999L, true);
 
 		props.setProperty("persistence.type", "auto");
-		
-		assertNotNull( feat.activatePolicySession(polcont, "myname", "mybase"));
+
+		assertNotNull(feat.activatePolicySession(polcont, "myname", "mybase"));
 	}
-	
+
 	@Test
 	public void testIsPersistenceEnabled_Native() throws Exception {
 		feat.globalInit(null, SRC_TEST_RESOURCES);
@@ -979,10 +1017,10 @@
 		setUpKie("myname", 999L, true);
 
 		props.setProperty("persistence.type", "native");
-		
-		assertNotNull( feat.activatePolicySession(polcont, "myname", "mybase"));
+
+		assertNotNull(feat.activatePolicySession(polcont, "myname", "mybase"));
 	}
-	
+
 	@Test
 	public void testIsPersistenceEnabled_None() throws Exception {
 		feat.globalInit(null, SRC_TEST_RESOURCES);
@@ -991,23 +1029,22 @@
 		setUpKie("myname", 999L, true);
 
 		props.remove("persistence.type");
-		
-		assertNull( feat.activatePolicySession(polcont, "myname", "mybase"));
+
+		assertNull(feat.activatePolicySession(polcont, "myname", "mybase"));
 	}
-	
+
 	@Test
 	public void testGetProperties_Ex() throws Exception {
 		feat.globalInit(null, SRC_TEST_RESOURCES);
 
 		mockDbConn(5);
 		setUpKie("myname", 999L, true);
-		
-		when(fact.getPolicyContainer(polcont))
-			.thenThrow( new IllegalArgumentException("expected exception"));
 
-		assertNull( feat.activatePolicySession(polcont, "myname", "mybase"));
+		when(fact.getPolicyController(polcont)).thenThrow(new IllegalArgumentException("expected exception"));
+
+		assertNull(feat.activatePolicySession(polcont, "myname", "mybase"));
 	}
-	
+
 	@Test
 	public void testGetProperty_Specific() throws Exception {
 		feat.globalInit(null, SRC_TEST_RESOURCES);
@@ -1017,10 +1054,10 @@
 
 		props.remove("persistence.type");
 		props.setProperty("persistence.myname.type", "auto");
-		
-		assertNotNull( feat.activatePolicySession(polcont, "myname", "mybase"));
+
+		assertNotNull(feat.activatePolicySession(polcont, "myname", "mybase"));
 	}
-	
+
 	@Test
 	public void testGetProperty_Specific_None() throws Exception {
 		feat.globalInit(null, SRC_TEST_RESOURCES);
@@ -1030,10 +1067,10 @@
 
 		props.remove("persistence.type");
 		props.setProperty("persistence.xxx.type", "auto");
-		
-		assertNull( feat.activatePolicySession(polcont, "myname", "mybase"));
+
+		assertNull(feat.activatePolicySession(polcont, "myname", "mybase"));
 	}
-	
+
 	@Test
 	public void testGetProperty_Both_SpecificOn() throws Exception {
 		feat.globalInit(null, SRC_TEST_RESOURCES);
@@ -1043,10 +1080,10 @@
 
 		props.setProperty("persistence.type", "other");
 		props.setProperty("persistence.myname.type", "auto");
-		
-		assertNotNull( feat.activatePolicySession(polcont, "myname", "mybase"));
+
+		assertNotNull(feat.activatePolicySession(polcont, "myname", "mybase"));
 	}
-	
+
 	@Test
 	public void testGetProperty_Both_SpecificDisabledOff() throws Exception {
 		feat.globalInit(null, SRC_TEST_RESOURCES);
@@ -1056,10 +1093,10 @@
 
 		props.setProperty("persistence.type", "auto");
 		props.setProperty("persistence.myname.type", "other");
-		
-		assertNull( feat.activatePolicySession(polcont, "myname", "mybase"));
+
+		assertNull(feat.activatePolicySession(polcont, "myname", "mybase"));
 	}
-	
+
 	@Test
 	public void testGetProperty_None() throws Exception {
 		feat.globalInit(null, SRC_TEST_RESOURCES);
@@ -1068,70 +1105,157 @@
 		setUpKie("myname", 999L, true);
 
 		props.remove("persistence.type");
-		
-		assertNull( feat.activatePolicySession(polcont, "myname", "mybase"));
+
+		assertNull(feat.activatePolicySession(polcont, "myname", "mybase"));
 	}
 
-	
+	@Test
+	public void testPersistenceFeatureException() {
+		SecurityException secex = new SecurityException("expected exception");
+		PersistenceFeatureException ex = new PersistenceFeatureException(secex);
+
+		assertEquals(secex, ex.getCause());
+
+	}
+
+	@Test
+	public void testDsEmf_RtEx() throws Exception {
+		feat.globalInit(null, SRC_TEST_RESOURCES);
+
+		mockDbConn(5);
+		setUpKie("myname", 999L, false);
+		
+		when(fact.makeEntMgrFact(any())).thenThrow(new IllegalArgumentException("expected exception"));
+
+		try {
+			feat.activatePolicySession(polcont, "myname", "mybase");
+			fail("missing exception");
+			
+		} catch(IllegalArgumentException ex) {
+			logger.trace("expected exception", ex);
+		}
+
+		verify(bds, times(2)).close();
+	}
+
+	@Test
+	public void testDsEmf_Close_RtEx() throws Exception {
+		feat.globalInit(null, SRC_TEST_RESOURCES);
+
+		mockDbConn(5);
+		setUpKie("myname", 999L, false);
+		
+		feat.activatePolicySession(polcont, "myname", "mybase");
+
+		ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap = ArgumentCaptor
+				.forClass(PersistenceFeature.ContainerAdjunct.class);
+
+		verify(polcont, times(1)).setAdjunct(any(), adjcap.capture());
+
+		// return adjunct on next call
+		when(polcont.getAdjunct(any())).thenReturn(adjcap.getValue());
+
+		try {
+			doThrow(new IllegalArgumentException("expected exception")).when(emf).close();
+			
+			feat.destroyKieSession(polsess);
+			fail("missing exception");
+			
+		} catch(IllegalArgumentException ex) {
+			logger.trace("expected exception", ex);
+		}
+
+		verify(bds, times(2)).close();
+	}
+
+	@Test
+	public void testDsEmf_CloseDataSource_RtEx() throws Exception {
+		feat.globalInit(null, SRC_TEST_RESOURCES);
+
+		mockDbConn(5);
+		setUpKie("myname", 999L, false);
+		
+		feat.activatePolicySession(polcont, "myname", "mybase");
+
+		ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap = ArgumentCaptor
+				.forClass(PersistenceFeature.ContainerAdjunct.class);
+
+		verify(polcont, times(1)).setAdjunct(any(), adjcap.capture());
+
+		// return adjunct on next call
+		when(polcont.getAdjunct(any())).thenReturn(adjcap.getValue());
+
+		try {
+			doThrow(new SQLException("expected exception")).when(bds).close();
+			
+			feat.destroyKieSession(polsess);
+			fail("missing exception");
+			
+		} catch(PersistenceFeatureException ex) {
+			logger.trace("expected exception", ex);
+		}
+	}
+
 	/**
 	 * Gets an ordered list of ids of the current SessionInfo records.
+	 * 
 	 * @return ordered list of SessInfo IDs
-	 * @throws SQLException 
-	 * @throws IOException 
+	 * @throws SQLException
+	 * @throws IOException
 	 */
 	private List<Integer> getSessions() throws SQLException, IOException {
 		attachDb();
-		
+
 		ArrayList<Integer> lst = new ArrayList<>(5);
 
-		try(
-				PreparedStatement stmt = conn.prepareStatement("SELECT id from sessioninfo order by id");
+		try (PreparedStatement stmt = conn.prepareStatement("SELECT id from sessioninfo order by id");
 				ResultSet rs = stmt.executeQuery()) {
-			
-			while(rs.next()) {
-				lst.add( rs.getInt(1));
+
+			while (rs.next()) {
+				lst.add(rs.getInt(1));
 			}
 		}
-		
+
 		return lst;
 	}
-	
+
 	/**
 	 * Sets up for doing invoking the newKieSession() method.
-	 * @param sessnm	name to which JPA should respond with a session
-	 * @param sessid	session id to be returned by the session
-	 * @param loadOk 	{@code true} if loadKieSession() should return a
-	 * 					value, {@code false} to return null
+	 * 
+	 * @param sessnm
+	 *            name to which JPA should respond with a session
+	 * @param sessid
+	 *            session id to be returned by the session
+	 * @param loadOk
+	 *            {@code true} if loadKieSession() should return a value,
+	 *            {@code false} to return null
+	 * @throws Exception 
 	 */
-	private void setUpKie(String sessnm, long sessid, boolean loadOk) {
-		
-		when(fact.makeJpaConnector(any(), any())).thenReturn(jpa);
-		when(fact.makePoolingDataSource()).thenReturn(pds);
-		when(fact.getPolicyContainer(polcont)).thenReturn(polctlr);
-		
+	private void setUpKie(String sessnm, long sessid, boolean loadOk) throws Exception {
+
+		when(fact.makeJpaConnector(emf)).thenReturn(jpa);
+		when(fact.makeEntMgrFact(any())).thenReturn(emf);
+		when(fact.getPolicyController(polcont)).thenReturn(polctlr);
+
 		props.setProperty("persistence.type", "auto");
-		
+
 		when(polctlr.getProperties()).thenReturn(props);
-		
+
 		when(jpa.get(sessnm)).thenReturn(sess);
-		
-		when(pds.getDriverProperties()).thenReturn(dsprops);
-		
+
 		when(sess.getSessionId()).thenReturn(sessid);
-		
+
 		when(polsess.getPolicyContainer()).thenReturn(polcont);
 		when(polsess.getName()).thenReturn(sessnm);
-		
-		if(loadOk) {
+
+		if (loadOk) {
 			when(kiesess.getIdentifier()).thenReturn(sessid);
-			when(kiestore.loadKieSession(anyLong(), any(), any(), any()))
-					.thenReturn(kiesess);
-			
+			when(kiestore.loadKieSession(anyLong(), any(), any(), any())).thenReturn(kiesess);
+
 		} else {
 			// use an alternate id for the new session
 			when(kiesess.getIdentifier()).thenReturn(100L);
-			when(kiestore.loadKieSession(anyLong(), any(), any(), any()))
-					.thenReturn(null);
+			when(kiestore.loadKieSession(anyLong(), any(), any(), any())).thenReturn(null);
 		}
 
 		when(kiestore.newKieSession(any(), any(), any())).thenReturn(kiesess);
@@ -1139,48 +1263,47 @@
 
 	/**
 	 * Creates the SessionInfo DB table and populates it with some data.
-	 * @param expMs 	number of milli-seconds for expired sessioninfo records
-	 * @throws SQLException 
-	 * @throws IOException 
+	 * 
+	 * @param expMs
+	 *            number of milli-seconds for expired sessioninfo records
+	 * @throws SQLException
+	 * @throws IOException
 	 */
-	private void makeSessionInfoTbl(int expMs)
-				throws SQLException, IOException {
-		
+	private void makeSessionInfoTbl(int expMs) throws SQLException, IOException {
+
 		attachDb();
 
-		try(
-				PreparedStatement stmt = conn.prepareStatement(
-						"CREATE TABLE sessioninfo(id int, lastmodificationdate timestamp)")) {
+		try (PreparedStatement stmt = conn
+				.prepareStatement("CREATE TABLE sessioninfo(id int, lastmodificationdate timestamp)")) {
 
-			stmt.executeUpdate();	
+			stmt.executeUpdate();
 		}
 
-		try(
-				PreparedStatement stmt = conn.prepareStatement(
-						"INSERT into sessioninfo(id, lastmodificationdate) values(?, ?)")) {
+		try (PreparedStatement stmt = conn
+				.prepareStatement("INSERT into sessioninfo(id, lastmodificationdate) values(?, ?)")) {
 
 			Timestamp ts;
-			
+
 			// current data
-			ts = new Timestamp( System.currentTimeMillis());
+			ts = new Timestamp(System.currentTimeMillis());
 			stmt.setTimestamp(2, ts);
-	
+
 			stmt.setInt(1, 1);
 			stmt.executeUpdate();
-	
+
 			stmt.setInt(1, 4);
 			stmt.executeUpdate();
-	
+
 			stmt.setInt(1, 5);
 			stmt.executeUpdate();
-			
+
 			// expired data
-			ts = new Timestamp( System.currentTimeMillis() - expMs);
+			ts = new Timestamp(System.currentTimeMillis() - expMs);
 			stmt.setTimestamp(2, ts);
-	
+
 			stmt.setInt(1, 2);
 			stmt.executeUpdate();
-	
+
 			stmt.setInt(1, 3);
 			stmt.executeUpdate();
 		}
@@ -1188,17 +1311,18 @@
 
 	/**
 	 * Attaches {@link #conn} to the DB, if it isn't already attached.
+	 * 
 	 * @throws SQLException
-	 * @throws IOException if the property file cannot be read
+	 * @throws IOException
+	 *             if the property file cannot be read
 	 */
 	private void attachDb() throws SQLException, IOException {
-		if(conn == null) {
+		if (conn == null) {
 			Properties p = loadDbProps();
-			
-			conn = DriverManager.getConnection(
-						p.getProperty(DroolsPersistenceProperties.DB_URL),
-						p.getProperty(DroolsPersistenceProperties.DB_USER),
-						p.getProperty(DroolsPersistenceProperties.DB_PWD));
+
+			conn = DriverManager.getConnection(p.getProperty(DroolsPersistenceProperties.DB_URL),
+					p.getProperty(DroolsPersistenceProperties.DB_USER),
+					p.getProperty(DroolsPersistenceProperties.DB_PWD));
 			conn.setAutoCommit(true);
 		}
 	}
@@ -1206,27 +1330,30 @@
 	/**
 	 * Loads the DB properties from the file,
 	 * <i>feature-session-persistence.properties</i>.
+	 * 
 	 * @return the properties that were loaded
-	 * @throws IOException if the property file cannot be read
-	 * @throws FileNotFoundException if the property file does not exist
+	 * @throws IOException
+	 *             if the property file cannot be read
+	 * @throws FileNotFoundException
+	 *             if the property file does not exist
 	 */
-	private Properties loadDbProps()
-				throws IOException, FileNotFoundException {
-		
+	private Properties loadDbProps() throws IOException, FileNotFoundException {
+
 		Properties p = new Properties();
-		
-		try(FileReader rdr = new FileReader(
-				"src/test/resources/feature-session-persistence.properties")) {
+
+		try (FileReader rdr = new FileReader("src/test/resources/feature-session-persistence.properties")) {
 			p.load(rdr);
 		}
-		
+
 		return p;
 	}
 
 	/**
 	 * Create a mock DB connection and statement.
-	 * @param retval	value to be returned when the statement is executed,
-	 * 					or negative to throw an exception
+	 * 
+	 * @param retval
+	 *            value to be returned when the statement is executed, or
+	 *            negative to throw an exception
 	 * @return the statement that will be returned by the connection
 	 * @throws SQLException
 	 */
@@ -1234,32 +1361,41 @@
 		Connection c = mock(Connection.class);
 		PreparedStatement s = mock(PreparedStatement.class);
 
-		when(fact.makeDbConnection(anyString(), anyString(), anyString()))
-				.thenReturn(c);
+		when(bds.getConnection()).thenReturn(c);
+		when(fact.makeDataSource(any())).thenReturn(bds);
 		when(c.prepareStatement(anyString())).thenReturn(s);
-		
-		if(retval < 0) {
+
+		if (retval < 0) {
 			// should throw an exception
-			when(s.executeUpdate())
-				.thenThrow( new SQLException("expected exception"));
-			
+			when(s.executeUpdate()).thenThrow(new SQLException("expected exception"));
+
 		} else {
 			// should return the value
 			when(s.executeUpdate()).thenReturn(retval);
 		}
-		
+
 		return s;
 	}
-	
+
 	/**
-	 * A partial factory, which exports a few of the real methods, but
-	 * overrides the rest.
+	 * A partial factory, which exports a few of the real methods, but overrides
+	 * the rest.
 	 */
 	private class PartialFactory extends PersistenceFeature.Factory {
-		
+
 		@Override
-		public PoolingDataSource makePoolingDataSource() {
-			return pds;
+		public TransactionManager getTransMgr() {
+			return transmgr;
+		}
+
+		@Override
+		public UserTransaction getUserTrans() {
+			return usertrans;
+		}
+
+		@Override
+		public TransactionSynchronizationRegistry getTransSyncReg() {
+			return transreg;
 		}
 
 		@Override
@@ -1268,24 +1404,14 @@
 		}
 
 		@Override
-		public BitronixTransactionManager getTransMgr() {
-			return null;
+		public EntityManagerFactory makeEntMgrFact(Map<String, Object> props) {
+			return emf;
 		}
 
 		@Override
-		public EntityManagerFactory makeEntMgrFact(String pu,
-													Properties propMap) {
-			if(pu.equals("onapsessionsPU")) {
-				return null;
-			}
-			
-			return super.makeEntMgrFact("junitPersistenceFeaturePU", propMap);
-		}
-
-		@Override
-		public PolicyController getPolicyContainer(PolicyContainer container) {
+		public PolicyController getPolicyController(PolicyContainer container) {
 			return polctlr;
 		}
-		
+
 	}
 }
diff --git a/feature-session-persistence/src/test/resources/META-INF/persistence.xml b/feature-session-persistence/src/test/resources/META-INF/persistence.xml
index 6794e24..5cc1bad 100644
--- a/feature-session-persistence/src/test/resources/META-INF/persistence.xml
+++ b/feature-session-persistence/src/test/resources/META-INF/persistence.xml
@@ -23,16 +23,8 @@
 	xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
 
-	<persistence-unit name="junitDroolsSessionEntityPU" transaction-type="RESOURCE_LOCAL">
-		<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
-		<class>org.onap.policy.drools.persistence.DroolsSessionEntity</class>
-		<properties>
-			<property name="javax.persistence.schema-generation.database.action" value="create"/>
-        </properties>
-	</persistence-unit>
-	
-	<persistence-unit name="junitPersistenceFeaturePU" transaction-type="RESOURCE_LOCAL">
-		<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
+	<persistence-unit name="junitDroolsSessionEntityPU" transaction-type="JTA">
+		<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
 		<class>org.onap.policy.drools.persistence.DroolsSessionEntity</class>
 		<properties>
 			<property name="javax.persistence.schema-generation.database.action" value="create"/>
diff --git a/feature-session-persistence/src/test/resources/feature-session-persistence.properties b/feature-session-persistence/src/test/resources/feature-session-persistence.properties
index 6b448dc..a1e9cc4 100644
--- a/feature-session-persistence/src/test/resources/feature-session-persistence.properties
+++ b/feature-session-persistence/src/test/resources/feature-session-persistence.properties
@@ -23,6 +23,5 @@
 javax.persistence.jdbc.user=testuser
 javax.persistence.jdbc.password=testpass
 
-hibernate.dataSource=org.h2.jdbcx.JdbcDataSource
-
 persistence.sessioninfo.timeout=10
+persistence.objectstore.dir=target/jta