Replace bitronix and eclipselink in persistence 69/31769/1
authorJim Hahn <jrh3@att.com>
Wed, 14 Feb 2018 17:52:31 +0000 (12:52 -0500)
committerJim Hahn <jrh3@att.com>
Wed, 14 Feb 2018 21:14:17 +0000 (16:14 -0500)
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>
17 files changed:
feature-session-persistence/pom.xml
feature-session-persistence/src/main/feature/config/feature-session-persistence.properties
feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/DroolsPersistenceProperties.java
feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/DroolsSessionEntity.java
feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/EntityMgrCloser.java [deleted file]
feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/EntityMgrTrans.java
feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/JpaDroolsSessionConnector.java
feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/PersistenceFeature.java
feature-session-persistence/src/main/resources/META-INF/persistence.xml
feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/DroolsSessionEntityTest.java
feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/EntityMgrCloserTest.java [deleted file]
feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/EntityMgrTransTest.java
feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/GenSchema.java [moved from feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/GenSchemaTest.java with 65% similarity]
feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/JpaDroolsSessionConnectorTest.java
feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/PersistenceFeatureTest.java
feature-session-persistence/src/test/resources/META-INF/persistence.xml
feature-session-persistence/src/test/resources/feature-session-persistence.properties

index a8b01f8..70d37f2 100644 (file)
                        <version>${project.version}</version>
                        <scope>provided</scope>
                </dependency>
+               <dependency>
+                       <groupId>org.onap.policy.common</groupId>
+                       <artifactId>utils</artifactId>
+                       <version>${project.version}</version>
+               </dependency>
                <dependency>
                        <groupId>org.powermock</groupId>
                        <artifactId>powermock-api-mockito</artifactId>
                        <version>3.21.0-GA</version>
                        <scope>test</scope>
                </dependency>
-               <dependency>
-                       <groupId>org.codehaus.btm</groupId>
-                       <artifactId>btm</artifactId>
-                       <version>2.1.4</version>
-               </dependency>
+               <dependency>
+                       <groupId>org.jboss.jbossts</groupId>
+                       <artifactId>jbossjta</artifactId>
+                       <version>4.16.6.Final</version>
+                       <exclusions>
+                               <exclusion>
+                                       <artifactId>jboss-servlet-api_3.0_spec</artifactId>
+                                       <groupId>org.jboss.spec.javax.servlet</groupId>
+                               </exclusion>
+                       </exclusions>
+               </dependency>
                <dependency>
                        <groupId>com.h2database</groupId>
                        <artifactId>h2</artifactId>
                        <scope>provided</scope>
                </dependency>
                <dependency>
-                       <groupId>junit</groupId>
-                       <artifactId>junit</artifactId>
-                       <scope>provided</scope>
+                       <groupId>org.apache.commons</groupId>
+                       <artifactId>commons-dbcp2</artifactId>
+                       <version>2.1.1</version>
                </dependency>
                <dependency>
-                       <groupId>org.eclipse.persistence</groupId>
-                       <artifactId>eclipselink</artifactId>
-                       <scope>provided</scope>
+                       <groupId>org.apache.commons</groupId>
+                       <artifactId>commons-pool2</artifactId>
+                       <version>2.4.2</version>
+               </dependency>
+               
+               <dependency>
+                       <groupId>junit</groupId>
+                       <artifactId>junit</artifactId>
+                       <scope>test</scope>
                </dependency>
        </dependencies>
 </project>
index 6204b5e..0f15e3a 100644 (file)
@@ -22,7 +22,8 @@ javax.persistence.jdbc.driver= org.mariadb.jdbc.Driver
 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
index 1c935b0..42a638a 100644 (file)
@@ -27,10 +27,9 @@ public class DroolsPersistenceProperties {
         * 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";
 }
index e9c5b33..b3616c4 100644 (file)
@@ -35,53 +35,53 @@ import javax.persistence.TemporalType;
 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 @@ public class DroolsSessionEntity implements Serializable, DroolsSession {
                this.sessionId = sessionId;
        }
 
-       @Override       
+       @Override
        public Date getCreatedDate() {
                return createdDate;
        }
@@ -112,17 +112,16 @@ public class DroolsSessionEntity implements Serializable, DroolsSession {
                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 @@ public class DroolsSessionEntity implements Serializable, DroolsSession {
                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 (file)
index 5829211..0000000
+++ /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();
-       }
-
-}
index 79b620d..9bb26ac 100644 (file)
 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 @@ public class EntityMgrTrans extends EntityMgrCloser {
        /**
         * Transaction to be rolled back.
         */
-       private EntityTransaction trans;
+       private static UserTransaction userTrans = com.arjuna.ats.jta.UserTransaction.userTransaction();
 
        /**
         * 
@@ -43,39 +51,94 @@ public class EntityMgrTrans extends EntityMgrCloser {
                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);
+               }
+       }
 }
index 76c0968..cd76ae8 100644 (file)
@@ -26,14 +26,12 @@ import javax.persistence.EntityManagerFactory;
 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 @@ public class JpaDroolsSessionConnector implements DroolsSessionConnector {
 
                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 @@ public class JpaDroolsSessionConnector implements DroolsSessionConnector {
        @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;
        }
 }
index db33d05..032383b 100644 (file)
 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 java.util.concurrent.TimeUnit;
 
 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.onap.policy.drools.utils.PropertyUtil;
 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 @@ public class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngine
 
        private static final Logger logger = LoggerFactory.getLogger(PersistenceFeature.class);
 
-
        /**
         * Standard factory used to get various items.
         */
@@ -87,11 +82,6 @@ public class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngine
         */
        private KieServices kieSvcFact;
 
-       /**
-        * Host name.
-        */
-       private String hostName;
-
        /**
         * Persistence properties.
         */
@@ -159,10 +149,8 @@ public class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngine
         */
        @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 @@ public class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngine
                }
 
                sessionInfoTimeoutMs = getPersistenceTimeout();
-
-               Configuration bitronixConfiguration = fact.getTransMgrConfig();
-               bitronixConfiguration.setJournal(null);
-               bitronixConfiguration.setServerId(hostName);
        }
 
        /**
@@ -199,6 +183,7 @@ public class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngine
         */
        @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 @@ public class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngine
         */
        @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 class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngine
        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 @@ public class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngine
 
                } 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 @@ public class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngine
                 * '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 @@ public class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngine
                 */
                private KieSession newPersistentKieSession(String name, String kieBaseName) {
 
-                       long desiredSessionId;
-
-                       DroolsSessionConnector conn = getDroolsSessionConnector("onapPU");
+                       configureSysProps();
 
-                       desiredSessionId = getSessionId(conn, name);
+                       BasicDataSource ds = fact.makeDataSource(getDataSourceProperties());
+                       DsEmf dsemf = new DsEmf(ds);
 
-                       logger.info("\n\nThis controller is primary... coming up with session {} \n\n", desiredSessionId);
+                       try {
+                               EntityManagerFactory emf = dsemf.emf;
+                               DroolsSessionConnector conn = fact.makeJpaConnector(emf);
 
-                       // session does not exist -- attempt to create one
-                       logger.info("getPolicySession:session does not exist -- attempt to create one with name {}", name);
+                               long desiredSessionId = getSessionId(conn, name);
 
-                       System.getProperties().put("java.naming.factory.initial", "bitronix.tm.jndi.BitronixInitialContextFactory");
+                               logger.info("\n\nThis controller is primary... coming up with session {} \n\n", desiredSessionId);
 
-                       Environment env = kieSvcFact.newEnvironment();
-                       String dsName = loadDataSource(name);
+                               // session does not exist -- attempt to create one
+                               logger.info("getPolicySession:session does not exist -- attempt to create one with name {}", name);
 
-                       configureKieEnv(name, env, dsName);
+                               Environment env = kieSvcFact.newEnvironment();
 
-                       KieSessionConfiguration kConf = kieSvcFact.newKieSessionConfiguration();
+                               configureKieEnv(env, emf);
 
-                       KieSession kieSession = desiredSessionId >= 0 ? loadKieSession(kieBaseName, desiredSessionId, env, kConf)
-                                       : null;
+                               KieSessionConfiguration kConf = kieSvcFact.newKieSessionConfiguration();
 
-                       if (kieSession == null) {
-                               // loadKieSession() returned null or desiredSessionId < 0
-                               logger.info("LOADING We cannot load session {}. Going to create a new one", desiredSessionId);
+                               KieSession kieSession = (desiredSessionId >= 0
+                                               ? loadKieSession(kieBaseName, desiredSessionId, env, kConf) : null);
 
-                               kieSession = newKieSession(kieBaseName, env);
-                       }
+                               if (kieSession == null) {
+                                       // loadKieSession() returned null or desiredSessionId < 0
+                                       logger.info("LOADING We cannot load session {}. Going to create a new one", desiredSessionId);
 
-                       replaceSession(conn, name, kieSession);
+                                       kieSession = newKieSession(kieBaseName, env);
+                               }
 
-                       return kieSession;
-               }
+                               replaceSession(conn, name, 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();
-               }
+                               name2ds.put(name, dsemf);
 
-               /**
-                * 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);
+                               return kieSession;
 
-                       env.set(EnvironmentName.ENTITY_MANAGER_FACTORY, emfact);
-                       env.set(EnvironmentName.TRANSACTION_MANAGER, fact.getTransMgr());
+                       } catch (RuntimeException e) {
+                               dsemf.close();
+                               throw e;
+                       }
                }
 
                /**
@@ -487,7 +418,9 @@ public class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngine
 
                /**
                 * 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 @@ public class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngine
 
                /**
                 * 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 @@ public class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngine
 
                /**
                 * 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();
                        }
                }
@@ -515,6 +452,53 @@ public class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngine
 
        /* ============================================================ */
 
+       /**
+        * 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
@@ -534,21 +518,15 @@ public class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngine
                                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);
@@ -564,40 +542,6 @@ public class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngine
                }
        }
 
-       /**
-        * 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.
         * 
@@ -613,8 +557,8 @@ public class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngine
        }
 
        /**
-        * 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 @@ public class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngine
         */
        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 @@ public class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngine
         * compatible with persistence.
         */
        public class PersistentThreadModel implements Runnable, PolicySession.ThreadModel {
-               
+
                /**
                 * Session associated with this persistent thread.
                 */
@@ -715,22 +659,22 @@ public class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngine
                 * 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 class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngine
                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 @@ public class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngine
                                minSleepTime = maxSleepTime;
                                maxSleepTime = tmp;
                        }
-                       
-                       halfMaxSleepTime = Math.max(1, maxSleepTime/2);
+
+                       halfMaxSleepTime = Math.max(1, maxSleepTime / 2);
                }
 
                /**
@@ -812,18 +756,18 @@ public class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngine
                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 @@ public class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngine
                @Override
                public void run() {
                        logger.info("PersistentThreadModel running");
-                       
+
                        // set thread local variable
                        session.setPolicySession();
 
@@ -856,33 +800,34 @@ public class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngine
 
                        // 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,46 +835,104 @@ public class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngine
        /* ============================================================ */
 
        /**
-        * Factory for various items. Methods can be overridden for junit testing.
+        * DataSource-EntityManagerFactory pair.
         */
-       protected static class Factory {
+       private class DsEmf {
+               private BasicDataSource bds;
+               private EntityManagerFactory emf;
 
                /**
-                * Gets the configuration for the transaction manager.
+                * Makes an entity manager factory for the given data source.
                 * 
-                * @return the configuration for the transaction manager
+                * @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 Configuration getTransMgrConfig() {
-                       return TransactionManagerServices.getConfiguration();
+               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 transaction manager.
                 * 
                 * @return the transaction manager
                 */
-               public BitronixTransactionManager getTransMgr() {
-                       return TransactionManagerServices.getTransactionManager();
+               public TransactionManager getTransMgr() {
+                       return com.arjuna.ats.jta.TransactionManager.transactionManager();
                }
 
                /**
-                * Gets the KIE services.
+                * Gets the user transaction.
                 * 
-                * @return the KIE services
+                * @return the user transaction
                 */
-               public KieServices getKieServices() {
-                       return KieServices.Factory.get();
+               public UserTransaction getUserTrans() {
+                       return com.arjuna.ats.jta.UserTransaction.userTransaction();
                }
 
                /**
-                * Gets the current host name.
+                * Gets the transaction synchronization registry.
                 * 
-                * @return the current host name, associated with the IP address of the
-                *         local machine
-                * @throws UnknownHostException
+                * @return the transaction synchronization registry
                 */
-               public String getHostName() throws UnknownHostException {
-                       return InetAddress.getLocalHost().getHostName();
+               public TransactionSynchronizationRegistry getTransSyncReg() {
+                       return SingletonRegistry.transreg;
+               }
+
+               /**
+                * Gets the KIE services.
+                * 
+                * @return the KIE services
+                */
+               public KieServices getKieServices() {
+                       return KieServices.Factory.get();
                }
 
                /**
@@ -946,58 +949,41 @@ public class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngine
                }
 
                /**
-                * 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 {
-
-                       return DriverManager.getConnection(url, user, pass);
-               }
+               public BasicDataSource makeDataSource(Properties dsProps) {
+                       try {
+                               return BasicDataSourceFactory.createDataSource(dsProps);
 
-               /**
-                * 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 @@ public class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngine
                 *            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);
+               }
+       }
 }
index 7ddd2fd..6b8345c 100644 (file)
        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>
                        <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"/>
index c7fa848..7624d04 100644 (file)
@@ -36,28 +36,28 @@ public class DroolsSessionEntityTest {
                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 @@ public class DroolsSessionEntityTest {
                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 @@ public class DroolsSessionEntityTest {
                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 @@ public class DroolsSessionEntityTest {
        @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 @@ public class DroolsSessionEntityTest {
        @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 @@ public class DroolsSessionEntityTest {
        }
 
        /**
-        * 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 @@ public class DroolsSessionEntityTest {
        @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 (file)
index 7350a7f..0000000
+++ /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();
-       }
-
-}
index 0165b1e..9c9a30b 100644 (file)
@@ -25,37 +25,69 @@ import static org.mockito.Mockito.never;
 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 @@ public class EntityMgrTransTest {
                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 @@ public class EntityMgrTransTest {
 
        /**
         * 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 @@ public class EntityMgrTransTest {
                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 @@ public class EntityMgrTransTest {
 
        /**
         * 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 @@ public class EntityMgrTransTest {
        }
 
        /**
-        * 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 @@ public class EntityMgrTransTest {
         * 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 @@ public class EntityMgrTransTest {
        }
 
        /**
-        * 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 @@ public class EntityMgrTransTest {
                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 @@ public class EntityMgrTransTest {
                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());
+
+       }
 }
@@ -26,31 +26,44 @@ import java.util.Map;
 import javax.persistence.EntityManagerFactory;
 import javax.persistence.Persistence;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 /**
  * Generates the schema DDL files.
  */
-public class GenSchemaTest {
-       
+public class GenSchema {
+
+       private static final Logger logger = LoggerFactory.getLogger(PersistenceFeatureTest.class);
+
        private EntityManagerFactory emf;
-       
 
-       /*
-        * This is a JUnit which is provided as a utility for producing a basic
-        * ddl schema file in the sql directory.  
+       /**
+        * 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);
+               }
+       }
 }
index 792e6f8..dd601dd 100644 (file)
@@ -37,31 +37,35 @@ import javax.persistence.Persistence;
 
 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 @@ public class JpaDroolsSessionConnectorTest {
                /*
                 * 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 @@ public class JpaDroolsSessionConnectorTest {
        @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();
                }
        }
index e73031d..a7c33ab 100644 (file)
@@ -24,8 +24,9 @@ import static org.junit.Assert.assertEquals;
 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.never;
 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.SQLException;
 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.KieContainer;
 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 @@ public class PersistenceFeatureTest {
        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 @@ public class PersistenceFeatureTest {
                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 @@ public class PersistenceFeatureTest {
                // 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,22 +230,45 @@ public class PersistenceFeatureTest {
                // 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());
@@ -238,18 +276,20 @@ public class PersistenceFeatureTest {
 
        @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 @@ public class PersistenceFeatureTest {
 
                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 @@ public class PersistenceFeatureTest {
 
                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 @@ public class PersistenceFeatureTest {
 
        /**
         * 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 @@ public class PersistenceFeatureTest {
 
                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 @@ public class PersistenceFeatureTest {
 
                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 testConfigureKieEnv() throws Exception {
+       public void testLoadDataSource() 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).set(EnvironmentName.ENTITY_MANAGER_FACTORY, emf);
-               verify(kieenv).set(EnvironmentName.TRANSACTION_MANAGER, bittrans);
+               verify(fact).makeEntMgrFact(any());
        }
 
        @Test
-       public void testInitDataSource() throws Exception {
+       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(4)).set(any(), any());
+
+               verify(kieenv).set(EnvironmentName.ENTITY_MANAGER_FACTORY, emf);
+               verify(kieenv).set(EnvironmentName.TRANSACTION, usertrans);
+               verify(kieenv).set(EnvironmentName.TRANSACTION_MANAGER, transmgr);
+               verify(kieenv).set(EnvironmentName.TRANSACTION_SYNCHRONIZATION_REGISTRY, transreg);
                
-               assertEquals(JDBC_URL, dsprops.getProperty("URL"));
-               assertEquals(JDBC_USER, dsprops.getProperty("user"));
-               assertEquals(JDBC_PASSWD, dsprops.getProperty("password"));
+               verify(bds, times(1)).close();
+       }
+
+       @Test
+       public void testConfigureKieEnv_RtEx() throws Exception {
+               feat.globalInit(null, SRC_TEST_RESOURCES);
+
+               mockDbConn(5);
+               setUpKie("myname", 999L, false);
                
-               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 @@ public class PersistenceFeatureTest {
 
                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 @@ public class PersistenceFeatureTest {
 
                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,90 +494,99 @@ public class PersistenceFeatureTest {
 
                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 {
+       public void testLoadDataSource_DiffSession() 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);
-               
+               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, "myname", "mybase");
+               feat.activatePolicySession(polcont, "myname2", "mybase");
+
+               verify(fact, times(2)).makeEntMgrFact(any());
+       }
+       
+       @Test
+       public void testSelectThreadModel_Persistent() throws Exception {
+               setUpKie("myname", 999L, true);
+               
+               ThreadModel m = feat.selectThreadModel(polsess);
+               assertNotNull(m);
+               assertTrue(m instanceof PersistentThreadModel);
                
-               verify(fact, times(1)).makePoolingDataSource();
        }
-
+       
        @Test
-       public void testLoadDataSource_DiffSession() 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);
+       public void testSelectThreadModel_NotPersistent() throws Exception {
+               when(fact.getPolicyController(any())).thenReturn(polctlr);
+               assertNull(feat.selectThreadModel(polsess));
                
-               verify(polcont).setAdjunct(any(), adjcap.capture());
+       }
+       
+       @Test
+       public void testSelectThreadModel_Start__Run_Update_Stop() throws Exception {
+               setUpKie("myname", 999L, true);
                
-               when(polcont.getAdjunct(any())).thenReturn( adjcap.getValue());
-
-               setUpKie("myname2", 999L, false);
+               ThreadModel m = feat.selectThreadModel(polsess);
+               assertNotNull(m);
+               assertTrue(m instanceof PersistentThreadModel);
                
-               // invoke it again
-               feat.activatePolicySession(polcont, "myname2", "mybase");
+               when(polsess.getKieSession()).thenReturn(kiesess);
                
-               verify(fact, times(2)).makePoolingDataSource();
+               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 class PersistenceFeatureTest {
        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 class PersistenceFeatureTest {
        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 @@ public class PersistenceFeatureTest {
                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 @@ public class PersistenceFeatureTest {
                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");
-       }
+               feat.activatePolicySession(polcont, "myname", "mybase");
 
-       @Test(expected = RuntimeException.class)
-       public void testInitHostName_Ex() throws Exception {
-               when(fact.getHostName())
-                               .thenThrow(
-                                               new UnknownHostException("expected exception"));
-               
-               feat.globalInit(null, SRC_TEST_RESOURCES);
+               verify(s, never()).executeUpdate();
        }
 
        @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 @@ public class PersistenceFeatureTest {
                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 @@ public class PersistenceFeatureTest {
                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 @@ public class PersistenceFeatureTest {
                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 @@ public class PersistenceFeatureTest {
                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 class PersistenceFeatureTest {
        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 @@ public class PersistenceFeatureTest {
                feat.globalInit(null, SRC_TEST_RESOURCES);
 
                setUpKie("myname", 999L, true);
-               
+
                feat.activatePolicySession(polcont, "myname", "mybase");
-               
+
                verify(s).executeUpdate();
        }
 
@@ -914,51 +974,29 @@ public class PersistenceFeatureTest {
 
                mockDbConn(5);
                setUpKie("myname", 999L, true);
-               
-               
-               feat.activatePolicySession(polcont, "myname", "mybase");
 
+               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 @@ public class PersistenceFeatureTest {
                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 @@ public class PersistenceFeatureTest {
                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 @@ public class PersistenceFeatureTest {
                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 @@ public class PersistenceFeatureTest {
 
                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 @@ public class PersistenceFeatureTest {
 
                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 @@ public class PersistenceFeatureTest {
 
                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 @@ public class PersistenceFeatureTest {
 
                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 @@ public class PersistenceFeatureTest {
                setUpKie("myname", 999L, true);
 
                props.remove("persistence.type");
+
+               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);
                
-               assertNull( feat.activatePolicySession(polcont, "myname", "mybase"));
+               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 @@ public class PersistenceFeatureTest {
 
        /**
         * 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 @@ public class PersistenceFeatureTest {
 
        /**
         * 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 @@ public class PersistenceFeatureTest {
        /**
         * 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,58 +1361,57 @@ public class PersistenceFeatureTest {
                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 KieServices getKieServices() {
-                       return kiesvc;
+               public UserTransaction getUserTrans() {
+                       return usertrans;
                }
 
                @Override
-               public BitronixTransactionManager getTransMgr() {
-                       return null;
+               public TransactionSynchronizationRegistry getTransSyncReg() {
+                       return transreg;
                }
 
                @Override
-               public EntityManagerFactory makeEntMgrFact(String pu,
-                                                                                                       Properties propMap) {
-                       if(pu.equals("onapsessionsPU")) {
-                               return null;
-                       }
-                       
-                       return super.makeEntMgrFact("junitPersistenceFeaturePU", propMap);
+               public KieServices getKieServices() {
+                       return kiesvc;
                }
 
                @Override
-               public PolicyController getPolicyContainer(PolicyContainer container) {
+               public EntityManagerFactory makeEntMgrFact(Map<String, Object> props) {
+                       return emf;
+               }
+
+               @Override
+               public PolicyController getPolicyController(PolicyContainer container) {
                        return polctlr;
                }
-               
+
        }
 }
index 6794e24..5cc1bad 100644 (file)
        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"/>
index 6b448dc..a1e9cc4 100644 (file)
@@ -23,6 +23,5 @@ javax.persistence.jdbc.url=jdbc:h2:mem:TestPersistenceFeature
 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