diff options
author | Jim Hahn <jrh3@att.com> | 2018-02-14 12:52:31 -0500 |
---|---|---|
committer | Jim Hahn <jrh3@att.com> | 2018-02-14 16:14:17 -0500 |
commit | c83e35bab5aa44f01cb7a9089701ef963ee0c131 (patch) | |
tree | d76dfcdb85ecdde91202da22053876ab57f46204 /feature-session-persistence | |
parent | c5d5a9058d47eca9d4ac90308514ff8f1f9d0ca3 (diff) |
Replace bitronix and eclipselink in persistence
Replaced bitronix transaction manager, which is not intended for production,
with jboss transaction manager.
Eliminated eclipselink so that only hibernate is used for
persistence for both JPA and drools-persistence.
Added more test cases to EntityMgrTrans to provide coverage for
various exception types.
Moved object store to features/session-persistence/jta.
Wrapped RuntimeException in specific type.
Modified test to throw specific exception type.
Converted GenSchema from an @Test to a main().
Logged caught exceptions in junit tests.
Change-Id: I4b02efc8da43d20b2dbb3c0b25adc382e80474ec
Issue-ID: POLICY-191
Signed-off-by: Jim Hahn <jrh3@att.com>
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 |