diff options
Diffstat (limited to 'feature-session-persistence')
17 files changed, 1377 insertions, 1111 deletions
diff --git a/feature-session-persistence/pom.xml b/feature-session-persistence/pom.xml index a8b01f8a..70d37f23 100644 --- a/feature-session-persistence/pom.xml +++ b/feature-session-persistence/pom.xml @@ -107,6 +107,11 @@ <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>${powermock.version}</version> @@ -142,11 +147,17 @@ <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> @@ -164,14 +175,20 @@ <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> diff --git a/feature-session-persistence/src/main/feature/config/feature-session-persistence.properties b/feature-session-persistence/src/main/feature/config/feature-session-persistence.properties index 6204b5ed..0f15e3aa 100644 --- a/feature-session-persistence/src/main/feature/config/feature-session-persistence.properties +++ b/feature-session-persistence/src/main/feature/config/feature-session-persistence.properties @@ -22,7 +22,8 @@ javax.persistence.jdbc.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 diff --git a/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/DroolsPersistenceProperties.java b/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/DroolsPersistenceProperties.java index 1c935b0c..42a638a0 100644 --- a/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/DroolsPersistenceProperties.java +++ b/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/DroolsPersistenceProperties.java @@ -27,10 +27,9 @@ 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"; } diff --git a/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/DroolsSessionEntity.java b/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/DroolsSessionEntity.java index e9c5b33b..b3616c43 100644 --- a/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/DroolsSessionEntity.java +++ b/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/DroolsSessionEntity.java @@ -35,53 +35,53 @@ 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 index 58292117..00000000 --- a/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/EntityMgrCloser.java +++ /dev/null @@ -1,49 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * feature-session-persistence - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.policy.drools.persistence; - -import javax.persistence.EntityManager; - -/** - * Wrapper for an <i>EntityManager</i>, providing auto-close functionality. - */ -public class EntityMgrCloser implements AutoCloseable { - - /** - * The wrapper manager. - */ - private final EntityManager em; - - /** - * - * @param em - * manager to be auto-closed - */ - public EntityMgrCloser(EntityManager em) { - this.em = em; - } - - @Override - public void close() { - em.close(); - } - -} diff --git a/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/EntityMgrTrans.java b/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/EntityMgrTrans.java index 79b620d3..9bb26ac1 100644 --- a/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/EntityMgrTrans.java +++ b/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/EntityMgrTrans.java @@ -21,10 +21,18 @@ package org.onap.policy.drools.persistence; import javax.persistence.EntityManager; -import javax.persistence.EntityTransaction; +import javax.transaction.HeuristicMixedException; +import javax.transaction.HeuristicRollbackException; +import javax.transaction.NotSupportedException; +import javax.transaction.RollbackException; +import javax.transaction.Status; +import javax.transaction.SystemException; +import javax.transaction.UserTransaction; + +import org.onap.policy.common.utils.jpa.EntityMgrCloser; /** - * Wrapper for an <i>EntityManager</i> that creates a transaction that is + * Wrapper for an <i>EntityManager</i> that creates a JTA transaction that is * auto-rolled back when closed. */ public class EntityMgrTrans extends EntityMgrCloser { @@ -32,7 +40,7 @@ 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); + } + } } diff --git a/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/JpaDroolsSessionConnector.java b/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/JpaDroolsSessionConnector.java index 76c09681..cd76ae8d 100644 --- a/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/JpaDroolsSessionConnector.java +++ b/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/JpaDroolsSessionConnector.java @@ -26,14 +26,12 @@ import 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; } } diff --git a/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/PersistenceFeature.java b/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/PersistenceFeature.java index db33d05a..032383b4 100644 --- a/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/PersistenceFeature.java +++ b/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/PersistenceFeature.java @@ -21,10 +21,7 @@ package org.onap.policy.drools.persistence; import java.io.IOException; -import java.net.InetAddress; -import java.net.UnknownHostException; import java.sql.Connection; -import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.HashMap; @@ -35,8 +32,12 @@ import 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. */ @@ -88,11 +83,6 @@ public class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngine private KieServices kieSvcFact; /** - * Host name. - */ - private String hostName; - - /** * Persistence properties. */ private Properties persistProps; @@ -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(); } } @@ -516,6 +453,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 * removing abandoned records as well. @@ -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); @@ -565,40 +543,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. * * @param conn @@ -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); + } + } } diff --git a/feature-session-persistence/src/main/resources/META-INF/persistence.xml b/feature-session-persistence/src/main/resources/META-INF/persistence.xml index 7ddd2fd3..6b8345c3 100644 --- a/feature-session-persistence/src/main/resources/META-INF/persistence.xml +++ b/feature-session-persistence/src/main/resources/META-INF/persistence.xml @@ -23,20 +23,10 @@ xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"> - <persistence-unit name="onapPU" transaction-type="RESOURCE_LOCAL"> - <!-- This is for database access by non-drools methods --> - <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> - <class>org.onap.policy.drools.persistence.DroolsSessionEntity</class> - <class>org.drools.persistence.info.SessionInfo</class> - <class>org.drools.persistence.info.WorkItemInfo</class> - <properties> - <!-- Properties are passed in --> - </properties> - </persistence-unit> - <persistence-unit name="onapsessionsPU" transaction-type="JTA"> <!-- Used for drools session data access --> - <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider> + <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider> + <class>org.onap.policy.drools.persistence.DroolsSessionEntity</class> <class>org.drools.persistence.info.SessionInfo</class> <class>org.drools.persistence.info.WorkItemInfo</class> <properties> @@ -44,18 +34,19 @@ <property name="hibernate.max_fetch_depth" value="3" /> <property name="hibernate.hbm2ddl.auto" value="update" /> <property name="hibernate.show_sql" value="false" /> - <property name="hibernate.transaction.manager_lookup_class" - value="org.hibernate.transaction.BTMTransactionManagerLookup" /> + <property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.JTATransactionFactory" /> + <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup" /> </properties> </persistence-unit> <persistence-unit name="schemaDroolsPU" transaction-type="RESOURCE_LOCAL"> <!-- Limited use for generating the DB and schema files for drools DB - uses eclipselink for convenience --> - <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> + <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider> <class>org.onap.policy.drools.persistence.DroolsSessionEntity</class> <class>org.drools.persistence.info.SessionInfo</class> <class>org.drools.persistence.info.WorkItemInfo</class> <properties> + <property name="hibernate.dialect" value="org.hibernate.dialect.MariaDBDialect" /> <property name="javax.persistence.schema-generation.scripts.action" value="drop-and-create"/> <property name="javax.persistence.schema-generation.scripts.create-target" value="sql/generatedCreateDrools.ddl"/> <property name="javax.persistence.schema-generation.scripts.drop-target" value="sql/generatedDropDrools.ddl"/> diff --git a/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/DroolsSessionEntityTest.java b/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/DroolsSessionEntityTest.java index c7fa8486..7624d043 100644 --- a/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/DroolsSessionEntityTest.java +++ b/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/DroolsSessionEntityTest.java @@ -36,28 +36,28 @@ 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 index 7350a7f7..00000000 --- a/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/EntityMgrCloserTest.java +++ /dev/null @@ -1,100 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * feature-session-persistence - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.policy.drools.persistence; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; - -import javax.persistence.EntityManager; - -import org.junit.Before; -import org.junit.Test; -import org.onap.policy.drools.persistence.EntityMgrCloser; - -public class EntityMgrCloserTest { - - private EntityManager mgr; - - - @Before - public void setUp() throws Exception { - mgr = mock(EntityManager.class); - } - - - /** - * Verifies that the constructor does not do anything extra before - * being closed. - */ - @Test - public void testEntityMgrCloser() { - EntityMgrCloser c = new EntityMgrCloser(mgr); - - // verify not closed yet - verify(mgr, never()).close(); - - c.close(); - } - - /** - * Verifies that the manager gets closed when close() is invoked. - */ - @Test - public void testClose() { - EntityMgrCloser c = new EntityMgrCloser(mgr); - - c.close(); - - // should be closed - verify(mgr).close(); - } - - /** - * Ensures that the manager gets closed when "try" block exits normally. - */ - @Test - public void testClose_TryWithoutExcept() { - try(EntityMgrCloser c = new EntityMgrCloser(mgr)) { - - } - - verify(mgr).close(); - } - - /** - * Ensures that the manager gets closed when "try" block throws an - * exception. - */ - @Test - public void testClose_TryWithExcept() { - try { - try(EntityMgrCloser c = new EntityMgrCloser(mgr)) { - throw new Exception("expected exception"); - } - - } catch (Exception e) { - } - - verify(mgr).close(); - } - -} diff --git a/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/EntityMgrTransTest.java b/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/EntityMgrTransTest.java index 0165b1e4..9c9a30b3 100644 --- a/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/EntityMgrTransTest.java +++ b/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/EntityMgrTransTest.java @@ -25,37 +25,69 @@ import static org.mockito.Mockito.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()); + + } } diff --git a/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/GenSchemaTest.java b/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/GenSchema.java index d9e25b28..a0af2e6c 100644 --- a/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/GenSchemaTest.java +++ b/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/GenSchema.java @@ -26,31 +26,44 @@ import 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); + } + } } diff --git a/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/JpaDroolsSessionConnectorTest.java b/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/JpaDroolsSessionConnectorTest.java index 792e6f8b..dd601dd3 100644 --- a/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/JpaDroolsSessionConnectorTest.java +++ b/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/JpaDroolsSessionConnectorTest.java @@ -37,31 +37,35 @@ import 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(); } } diff --git a/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/PersistenceFeatureTest.java b/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/PersistenceFeatureTest.java index e73031dd..a7c33aba 100644 --- a/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/PersistenceFeatureTest.java +++ b/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/PersistenceFeatureTest.java @@ -24,8 +24,9 @@ import static org.junit.Assert.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,41 +230,66 @@ 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()); } @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; } - + } } diff --git a/feature-session-persistence/src/test/resources/META-INF/persistence.xml b/feature-session-persistence/src/test/resources/META-INF/persistence.xml index 6794e24e..5cc1badc 100644 --- a/feature-session-persistence/src/test/resources/META-INF/persistence.xml +++ b/feature-session-persistence/src/test/resources/META-INF/persistence.xml @@ -23,16 +23,8 @@ xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"> - <persistence-unit name="junitDroolsSessionEntityPU" transaction-type="RESOURCE_LOCAL"> - <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> - <class>org.onap.policy.drools.persistence.DroolsSessionEntity</class> - <properties> - <property name="javax.persistence.schema-generation.database.action" value="create"/> - </properties> - </persistence-unit> - - <persistence-unit name="junitPersistenceFeaturePU" transaction-type="RESOURCE_LOCAL"> - <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> + <persistence-unit name="junitDroolsSessionEntityPU" transaction-type="JTA"> + <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider> <class>org.onap.policy.drools.persistence.DroolsSessionEntity</class> <properties> <property name="javax.persistence.schema-generation.database.action" value="create"/> diff --git a/feature-session-persistence/src/test/resources/feature-session-persistence.properties b/feature-session-persistence/src/test/resources/feature-session-persistence.properties index 6b448dc8..a1e9cc43 100644 --- a/feature-session-persistence/src/test/resources/feature-session-persistence.properties +++ b/feature-session-persistence/src/test/resources/feature-session-persistence.properties @@ -23,6 +23,5 @@ javax.persistence.jdbc.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 |