Remove Factory from various drools-pdp classes 70/73570/2
authorJim Hahn <jrh3@att.com>
Thu, 29 Nov 2018 14:33:02 +0000 (09:33 -0500)
committerJim Hahn <jrh3@att.com>
Thu, 29 Nov 2018 14:35:21 +0000 (09:35 -0500)
Also merged changes from 'Rename test classes in drools-pdp'.

Change-Id: I4d0a3a1b0b5523eadf38d1edb5aa86c404b69d19
Issue-ID: POLICY-1288
Signed-off-by: Jim Hahn <jrh3@att.com>
14 files changed:
feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/DmaapManager.java
feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/PoolingFeature.java
feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/PoolingManagerImpl.java
feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/DmaapManagerTest.java
feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/EndToEndFeatureTest.java
feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/FeatureTest.java
feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/PoolingFeatureTest.java
feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/PoolingManagerImplTest.java
feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/PersistenceFeature.java
feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/PersistenceFeatureTest.java
policy-core/src/main/java/org/onap/policy/drools/core/lock/PolicyResourceLockManager.java
policy-core/src/test/java/org/onap/policy/drools/core/lock/PolicyResourceLockManagerTest.java
policy-management/src/main/java/org/onap/policy/drools/system/internal/AggregatedPolicyController.java
policy-management/src/test/java/org/onap/policy/drools/system/internal/AggregatedPolicyControllerTest.java

index 27b8150..eb258b8 100644 (file)
@@ -38,11 +38,6 @@ public class DmaapManager {
 
     private static final Logger logger = LoggerFactory.getLogger(DmaapManager.class);
 
-    /**
-     * Factory used to construct objects.
-     */
-    private static Factory factory = new Factory();
-
     /**
      * Name of the DMaaP topic.
      */
@@ -93,19 +88,6 @@ public class DmaapManager {
         }
     }
 
-    protected static Factory getFactory() {
-        return factory;
-    }
-
-    /**
-     * Used by junit tests to set the factory used to create various objects used by this class.
-     * 
-     * @param factory the new factory
-     */
-    protected static void setFactory(Factory factory) {
-        DmaapManager.factory = factory;
-    }
-
     public String getTopic() {
         return topic;
     }
@@ -117,7 +99,7 @@ public class DmaapManager {
      * @throws PoolingFeatureException if the source doesn't exist or is not filterable
      */
     private FilterableTopicSource findTopicSource() throws PoolingFeatureException {
-        for (TopicSource src : factory.getTopicSources()) {
+        for (TopicSource src : getTopicSources()) {
             if (topic.equals(src.getTopic())) {
                 if (src instanceof FilterableTopicSource) {
                     return (FilterableTopicSource) src;
@@ -138,7 +120,7 @@ public class DmaapManager {
      * @throws PoolingFeatureException if the sink doesn't exist
      */
     private TopicSink findTopicSink() throws PoolingFeatureException {
-        for (TopicSink sink : factory.getTopicSinks()) {
+        for (TopicSink sink : getTopicSinks()) {
             if (topic.equals(sink.getTopic())) {
                 return sink;
             }
@@ -252,29 +234,26 @@ public class DmaapManager {
             throw new PoolingFeatureException("cannot send to topic sink " + topic, e);
         }
     }
+    
+    /*
+     * The remaining methods may be overridden by junit tests.
+     */
 
     /**
-     * Factory used to construct objects.
+     * Get topic source.
+     * 
+     * @return the topic sources
      */
-    public static class Factory {
-
-        /**
-         * Get topic source.
-         * 
-         * @return the topic sources
-         */
-        public List<TopicSource> getTopicSources() {
-            return TopicEndpoint.manager.getTopicSources();
-        }
-
-        /**
-         * Get topic sinks.
-         * 
-         * @return the topic sinks
-         */
-        public List<TopicSink> getTopicSinks() {
-            return TopicEndpoint.manager.getTopicSinks();
-        }
+    protected List<TopicSource> getTopicSources() {
+        return TopicEndpoint.manager.getTopicSources();
+    }
 
+    /**
+     * Get topic sinks.
+     * 
+     * @return the topic sinks
+     */
+    protected List<TopicSink> getTopicSinks() {
+        return TopicEndpoint.manager.getTopicSinks();
     }
 }
index d45bded..60a6f29 100644 (file)
@@ -56,11 +56,6 @@ public class PoolingFeature implements PolicyEngineFeatureAPI, PolicyControllerF
 
     private static final Logger logger = LoggerFactory.getLogger(PoolingFeature.class);
 
-    /**
-     * Factory used to create objects.
-     */
-    private static Factory factory = new Factory();
-
     /**
      * ID of this host.
      */
@@ -97,19 +92,6 @@ public class PoolingFeature implements PolicyEngineFeatureAPI, PolicyControllerF
         this.host = UUID.randomUUID().toString();
     }
 
-    protected static Factory getFactory() {
-        return factory;
-    }
-
-    /**
-     * Sets the factory to be used to create objects. Used by junit tests.
-     * 
-     * @param factory the new factory to be used to create objects
-     */
-    protected static void setFactory(Factory factory) {
-        PoolingFeature.factory = factory;
-    }
-
     public String getHost() {
         return host;
     }
@@ -131,13 +113,13 @@ public class PoolingFeature implements PolicyEngineFeatureAPI, PolicyControllerF
     @Override
     public boolean beforeStart(PolicyEngine engine) {
         logger.info("initializing {}", PoolingProperties.FEATURE_NAME);
-        featProps = factory.getProperties(PoolingProperties.FEATURE_NAME);
+        featProps = getProperties(PoolingProperties.FEATURE_NAME);
 
         // remove any generic pooling topic - always use controller-specific property
         featProps.remove(PoolingProperties.POOLING_TOPIC);
 
-        factory.initTopicSources(featProps);
-        factory.initTopicSinks(featProps);
+        initTopicSources(featProps);
+        initTopicSinks(featProps);
 
         return false;
     }
@@ -173,7 +155,7 @@ public class PoolingFeature implements PolicyEngineFeatureAPI, PolicyControllerF
                 PoolingProperties props = new PoolingProperties(name, featProps);
 
                 logger.info("pooling enabled for {}", name);
-                ctlr2pool.computeIfAbsent(name, xxx -> factory.makeManager(host, controller, props, activeLatch));
+                ctlr2pool.computeIfAbsent(name, xxx -> makeManager(host, controller, props, activeLatch));
 
             } catch (PropertyException e) {
                 logger.error("pooling disabled due to exception for {}", name, e);
@@ -270,7 +252,7 @@ public class PoolingFeature implements PolicyEngineFeatureAPI, PolicyControllerF
 
         PolicyController controller;
         try {
-            controller = factory.getController(droolsController);
+            controller = getController(droolsController);
 
         } catch (IllegalArgumentException | IllegalStateException e) {
             logger.warn("cannot get controller for {} {}", droolsController.getGroupId(),
@@ -393,64 +375,62 @@ public class PoolingFeature implements PolicyEngineFeatureAPI, PolicyControllerF
             this.event = event;
         }
     }
+    
+    /*
+     * The remaining methods may be overridden by junit tests.
+     */
 
     /**
-     * Used to create objects.
+     * Get properties.
+     * 
+     * @param featName feature name
+     * @return the properties for the specified feature
      */
-    public static class Factory {
-
-        /**
-         * Get properties.
-         * 
-         * @param featName feature name
-         * @return the properties for the specified feature
-         */
-        public Properties getProperties(String featName) {
-            return SystemPersistence.manager.getProperties(featName);
-        }
+    protected Properties getProperties(String featName) {
+        return SystemPersistence.manager.getProperties(featName);
+    }
 
-        /**
-         * Makes a pooling manager for a controller.
-         
-         * @param host name/uuid of this host
-         * @param controller controller
-         * @param props properties to use to configure the manager
-         * @param activeLatch decremented when the manager goes Active
-         * @return a new pooling manager
-         */
-        public PoolingManagerImpl makeManager(String host, PolicyController controller, PoolingProperties props,
-                CountDownLatch activeLatch) {
-            return new PoolingManagerImpl(host, controller, props, activeLatch);
-        }
+    /**
+     * Makes a pooling manager for a controller.
+     * 
+     * @param host name/uuid of this host
+     * @param controller controller
+     * @param props properties to use to configure the manager
+     * @param activeLatch decremented when the manager goes Active
+     * @return a new pooling manager
+     */
+    protected PoolingManagerImpl makeManager(String host, PolicyController controller, PoolingProperties props,
+            CountDownLatch activeLatch) {
+        return new PoolingManagerImpl(host, controller, props, activeLatch);
+    }
 
-        /**
-         * Gets the policy controller associated with a drools controller.
-         
-         * @param droolsController drools controller
-         * @return the policy controller associated with a drools controller
-         */
-        public PolicyController getController(DroolsController droolsController) {
-            return PolicyController.factory.get(droolsController);
-        }
+    /**
+     * Gets the policy controller associated with a drools controller.
+     * 
+     * @param droolsController drools controller
+     * @return the policy controller associated with a drools controller
+     */
+    protected PolicyController getController(DroolsController droolsController) {
+        return PolicyController.factory.get(droolsController);
+    }
 
-        /**
-         * Initializes the topic sources.
-         
-         * @param props properties used to configure the topics
-         * @return the topic sources
-         */
-        public List<TopicSource> initTopicSources(Properties props) {
-            return TopicEndpoint.manager.addTopicSources(props);
-        }
+    /**
+     * Initializes the topic sources.
+     * 
+     * @param props properties used to configure the topics
+     * @return the topic sources
+     */
+    protected List<TopicSource> initTopicSources(Properties props) {
+        return TopicEndpoint.manager.addTopicSources(props);
+    }
 
-        /**
-         * Initializes the topic sinks.
-         * 
-         * @param props properties used to configure the topics
-         * @return the topic sinks
-         */
-        public List<TopicSink> initTopicSinks(Properties props) {
-            return TopicEndpoint.manager.addTopicSinks(props);
-        }
+    /**
+     * Initializes the topic sinks.
+     * 
+     * @param props properties used to configure the topics
+     * @return the topic sinks
+     */
+    protected List<TopicSink> initTopicSinks(Properties props) {
+        return TopicEndpoint.manager.addTopicSinks(props);
     }
 }
index 6b5828c..4db8fe3 100644 (file)
@@ -68,11 +68,6 @@ public class PoolingManagerImpl implements PoolingManager, TopicListener {
      */
     public static final int MAX_HOPS = 5;
 
-    /**
-     * Factory used to create various objects. Can be overridden during junit testing.
-     */
-    private static Factory factory = new Factory();
-
     /**
      * ID of this host.
      */
@@ -170,8 +165,8 @@ public class PoolingManagerImpl implements PoolingManager, TopicListener {
             this.listener = (TopicListener) controller;
             this.serializer = new Serializer();
             this.topic = props.getPoolingTopic();
-            this.extractors = factory.makeClassExtractors(makeExtractorProps(controller, props.getSource()));
-            this.dmaapMgr = factory.makeDmaapManager(props.getPoolingTopic());
+            this.extractors = makeClassExtractors(makeExtractorProps(controller, props.getSource()));
+            this.dmaapMgr = makeDmaapManager(props.getPoolingTopic());
             this.current = new IdleState(this);
 
             logger.info("allocating host {} to controller {} for topic {}", host, controller.getName(), topic);
@@ -186,14 +181,6 @@ public class PoolingManagerImpl implements PoolingManager, TopicListener {
         }
     }
 
-    protected static Factory getFactory() {
-        return factory;
-    }
-
-    protected static void setFactory(Factory factory) {
-        PoolingManagerImpl.factory = factory;
-    }
-
     /**
      * Should only be used by junit tests.
      * 
@@ -241,7 +228,7 @@ public class PoolingManagerImpl implements PoolingManager, TopicListener {
                 dmaapMgr.startPublisher();
 
                 logger.debug("make scheduler thread for topic {}", getTopic());
-                scheduler = factory.makeScheduler();
+                scheduler = makeScheduler();
 
                 /*
                  * Only a handful of timers at any moment, thus we can afford to take the
@@ -603,7 +590,7 @@ public class PoolingManagerImpl implements PoolingManager, TopicListener {
 
         // check if this topic has a decoder
 
-        if (!factory.canDecodeEvent(drools, topic2)) {
+        if (!canDecodeEvent(drools, topic2)) {
 
             logger.warn("{}: DECODING-UNSUPPORTED {}:{}:{}", drools, topic2, drools.getGroupId(),
                             drools.getArtifactId());
@@ -613,7 +600,7 @@ public class PoolingManagerImpl implements PoolingManager, TopicListener {
         // decode
 
         try {
-            return factory.decodeEvent(drools, topic2, event);
+            return decodeEventWrapper(drools, topic2, event);
 
         } catch (UnsupportedOperationException | IllegalStateException | IllegalArgumentException e) {
             logger.debug("{}: DECODE FAILED: {} <- {} because of {}", drools, topic2, event, e.getMessage(), e);
@@ -777,67 +764,65 @@ public class PoolingManagerImpl implements PoolingManager, TopicListener {
             }
         }
     }
+    
+    /*
+     * The remaining methods may be overridden by junit tests.
+     */
 
     /**
-     * Factory used to create objects.
+     * Creates object extractors.
+     * 
+     * @param props properties used to configure the extractors
+     * @return a new set of extractors
      */
-    public static class Factory {
-
-        /**
-         * Creates object extractors.
-         * 
-         * @param props properties used to configure the extractors
-         * @return a new set of extractors
-         */
-        public ClassExtractors makeClassExtractors(Properties props) {
-            return new ClassExtractors(props, PoolingProperties.PROP_EXTRACTOR_PREFIX,
-                            PoolingProperties.EXTRACTOR_TYPE);
-        }
+    protected ClassExtractors makeClassExtractors(Properties props) {
+        return new ClassExtractors(props, PoolingProperties.PROP_EXTRACTOR_PREFIX,
+                        PoolingProperties.EXTRACTOR_TYPE);
+    }
 
-        /**
-         * Creates a DMaaP manager.
-         
-         * @param topic name of the internal DMaaP topic
-         * @return a new DMaaP manager
-         * @throws PoolingFeatureException if an error occurs
-         */
-        public DmaapManager makeDmaapManager(String topic) throws PoolingFeatureException {
-            return new DmaapManager(topic);
-        }
+    /**
+     * Creates a DMaaP manager.
+     * 
+     * @param topic name of the internal DMaaP topic
+     * @return a new DMaaP manager
+     * @throws PoolingFeatureException if an error occurs
+     */
+    protected DmaapManager makeDmaapManager(String topic) throws PoolingFeatureException {
+        return new DmaapManager(topic);
+    }
 
-        /**
-         * Creates a scheduled thread pool.
-         
-         * @return a new scheduled thread pool
-         */
-        public ScheduledThreadPoolExecutor makeScheduler() {
-            return new ScheduledThreadPoolExecutor(1);
-        }
+    /**
+     * Creates a scheduled thread pool.
+     * 
+     * @return a new scheduled thread pool
+     */
+    protected ScheduledThreadPoolExecutor makeScheduler() {
+        return new ScheduledThreadPoolExecutor(1);
+    }
 
-        /**
-         * Determines if the event can be decoded.
-         
-         * @param drools drools controller
-         * @param topic topic on which the event was received
-         * @return {@code true} if the event can be decoded, {@code false} otherwise
-         */
-        public boolean canDecodeEvent(DroolsController drools, String topic) {
-            return EventProtocolCoder.manager.isDecodingSupported(drools.getGroupId(), drools.getArtifactId(), topic);
-        }
+    /**
+     * Determines if the event can be decoded.
+     * 
+     * @param drools drools controller
+     * @param topic topic on which the event was received
+     * @return {@code true} if the event can be decoded, {@code false} otherwise
+     */
+    protected boolean canDecodeEvent(DroolsController drools, String topic) {
+        return EventProtocolCoder.manager.isDecodingSupported(drools.getGroupId(), drools.getArtifactId(), topic);
+    }
 
-        /**
-         * Decodes the event.
-         * 
-         * @param drools drools controller
-         * @param topic topic on which the event was received
-         * @param event event text to be decoded
-         * @return the decoded event
-         * @throws IllegalArgumentException illegal argument
-         * @throw UnsupportedOperationException unsupported operation
-         * @throws IllegalStateException illegal state
-         */
-        public Object decodeEvent(DroolsController drools, String topic, String event) {
-            return EventProtocolCoder.manager.decode(drools.getGroupId(), drools.getArtifactId(), topic, event);
-        }
+    /**
+     * Decodes the event.
+     * 
+     * @param drools drools controller
+     * @param topic topic on which the event was received
+     * @param event event text to be decoded
+     * @return the decoded event
+     * @throws IllegalArgumentException illegal argument
+     * @throw UnsupportedOperationException unsupported operation
+     * @throws IllegalStateException illegal state
+     */
+    protected Object decodeEventWrapper(DroolsController drools, String topic, String event) {
+        return EventProtocolCoder.manager.decode(drools.getGroupId(), drools.getArtifactId(), topic, event);
     }
 }
index e554a34..a6404f4 100644 (file)
@@ -32,45 +32,30 @@ import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import java.util.Arrays;
-import java.util.LinkedList;
+import java.util.Collections;
+import java.util.List;
 import java.util.concurrent.CountDownLatch;
-import org.junit.AfterClass;
 import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.Test;
 import org.onap.policy.common.endpoints.event.comm.FilterableTopicSource;
 import org.onap.policy.common.endpoints.event.comm.TopicListener;
 import org.onap.policy.common.endpoints.event.comm.TopicSink;
 import org.onap.policy.common.endpoints.event.comm.TopicSource;
-import org.onap.policy.drools.pooling.DmaapManager.Factory;
 
 public class DmaapManagerTest {
 
-    private static String MY_TOPIC = "my.topic";
-    private static String MSG = "a message";
-    private static String FILTER = "a filter";
-
-    /**
-     * Original factory, to be restored when all tests complete.
-     */
-    private static Factory saveFactory;
-
-    private Factory factory;
+    private static final String EXPECTED = "expected";
+    private static final String MY_TOPIC = "my.topic";
+    private static final String MSG = "a message";
+    private static final String FILTER = "a filter";
+    
     private TopicListener listener;
     private FilterableTopicSource source;
+    private boolean gotSources;
     private TopicSink sink;
+    private boolean gotSinks;
     private DmaapManager mgr;
 
-    @BeforeClass
-    public static void setUpBeforeClass() throws Exception {
-        saveFactory = DmaapManager.getFactory();
-    }
-
-    @AfterClass
-    public static void tearDownAfterClass() throws Exception {
-        DmaapManager.setFactory(saveFactory);
-    }
-
     /**
      * Setup.
      * 
@@ -79,33 +64,24 @@ public class DmaapManagerTest {
     @Before
     public void setUp() throws Exception {
         listener = mock(TopicListener.class);
-        factory = mock(Factory.class);
         source = mock(FilterableTopicSource.class);
+        gotSources = false;
         sink = mock(TopicSink.class);
-
-        DmaapManager.setFactory(factory);
+        gotSinks = false;
 
         when(source.getTopic()).thenReturn(MY_TOPIC);
 
         when(sink.getTopic()).thenReturn(MY_TOPIC);
         when(sink.send(any())).thenReturn(true);
 
-        // three sources, with the desired one in the middle
-        when(factory.getTopicSources())
-                        .thenReturn(Arrays.asList(mock(TopicSource.class), source, mock(TopicSource.class)));
-
-        // three sinks, with the desired one in the middle
-        when(factory.getTopicSinks())
-                        .thenReturn(Arrays.asList(mock(TopicSink.class), sink, mock(TopicSink.class)));
-
-        mgr = new DmaapManager(MY_TOPIC);
+        mgr = new DmaapManagerImpl(MY_TOPIC);
     }
 
     @Test
     public void testDmaapManager() {
         // verify that the init methods were called
-        verify(factory).getTopicSinks();
-        verify(factory).getTopicSinks();
+        assertTrue(gotSources);
+        assertTrue(gotSinks);
     }
 
     @Test(expected = PoolingFeatureException.class)
@@ -113,23 +89,26 @@ public class DmaapManagerTest {
         // force error by having no topics match
         when(source.getTopic()).thenReturn("");
 
-        new DmaapManager(MY_TOPIC);
+        new DmaapManagerImpl(MY_TOPIC);
     }
 
     @Test(expected = PoolingFeatureException.class)
     public void testDmaapManager_IllegalArgEx() throws PoolingFeatureException {
         // force error
-        when(factory.getTopicSources()).thenThrow(new IllegalArgumentException("expected"));
-
-        new DmaapManager(MY_TOPIC);
+        new DmaapManagerImpl(MY_TOPIC) {
+            @Override
+            protected List<TopicSource> getTopicSources() {
+                throw new IllegalArgumentException(EXPECTED);
+            }
+        };
     }
 
     @Test(expected = PoolingFeatureException.class)
     public void testDmaapManager_CannotFilter() throws PoolingFeatureException {
         // force an error when setFilter() is called
-        doThrow(new UnsupportedOperationException("expected")).when(source).setFilter(any());
+        doThrow(new UnsupportedOperationException(EXPECTED)).when(source).setFilter(any());
 
-        new DmaapManager(MY_TOPIC);
+        new DmaapManagerImpl(MY_TOPIC);
     }
 
     @Test
@@ -149,25 +128,34 @@ public class DmaapManagerTest {
         TopicSource source2 = mock(TopicSource.class);
         when(source2.getTopic()).thenReturn(MY_TOPIC);
 
-        when(factory.getTopicSources()).thenReturn(Arrays.asList(source2));
-
-        new DmaapManager(MY_TOPIC);
+        new DmaapManagerImpl(MY_TOPIC) {
+            @Override
+            protected List<TopicSource> getTopicSources() {
+                return Arrays.asList(source2);
+            }
+        };
     }
 
     @Test(expected = PoolingFeatureException.class)
     public void testFindTopicSource_NotFound() throws PoolingFeatureException {
         // one item in list, and its topic doesn't match
-        when(factory.getTopicSources()).thenReturn(Arrays.asList(mock(TopicSource.class)));
-
-        new DmaapManager(MY_TOPIC);
+        new DmaapManagerImpl(MY_TOPIC) {
+            @Override
+            protected List<TopicSource> getTopicSources() {
+                return Arrays.asList(mock(TopicSource.class));
+            }
+        };
     }
 
     @Test(expected = PoolingFeatureException.class)
     public void testFindTopicSource_EmptyList() throws PoolingFeatureException {
         // empty list
-        when(factory.getTopicSources()).thenReturn(new LinkedList<>());
-
-        new DmaapManager(MY_TOPIC);
+        new DmaapManagerImpl(MY_TOPIC) {
+            @Override
+            protected List<TopicSource> getTopicSources() {
+                return Collections.emptyList();
+            }
+        };
     }
 
     @Test
@@ -178,17 +166,23 @@ public class DmaapManagerTest {
     @Test(expected = PoolingFeatureException.class)
     public void testFindTopicSink_NotFound() throws PoolingFeatureException {
         // one item in list, and its topic doesn't match
-        when(factory.getTopicSinks()).thenReturn(Arrays.asList(mock(TopicSink.class)));
-
-        new DmaapManager(MY_TOPIC);
+        new DmaapManagerImpl(MY_TOPIC) {
+            @Override
+            protected List<TopicSink> getTopicSinks() {
+                return Arrays.asList(mock(TopicSink.class));
+            }
+        };
     }
 
     @Test(expected = PoolingFeatureException.class)
     public void testFindTopicSink_EmptyList() throws PoolingFeatureException {
         // empty list
-        when(factory.getTopicSinks()).thenReturn(new LinkedList<>());
-
-        new DmaapManager(MY_TOPIC);
+        new DmaapManagerImpl(MY_TOPIC) {
+            @Override
+            protected List<TopicSink> getTopicSinks() {
+                return Collections.emptyList();
+            }
+        };
     }
 
     @Test
@@ -297,7 +291,7 @@ public class DmaapManagerTest {
     @Test(expected = PoolingFeatureException.class)
     public void testSetFilter_Exception() throws PoolingFeatureException {
         // force an error when setFilter() is called
-        doThrow(new UnsupportedOperationException("expected")).when(source).setFilter(any());
+        doThrow(new UnsupportedOperationException(EXPECTED)).when(source).setFilter(any());
 
         mgr.setFilter(FILTER);
     }
@@ -339,7 +333,7 @@ public class DmaapManagerTest {
         mgr.startPublisher();
 
         // arrange for send() to throw an exception
-        doThrow(new IllegalStateException("expected")).when(sink).send(MSG);
+        doThrow(new IllegalStateException(EXPECTED)).when(sink).send(MSG);
 
         mgr.publish(MSG);
     }
@@ -353,6 +347,32 @@ public class DmaapManagerTest {
             // OK
         }
     }
+    
+    /**
+     * Manager with overrides.
+     */
+    private class DmaapManagerImpl extends DmaapManager {
+
+        public DmaapManagerImpl(String topic) throws PoolingFeatureException {
+            super(topic);
+        }
+
+        @Override
+        protected List<TopicSource> getTopicSources() {
+            gotSources = true;
+            
+            // three sources, with the desired one in the middle
+            return Arrays.asList(mock(TopicSource.class), source, mock(TopicSource.class));
+        }
+
+        @Override
+        protected List<TopicSink> getTopicSinks() {
+            gotSinks = true;
+            
+            // three sinks, with the desired one in the middle
+            return Arrays.asList(mock(TopicSink.class), sink, mock(TopicSink.class));
+        }
+    }
 
     @FunctionalInterface
     public static interface VFunction {
index 616d95f..362c3b0 100644 (file)
@@ -7,9 +7,9 @@
  * 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.
@@ -30,7 +30,6 @@ import static org.onap.policy.drools.pooling.PoolingProperties.PREFIX;
 
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.ObjectMapper;
-
 import java.io.IOException;
 import java.util.Arrays;
 import java.util.Deque;
@@ -43,7 +42,6 @@ import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
-
 import org.junit.After;
 import org.junit.AfterClass;
 import org.junit.Before;
@@ -69,7 +67,7 @@ import org.slf4j.LoggerFactory;
  * feature object. Uses real feature objects, as well as real DMaaP sources and sinks. However, the
  * following are not: <dl> <dt>PolicyEngine, PolicyController, DroolsController</dt> <dd>mocked</dd>
  * </dl>
- * 
+ *
  * <p>The following fields must be set before executing this: <ul> <li>UEB_SERVERS</li>
  * <li>INTERNAL_TOPIC</li> <li>EXTERNAL_TOPIC</li> </ul>
  */
@@ -115,10 +113,26 @@ public class EndToEndFeatureTest {
     private static final long STD_OFFLINE_PUB_WAIT_MS = 2;
     private static final long EVENT_WAIT_SEC = 15;
 
-    // these are saved and restored on exit from this test class
-    private static PoolingFeature.Factory saveFeatureFactory;
-    private static PoolingManagerImpl.Factory saveManagerFactory;
-    private static DmaapManager.Factory saveDmaapFactory;
+    /**
+     * Used to decode events into a Map.
+     */
+    private static final TypeReference<TreeMap<String, String>> typeRef =
+                    new TypeReference<TreeMap<String, String>>() {};
+
+    /**
+     * Used to decode events from the external topic.
+     */
+    private static final ThreadLocal<ObjectMapper> mapper = new ThreadLocal<ObjectMapper>() {
+        @Override
+        protected ObjectMapper initialValue() {
+            return new ObjectMapper();
+        }
+    };
+
+    /**
+     * Used to identify the current host.
+     */
+    private static final ThreadLocal<Host> currentHost = new ThreadLocal<Host>();
 
     /**
      * Sink for external DMaaP topic.
@@ -137,14 +151,10 @@ public class EndToEndFeatureTest {
 
     /**
      * Setup before class.
-     * 
+     *
      */
     @BeforeClass
     public static void setUpBeforeClass() {
-        saveFeatureFactory = PoolingFeature.getFactory();
-        saveManagerFactory = PoolingManagerImpl.getFactory();
-        saveDmaapFactory = DmaapManager.getFactory();
-
         externalSink = TopicEndpoint.manager.addTopicSinks(makeSinkProperties(EXTERNAL_TOPIC)).get(0);
         externalSink.start();
 
@@ -154,14 +164,10 @@ public class EndToEndFeatureTest {
 
     /**
      * Tear down after class.
-     * 
+     *
      */
     @AfterClass
     public static void tearDownAfterClass() {
-        PoolingFeature.setFactory(saveFeatureFactory);
-        PoolingManagerImpl.setFactory(saveManagerFactory);
-        DmaapManager.setFactory(saveDmaapFactory);
-
         externalSink.stop();
         internalSink.stop();
     }
@@ -267,14 +273,27 @@ public class EndToEndFeatureTest {
         return props;
     }
 
+    /**
+     * Decodes an event.
+     *
+     * @param event event
+     * @return the decoded event, or {@code null} if it cannot be decoded
+     */
+    private static Object decodeEvent(String event) {
+        try {
+            return mapper.get().readValue(event, typeRef);
+
+        } catch (IOException e) {
+            logger.warn("cannot decode external event", e);
+            return null;
+        }
+    }
+
     /**
      * Context used for a single test case.
      */
     private static class Context {
 
-        private final FeatureFactory featureFactory;
-        private final ManagerFactory managerFactory;
-
         /**
          * Hosts that have been added to this context.
          */
@@ -297,16 +316,11 @@ public class EndToEndFeatureTest {
 
         /**
          * Constructor.
-         * 
+         *
          * @param nEvents number of events to be processed
          */
         public Context(int events) {
-            featureFactory = new FeatureFactory(this);
-            managerFactory = new ManagerFactory(this);
             eventCounter = new CountDownLatch(events);
-
-            PoolingFeature.setFactory(featureFactory);
-            PoolingManagerImpl.setFactory(managerFactory);
         }
 
         /**
@@ -319,7 +333,7 @@ public class EndToEndFeatureTest {
 
         /**
          * Creates and adds a new host to the context.
-         * 
+         *
          * @return the new Host
          */
         public Host addHost() {
@@ -356,26 +370,16 @@ public class EndToEndFeatureTest {
 
         /**
          * Offers an event to the external topic.
-         * 
+         *
          * @param event event
          */
         public void offerExternal(String event) {
             externalSink.send(event);
         }
 
-        /**
-         * Decodes an event.
-         * 
-         * @param event event
-         * @return the decoded event, or {@code null} if it cannot be decoded
-         */
-        public Object decodeEvent(String event) {
-            return managerFactory.decodeEvent(null, null, event);
-        }
-
         /**
          * Associates a controller with its drools controller.
-         * 
+         *
          * @param controller controller
          * @param droolsController drools controller
          */
@@ -385,7 +389,7 @@ public class EndToEndFeatureTest {
 
         /**
          * Get controller.
-         * 
+         *
          * @param droolsController drools controller
          * @return the controller associated with a drools controller, or {@code null} if it has no
          *         associated controller
@@ -396,7 +400,7 @@ public class EndToEndFeatureTest {
 
         /**
          * Get decode errors.
-         * 
+         *
          * @return the number of decode errors so far
          */
         public int getDecodeErrors() {
@@ -412,7 +416,7 @@ public class EndToEndFeatureTest {
 
         /**
          * Get remaining events.
-         * 
+         *
          * @return the number of events that haven't been processed
          */
         public long getRemainingEvents() {
@@ -428,7 +432,7 @@ public class EndToEndFeatureTest {
 
         /**
          * Waits, for a period of time, for all events to be processed.
-         * 
+         *
          * @param time time
          * @param units units
          * @return {@code true} if all events have been processed, {@code false} otherwise
@@ -440,7 +444,7 @@ public class EndToEndFeatureTest {
 
         /**
          * Waits, for a period of time, for all hosts to enter the Active state.
-         * 
+         *
          * @param timeMs maximum time to wait, in milliseconds
          * @throws InterruptedException throws interrupted exception
          */
@@ -459,7 +463,7 @@ public class EndToEndFeatureTest {
      */
     private static class Host {
 
-        private final PoolingFeature feature = new PoolingFeature();
+        private final PoolingFeature feature;
 
         /**
          * {@code True} if this host has processed a message, {@code false} otherwise.
@@ -476,7 +480,7 @@ public class EndToEndFeatureTest {
 
         /**
          * Constructor.
-         * 
+         *
          * @param context context
          */
         public Host(Context context) {
@@ -496,11 +500,13 @@ public class EndToEndFeatureTest {
             doAnswer(new MyExternalTopicListener(context, this)).when(controller).onTopicEvent(any(), any(), any());
 
             context.addController(controller, drools);
+
+            feature = new PoolingFeatureImpl(context, this);
         }
 
         /**
          * Waits, for a period of time, for the host to enter the Active state.
-         * 
+         *
          * @param timeMs time to wait, in milliseconds
          * @return {@code true} if the host entered the Active state within the given amount of
          *         time, {@code false} otherwise
@@ -515,18 +521,6 @@ public class EndToEndFeatureTest {
          * topic and its own internal "DMaaP" topic.
          */
         public void start() {
-            DmaapManager.setFactory(new DmaapManager.Factory() {
-                @Override
-                public List<TopicSource> getTopicSources() {
-                    return Arrays.asList(internalSource, externalSource);
-                }
-
-                @Override
-                public List<TopicSink> getTopicSinks() {
-                    return Arrays.asList(internalSink, externalSink);
-                }
-            });
-
             feature.beforeStart(engine);
             feature.afterCreate(controller);
 
@@ -549,7 +543,7 @@ public class EndToEndFeatureTest {
 
         /**
          * Offers an event to the feature, before the policy controller handles it.
-         * 
+         *
          * @param protocol protocol
          * @param topic2 topic
          * @param event event
@@ -561,7 +555,7 @@ public class EndToEndFeatureTest {
 
         /**
          * Offers an event to the feature, after the policy controller handles it.
-         * 
+         *
          * @param protocol protocol
          * @param topic topic
          * @param event event
@@ -575,7 +569,7 @@ public class EndToEndFeatureTest {
 
         /**
          * Offers an event to the feature, before the drools controller handles it.
-         * 
+         *
          * @param fact fact
          * @return {@code true} if the event was handled, {@code false} otherwise
          */
@@ -585,7 +579,7 @@ public class EndToEndFeatureTest {
 
         /**
          * Offers an event to the feature, after the drools controller handles it.
-         * 
+         *
          * @param fact fact
          * @param successInsert {@code true} if it was successfully inserted by the drools
          *        controller, {@code false} otherwise
@@ -604,7 +598,7 @@ public class EndToEndFeatureTest {
 
         /**
          * Message seen.
-         * 
+         *
          * @return {@code true} if a message was seen for this host, {@code false} otherwise
          */
         public boolean messageSeen() {
@@ -638,7 +632,7 @@ public class EndToEndFeatureTest {
             }
 
             boolean result;
-            Object fact = context.decodeEvent(event);
+            Object fact = decodeEvent(event);
 
             if (fact == null) {
                 result = false;
@@ -662,19 +656,21 @@ public class EndToEndFeatureTest {
     }
 
     /**
-     * Simulator for the feature-level factory.
+     * Feature with overrides.
      */
-    private static class FeatureFactory extends PoolingFeature.Factory {
+    private static class PoolingFeatureImpl extends PoolingFeature {
 
         private final Context context;
+        private final Host host;
 
         /**
          * Constructor.
-         * 
+         *
          * @param context context
          */
-        public FeatureFactory(Context context) {
+        public PoolingFeatureImpl(Context context, Host host) {
             this.context = context;
+            this.host = host;
 
             /*
              * Note: do NOT extract anything from "context" at this point, because it hasn't been
@@ -716,7 +712,7 @@ public class EndToEndFeatureTest {
 
         /**
          * Embeds a specializer within a property name, after the prefix.
-         * 
+         *
          * @param propnm property name into which it should be embedded
          * @param spec specializer to be embedded
          * @return the property name, with the specializer embedded within it
@@ -725,55 +721,80 @@ public class EndToEndFeatureTest {
             String suffix = propnm.substring(PREFIX.length());
             return PREFIX + spec + "." + suffix;
         }
+
+        @Override
+        protected PoolingManagerImpl makeManager(String hostName, PolicyController controller, PoolingProperties props,
+                        CountDownLatch activeLatch) {
+
+            /*
+             * Set this before creating the test, because the test's superclass
+             * constructor uses it before the test object has a chance to store it.
+             */
+            currentHost.set(host);
+
+            return new PoolingManagerTest(hostName, controller, props, activeLatch);
+        }
     }
 
     /**
-     * Simulator for the pooling manager factory.
+     * Pooling Manager with overrides.
      */
-    private static class ManagerFactory extends PoolingManagerImpl.Factory {
+    private static class PoolingManagerTest extends PoolingManagerImpl {
 
         /**
-         * Used to decode events from the external topic.
+         * Constructor.
+         *
+         * @param hostName the host
+         * @param controller the controller
+         * @param props the properties
+         * @param activeLatch the latch
          */
-        private final ThreadLocal<ObjectMapper> mapper = new ThreadLocal<ObjectMapper>() {
-            @Override
-            protected ObjectMapper initialValue() {
-                return new ObjectMapper();
-            }
-        };
+        public PoolingManagerTest(String hostName, PolicyController controller,
+                        PoolingProperties props, CountDownLatch activeLatch) {
 
-        /**
-         * Used to decode events into a Map.
-         */
-        private final TypeReference<TreeMap<String, String>> typeRef = new TypeReference<TreeMap<String, String>>() {};
+            super(hostName, controller, props, activeLatch);
+        }
+
+        @Override
+        protected DmaapManager makeDmaapManager(String topic) throws PoolingFeatureException {
+            return new DmaapManagerImpl(topic);
+        }
+
+        @Override
+        protected boolean canDecodeEvent(DroolsController drools, String topic) {
+            return true;
+        }
+
+        @Override
+        protected Object decodeEventWrapper(DroolsController drools, String topic, String event) {
+            return decodeEvent(event);
+        }
+    }
+
+    /**
+     * DMaaP Manager with overrides.
+     */
+    private static class DmaapManagerImpl extends DmaapManager {
 
         /**
          * Constructor.
-         * 
-         * @param context context
+         *
+         * @param topic the topic
+         * @throws PoolingFeatureException if an error occurs
          */
-        public ManagerFactory(Context context) {
-
-            /*
-             * Note: do NOT extract anything from "context" at this point, because it hasn't been
-             * fully initialized yet
-             */
+        public DmaapManagerImpl(String topic) throws PoolingFeatureException {
+            super(topic);
         }
 
         @Override
-        public boolean canDecodeEvent(DroolsController drools, String topic) {
-            return true;
+        protected List<TopicSource> getTopicSources() {
+            Host host = currentHost.get();
+            return Arrays.asList(host.internalSource, host.externalSource);
         }
 
         @Override
-        public Object decodeEvent(DroolsController drools, String topic, String event) {
-            try {
-                return mapper.get().readValue(event, typeRef);
-
-            } catch (IOException e) {
-                logger.warn("cannot decode external event", e);
-                return null;
-            }
+        protected List<TopicSink> getTopicSinks() {
+            return Arrays.asList(internalSink, externalSink);
         }
     }
 
index 709f1b0..01253fb 100644 (file)
@@ -48,9 +48,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
 import org.junit.After;
-import org.junit.AfterClass;
 import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.Test;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
@@ -79,6 +77,8 @@ import org.slf4j.LoggerFactory;
  * <dt>PolicyEngine, PolicyController, DroolsController</dt>
  * <dd>mocked</dd>
  * </dl>
+ * 
+ * <p>Invoke {@link #runSlow()}, before the test, to slow things down.
  */
 public class FeatureTest {
 
@@ -109,38 +109,31 @@ public class FeatureTest {
     private static long stdInterPollMs = 2;
     private static long stdEventWaitSec = 10;
 
-    // these are saved and restored on exit from this test class
-    private static PoolingFeature.Factory saveFeatureFactory;
-    private static PoolingManagerImpl.Factory saveManagerFactory;
-    private static DmaapManager.Factory saveDmaapFactory;
+    /**
+     * Used to decode events into a Map.
+     */
+    private static final TypeReference<TreeMap<String, String>> typeRef =
+                    new TypeReference<TreeMap<String, String>>() {};
 
     /**
-     * Context for the current test case.
+     * Used to decode events from the external topic.
      */
-    private Context ctx;
+    private static final ThreadLocal<ObjectMapper> mapper = new ThreadLocal<ObjectMapper>() {
+        @Override
+        protected ObjectMapper initialValue() {
+            return new ObjectMapper();
+        }
+    };
 
     /**
-     * Setup before class.
-     * 
+     * Used to identify the current context.
      */
-    @BeforeClass
-    public static void setUpBeforeClass() {
-        saveFeatureFactory = PoolingFeature.getFactory();
-        saveManagerFactory = PoolingManagerImpl.getFactory();
-        saveDmaapFactory = DmaapManager.getFactory();
-        
-        // note: invoke runSlow() to slow things down
-    }
+    private static final ThreadLocal<Context> currentContext = new ThreadLocal<Context>();
 
     /**
-     * Tear down after class.
+     * Context for the current test case.
      */
-    @AfterClass
-    public static void tearDownAfterClass() {
-        PoolingFeature.setFactory(saveFeatureFactory);
-        PoolingManagerImpl.setFactory(saveManagerFactory);
-        DmaapManager.setFactory(saveDmaapFactory);
-    }
+    private Context ctx;
 
     /**
      * Setup.
@@ -214,15 +207,27 @@ public class FeatureTest {
         stdEventWaitSec = 1000;
     }
 
+    /**
+     * Decodes an event.
+     * 
+     * @param event event
+     * @return the decoded event, or {@code null} if it cannot be decoded
+     */
+    private static Object decodeEvent(String event) {
+        try {
+            return mapper.get().readValue(event, typeRef);
+
+        } catch (IOException e) {
+            logger.warn("cannot decode external event", e);
+            return null;
+        }
+    }
+
     /**
      * Context used for a single test case.
      */
     private static class Context {
 
-        private final FeatureFactory featureFactory;
-        private final ManagerFactory managerFactory;
-        private final DmaapFactory dmaapFactory;
-
         /**
          * Hosts that have been added to this context.
          */
@@ -265,14 +270,7 @@ public class FeatureTest {
          * @param nEvents number of events to be processed
          */
         public Context(int events) {
-            featureFactory = new FeatureFactory(this);
-            managerFactory = new ManagerFactory(this);
-            dmaapFactory = new DmaapFactory(this);
             eventCounter = new CountDownLatch(events);
-
-            PoolingFeature.setFactory(featureFactory);
-            PoolingManagerImpl.setFactory(managerFactory);
-            DmaapManager.setFactory(dmaapFactory);
         }
 
         /**
@@ -374,16 +372,6 @@ public class FeatureTest {
             }
         }
 
-        /**
-         * Decodes an event.
-         * 
-         * @param event event
-         * @return the decoded event, or {@code null} if it cannot be decoded
-         */
-        public Object decodeEvent(String event) {
-            return managerFactory.decodeEvent(null, null, event);
-        }
-
         /**
          * Associates a controller with its drools controller.
          * 
@@ -476,7 +464,7 @@ public class FeatureTest {
 
         private final Context context;
 
-        private final PoolingFeature feature = new PoolingFeature();
+        private final PoolingFeature feature;
 
         /**
          * {@code True} if this host has processed a message, {@code false} otherwise.
@@ -521,6 +509,8 @@ public class FeatureTest {
 
             // arrange to read from the external topic
             externalSource = new TopicSourceImpl(context, false);
+            
+            feature = new PoolingFeatureImpl(context);
         }
 
         /**
@@ -665,7 +655,7 @@ public class FeatureTest {
             }
 
             boolean result;
-            Object fact = context.decodeEvent(event);
+            Object fact = decodeEvent(event);
 
             if (fact == null) {
                 result = false;
@@ -977,9 +967,9 @@ public class FeatureTest {
     }
 
     /**
-     * Simulator for the feature-level factory.
+     * Feature with overrides.
      */
-    private static class FeatureFactory extends PoolingFeature.Factory {
+    private static class PoolingFeatureImpl extends PoolingFeature {
 
         private final Context context;
 
@@ -988,7 +978,7 @@ public class FeatureTest {
          * 
          * @param context context
          */
-        public FeatureFactory(Context context) {
+        public PoolingFeatureImpl(Context context) {
             this.context = context;
 
             /*
@@ -1037,87 +1027,76 @@ public class FeatureTest {
             String suffix = propnm.substring(PREFIX.length());
             return PREFIX + spec + "." + suffix;
         }
+
+        @Override
+        protected PoolingManagerImpl makeManager(String host, PolicyController controller, PoolingProperties props,
+                        CountDownLatch activeLatch) {
+
+            currentContext.set(context);
+            
+            return new PoolingManagerTest(host, controller, props, activeLatch);
+        }
     }
 
     /**
-     * Simulator for the pooling manager factory.
+     * Pooling Manager with overrides.
      */
-    private static class ManagerFactory extends PoolingManagerImpl.Factory {
-
-        /**
-         * Used to decode events from the external topic.
-         */
-        private final ThreadLocal<ObjectMapper> mapper = new ThreadLocal<ObjectMapper>() {
-            @Override
-            protected ObjectMapper initialValue() {
-                return new ObjectMapper();
-            }
-        };
-
-        /**
-         * Used to decode events into a Map.
-         */
-        private final TypeReference<TreeMap<String, String>> typeRef = new TypeReference<TreeMap<String, String>>() {};
+    private static class PoolingManagerTest extends PoolingManagerImpl {
 
         /**
          * Constructor.
          * 
-         * @param context context
+         * @param host the host
+         * @param controller the controller
+         * @param props the properties
+         * @param activeLatch the latch
          */
-        public ManagerFactory(Context context) {
+        public PoolingManagerTest(String host, PolicyController controller, PoolingProperties props,
+                        CountDownLatch activeLatch) {
 
-            /*
-             * Note: do NOT extract anything from "context" at this point, because it
-             * hasn't been fully initialized yet
-             */
+            super(host, controller, props, activeLatch);
         }
 
         @Override
-        public boolean canDecodeEvent(DroolsController drools, String topic) {
-            return true;
+        protected DmaapManager makeDmaapManager(String topic) throws PoolingFeatureException {
+            return new DmaapManagerImpl(topic);
         }
 
         @Override
-        public Object decodeEvent(DroolsController drools, String topic, String event) {
-            try {
-                return mapper.get().readValue(event, typeRef);
+        protected boolean canDecodeEvent(DroolsController drools, String topic) {
+            return true;
+        }
 
-            } catch (IOException e) {
-                logger.warn("cannot decode external event", e);
-                return null;
-            }
+        @Override
+        protected Object decodeEventWrapper(DroolsController drools, String topic, String event) {
+            return decodeEvent(event);
         }
     }
 
     /**
-     * Simulator for the dmaap manager factory.
+     * DMaaP Manager with overrides.
      */
-    private static class DmaapFactory extends DmaapManager.Factory {
-
-        private final Context context;
+    private static class DmaapManagerImpl extends DmaapManager {
 
         /**
          * Constructor.
          * 
-         * @param context context
+         * @param context this manager's context
+         * @param topic the topic
+         * @throws PoolingFeatureException if an error occurs
          */
-        public DmaapFactory(Context context) {
-            this.context = context;
-
-            /*
-             * Note: do NOT extract anything from "context" at this point, because it
-             * hasn't been fully initialized yet
-             */
+        public DmaapManagerImpl(String topic) throws PoolingFeatureException {
+            super(topic);
         }
 
         @Override
-        public List<TopicSource> getTopicSources() {
-            return Arrays.asList(new TopicSourceImpl(context, true));
+        protected List<TopicSource> getTopicSources() {
+            return Arrays.asList(new TopicSourceImpl(currentContext.get(), true));
         }
 
         @Override
-        public List<TopicSink> getTopicSinks() {
-            return Arrays.asList(new TopicSinkImpl(context));
+        protected List<TopicSink> getTopicSinks() {
+            return Arrays.asList(new TopicSinkImpl(currentContext.get()));
         }
     }
 
index a943575..ed9d1c9 100644 (file)
@@ -32,16 +32,17 @@ import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Properties;
-import org.junit.AfterClass;
+import java.util.concurrent.CountDownLatch;
 import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.Test;
 import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
+import org.onap.policy.common.endpoints.event.comm.TopicSink;
+import org.onap.policy.common.endpoints.event.comm.TopicSource;
 import org.onap.policy.drools.controller.DroolsController;
-import org.onap.policy.drools.pooling.PoolingFeature.Factory;
 import org.onap.policy.drools.system.PolicyController;
 import org.onap.policy.drools.system.PolicyEngine;
 import org.onap.policy.drools.utils.Pair;
@@ -63,11 +64,6 @@ public class PoolingFeatureTest {
     private static final Object OBJECT1 = new Object();
     private static final Object OBJECT2 = new Object();
 
-    /**
-     * Saved from PoolingFeature and restored on exit from this test class.
-     */
-    private static Factory saveFactory;
-
     private Properties props;
     private PolicyEngine engine;
     private PolicyController controller1;
@@ -81,21 +77,9 @@ public class PoolingFeatureTest {
     private List<Pair<PoolingManagerImpl, PoolingProperties>> managers;
     private PoolingManagerImpl mgr1;
     private PoolingManagerImpl mgr2;
-    private Factory factory;
 
     private PoolingFeature pool;
 
-
-    @BeforeClass
-    public static void setUpBeforeClass() {
-        saveFactory = PoolingFeature.getFactory();
-    }
-
-    @AfterClass
-    public static void tearDownAfterClass() {
-        PoolingFeature.setFactory(saveFactory);
-    }
-
     /**
      * Setup.
      * 
@@ -105,7 +89,6 @@ public class PoolingFeatureTest {
     public void setUp() throws Exception {
         props = initProperties();
         engine = mock(PolicyEngine.class);
-        factory = mock(Factory.class);
         controller1 = mock(PolicyController.class);
         controller2 = mock(PolicyController.class);
         controllerDisabled = mock(PolicyController.class);
@@ -116,30 +99,13 @@ public class PoolingFeatureTest {
         droolsDisabled = mock(DroolsController.class);
         managers = new LinkedList<>();
 
-        PoolingFeature.setFactory(factory);
-
         when(controller1.getName()).thenReturn(CONTROLLER1);
         when(controller2.getName()).thenReturn(CONTROLLER2);
         when(controllerDisabled.getName()).thenReturn(CONTROLLER_DISABLED);
         when(controllerException.getName()).thenReturn(CONTROLLER_EX);
         when(controllerUnknown.getName()).thenReturn(CONTROLLER_UNKNOWN);
 
-        when(factory.getProperties(PoolingProperties.FEATURE_NAME)).thenReturn(props);
-        when(factory.getController(drools1)).thenReturn(controller1);
-        when(factory.getController(drools2)).thenReturn(controller2);
-        when(factory.getController(droolsDisabled)).thenReturn(controllerDisabled);
-
-        when(factory.makeManager(any(), any(), any(), any())).thenAnswer(args -> {
-            PoolingProperties props = args.getArgument(2);
-
-            PoolingManagerImpl mgr = mock(PoolingManagerImpl.class);
-
-            managers.add(new Pair<>(mgr, props));
-
-            return mgr;
-        });
-
-        pool = new PoolingFeature();
+        pool = new PoolingFeatureImpl();
 
         pool.beforeStart(engine);
 
@@ -161,7 +127,7 @@ public class PoolingFeatureTest {
         assertNotNull(host);
 
         // create another and ensure it generates another host name
-        pool = new PoolingFeature();
+        pool = new PoolingFeatureImpl();
         String host2 = pool.getHost();
         assertNotNull(host2);
 
@@ -175,7 +141,7 @@ public class PoolingFeatureTest {
 
     @Test
     public void testBeforeStartEngine() {
-        pool = new PoolingFeature();
+        pool = new PoolingFeatureImpl();
 
         assertFalse(pool.beforeStart(engine));
     }
@@ -183,7 +149,7 @@ public class PoolingFeatureTest {
     @Test
     public void testAfterCreate() {
         managers.clear();
-        pool = new PoolingFeature();
+        pool = new PoolingFeatureImpl();
         pool.beforeStart(engine);
 
         assertFalse(pool.afterCreate(controller1));
@@ -201,7 +167,7 @@ public class PoolingFeatureTest {
     @Test
     public void testAfterCreate_NotEnabled() {
         managers.clear();
-        pool = new PoolingFeature();
+        pool = new PoolingFeatureImpl();
         pool.beforeStart(engine);
 
         assertFalse(pool.afterCreate(controllerDisabled));
@@ -211,7 +177,7 @@ public class PoolingFeatureTest {
     @Test(expected = PoolingFeatureRtException.class)
     public void testAfterCreate_PropertyEx() {
         managers.clear();
-        pool = new PoolingFeature();
+        pool = new PoolingFeatureImpl();
         pool.beforeStart(engine);
 
         pool.afterCreate(controllerException);
@@ -219,7 +185,7 @@ public class PoolingFeatureTest {
 
     @Test(expected = PoolingFeatureRtException.class)
     public void testAfterCreate_NoProps() {
-        pool = new PoolingFeature();
+        pool = new PoolingFeatureImpl();
 
         // did not perform globalInit, which is an error
 
@@ -229,7 +195,7 @@ public class PoolingFeatureTest {
     @Test
     public void testAfterCreate_NoFeatProps() {
         managers.clear();
-        pool = new PoolingFeature();
+        pool = new PoolingFeatureImpl();
         pool.beforeStart(engine);
 
         assertFalse(pool.afterCreate(controllerUnknown));
@@ -398,9 +364,13 @@ public class PoolingFeatureTest {
 
     @Test
     public void testBeforeInsert_ArgEx() {
-
         // generate exception
-        doThrow(new IllegalArgumentException()).when(factory).getController(any());
+        pool = new PoolingFeatureImpl() {
+            @Override
+            protected PolicyController getController(DroolsController droolsController) {
+                throw new IllegalArgumentException();
+            }
+        };
 
         pool.beforeOffer(controller1, CommInfrastructure.UEB, TOPIC1, EVENT1);
         assertFalse(pool.beforeInsert(drools1, OBJECT1));
@@ -409,9 +379,13 @@ public class PoolingFeatureTest {
 
     @Test
     public void testBeforeInsert_StateEx() {
-
         // generate exception
-        doThrow(new IllegalStateException()).when(factory).getController(any());
+        pool = new PoolingFeatureImpl() {
+            @Override
+            protected PolicyController getController(DroolsController droolsController) {
+                throw new IllegalStateException();
+            }
+        };
 
         pool.beforeOffer(controller1, CommInfrastructure.UEB, TOPIC1, EVENT1);
         assertFalse(pool.beforeInsert(drools1, OBJECT1));
@@ -422,7 +396,12 @@ public class PoolingFeatureTest {
     public void testBeforeInsert_NullController() {
 
         // return null controller
-        when(factory.getController(any())).thenReturn(null);
+        pool = new PoolingFeatureImpl() {
+            @Override
+            protected PolicyController getController(DroolsController droolsController) {
+                return null;
+            }
+        };
 
         pool.beforeOffer(controller1, CommInfrastructure.UEB, TOPIC1, EVENT1);
         assertFalse(pool.beforeInsert(drools1, OBJECT1));
@@ -514,4 +493,53 @@ public class PoolingFeatureTest {
                         String.valueOf(40 + offset));
         props.setProperty("pooling.controller" + suffix + ".inter.heartbeat.milliseconds", String.valueOf(50 + offset));
     }
+
+    /**
+     * Feature with overrides.
+     */
+    private class PoolingFeatureImpl extends PoolingFeature {
+
+        @Override
+        protected Properties getProperties(String featName) {
+            if (PoolingProperties.FEATURE_NAME.equals(featName)) {
+                return props;
+            } else {
+                throw new IllegalArgumentException("unknown feature name");
+            }
+        }
+
+        @Override
+        protected PoolingManagerImpl makeManager(String host, PolicyController controller, PoolingProperties props,
+                        CountDownLatch activeLatch) {
+
+            PoolingManagerImpl mgr = mock(PoolingManagerImpl.class);
+
+            managers.add(new Pair<>(mgr, props));
+
+            return mgr;
+        }
+
+        @Override
+        protected PolicyController getController(DroolsController droolsController) {
+            if (droolsController == drools1) {
+                return controller1;
+            } else if (droolsController == drools2) {
+                return controller2;
+            } else if (droolsController == droolsDisabled) {
+                return controllerDisabled;
+            } else {
+                throw new IllegalArgumentException("unknown drools controller");
+            }
+        }
+
+        @Override
+        protected List<TopicSource> initTopicSources(Properties props) {
+            return Collections.emptyList();
+        }
+
+        @Override
+        protected List<TopicSink> initTopicSinks(Properties props) {
+            return Collections.emptyList();
+        }
+    }
 }
index e6b6e4c..7fce99d 100644 (file)
@@ -42,15 +42,12 @@ import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.ScheduledThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
-import org.junit.AfterClass;
 import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
 import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
 import org.onap.policy.common.endpoints.event.comm.TopicListener;
 import org.onap.policy.drools.controller.DroolsController;
-import org.onap.policy.drools.pooling.PoolingManagerImpl.Factory;
 import org.onap.policy.drools.pooling.extractor.ClassExtractors;
 import org.onap.policy.drools.pooling.message.BucketAssignments;
 import org.onap.policy.drools.pooling.message.Forward;
@@ -93,11 +90,6 @@ public class PoolingManagerImplTest {
      */
     private static final int START_PUB = 1;
 
-    /**
-     * Saved from PoolingManagerImpl and restored on exit from this test class.
-     */
-    private static Factory saveFactory;
-
     /**
      * Futures that have been allocated due to calls to scheduleXxx().
      */
@@ -108,24 +100,15 @@ public class PoolingManagerImplTest {
     private ListeningController controller;
     private ClassExtractors extractors;
     private DmaapManager dmaap;
+    private boolean gotDmaap;
     private ScheduledThreadPoolExecutor sched;
+    private int schedCount;
     private DroolsController drools;
     private Serializer ser;
-    private Factory factory;
     private CountDownLatch active;
 
     private PoolingManagerImpl mgr;
 
-    @BeforeClass
-    public static void setUpBeforeClass() {
-        saveFactory = PoolingManagerImpl.getFactory();
-    }
-
-    @AfterClass
-    public static void tearDownAfterClass() {
-        PoolingManagerImpl.setFactory(saveFactory);
-    }
-
     /**
      * Setup.
      * 
@@ -149,19 +132,14 @@ public class PoolingManagerImplTest {
         ser = new Serializer();
         active = new CountDownLatch(1);
 
-        factory = mock(Factory.class);
         extractors = mock(ClassExtractors.class);
         dmaap = mock(DmaapManager.class);
+        gotDmaap = false;
         controller = mock(ListeningController.class);
         sched = mock(ScheduledThreadPoolExecutor.class);
+        schedCount = 0;
         drools = mock(DroolsController.class);
 
-        when(factory.makeClassExtractors(any())).thenReturn(extractors);
-        when(factory.makeDmaapManager(any())).thenReturn(dmaap);
-        when(factory.makeScheduler()).thenReturn(sched);
-        when(factory.canDecodeEvent(drools, TOPIC2)).thenReturn(true);
-        when(factory.decodeEvent(drools, TOPIC2, THE_EVENT)).thenReturn(DECODED_EVENT);
-
         when(extractors.extract(DECODED_EVENT)).thenReturn(REQUEST_ID);
 
         when(controller.getName()).thenReturn(MY_CONTROLLER);
@@ -183,14 +161,12 @@ public class PoolingManagerImplTest {
                             return fut;
                         });
 
-        PoolingManagerImpl.setFactory(factory);
-
-        mgr = new PoolingManagerImpl(MY_HOST, controller, poolProps, active);
+        mgr = new PoolingManagerTest(MY_HOST, controller, poolProps, active);
     }
 
     @Test
     public void testPoolingManagerImpl() throws Exception {
-        verify(factory).makeDmaapManager(any());
+        assertTrue(gotDmaap);
 
         State st = mgr.getCurrent();
         assertTrue(st instanceof IdleState);
@@ -208,7 +184,7 @@ public class PoolingManagerImplTest {
         PolicyController ctlr = mock(PolicyController.class);
 
         PoolingFeatureRtException ex = expectException(PoolingFeatureRtException.class,
-            () -> new PoolingManagerImpl(MY_HOST, ctlr, poolProps, active));
+            () -> new PoolingManagerTest(MY_HOST, ctlr, poolProps, active));
         assertNotNull(ex.getCause());
         assertTrue(ex.getCause() instanceof ClassCastException);
     }
@@ -217,10 +193,15 @@ public class PoolingManagerImplTest {
     public void testPoolingManagerImpl_PoolEx() throws PoolingFeatureException {
         // throw an exception when we try to create the dmaap manager
         PoolingFeatureException ex = new PoolingFeatureException();
-        when(factory.makeDmaapManager(any())).thenThrow(ex);
-
+        
         PoolingFeatureRtException ex2 = expectException(PoolingFeatureRtException.class,
-            () -> new PoolingManagerImpl(MY_HOST, controller, poolProps, active));
+            () -> new PoolingManagerTest(MY_HOST, controller, poolProps, active) {
+                @Override
+                protected DmaapManager makeDmaapManager(String topic) throws PoolingFeatureException {
+                    throw ex;
+                }
+            });
+        
         assertEquals(ex, ex2.getCause());
     }
 
@@ -237,7 +218,7 @@ public class PoolingManagerImplTest {
     public void testGetHost() {
         assertEquals(MY_HOST, mgr.getHost());
 
-        mgr = new PoolingManagerImpl(HOST2, controller, poolProps, active);
+        mgr = new PoolingManagerTest(HOST2, controller, poolProps, active);
         assertEquals(HOST2, mgr.getHost());
     }
 
@@ -258,7 +239,7 @@ public class PoolingManagerImplTest {
 
         verify(dmaap).startPublisher();
 
-        verify(factory).makeScheduler();
+        assertEquals(1, schedCount);
         verify(sched).setMaximumPoolSize(1);
         verify(sched).setContinueExistingPeriodicTasksAfterShutdownPolicy(false);
 
@@ -268,7 +249,7 @@ public class PoolingManagerImplTest {
 
         verify(dmaap).startPublisher();
 
-        verify(factory).makeScheduler();
+        assertEquals(1, schedCount);
         verify(sched).setMaximumPoolSize(1);
         verify(sched).setContinueExistingPeriodicTasksAfterShutdownPolicy(false);
     }
@@ -798,6 +779,14 @@ public class PoolingManagerImplTest {
 
     @Test
     public void testDecodeEvent_CannotDecode() throws Exception {
+
+        mgr = new PoolingManagerTest(MY_HOST, controller, poolProps, active) {
+            @Override
+            protected boolean canDecodeEvent(DroolsController drools2, String topic2) {
+                return false;
+            }
+        };
+        
         startMgr();
 
         when(controller.isLocked()).thenReturn(true);
@@ -805,13 +794,20 @@ public class PoolingManagerImplTest {
         // create assignments, though they are irrelevant
         mgr.startDistributing(makeAssignments(false));
 
-        when(factory.canDecodeEvent(drools, TOPIC2)).thenReturn(false);
-
         assertFalse(mgr.beforeOffer(CommInfrastructure.UEB, TOPIC2, THE_EVENT));
     }
 
     @Test
     public void testDecodeEvent_UnsuppEx() throws Exception {
+
+        // generate exception
+        mgr = new PoolingManagerTest(MY_HOST, controller, poolProps, active) {
+            @Override
+            protected Object decodeEventWrapper(DroolsController drools2, String topic2, String event) {
+                throw new UnsupportedOperationException();
+            }
+        };
+        
         startMgr();
 
         when(controller.isLocked()).thenReturn(true);
@@ -819,14 +815,19 @@ public class PoolingManagerImplTest {
         // create assignments, though they are irrelevant
         mgr.startDistributing(makeAssignments(false));
 
-        // generate exception
-        doThrow(new UnsupportedOperationException()).when(factory).decodeEvent(drools, TOPIC2, THE_EVENT);
-
         assertFalse(mgr.beforeOffer(CommInfrastructure.UEB, TOPIC2, THE_EVENT));
     }
 
     @Test
     public void testDecodeEvent_ArgEx() throws Exception {
+        // generate exception
+        mgr = new PoolingManagerTest(MY_HOST, controller, poolProps, active) {
+            @Override
+            protected Object decodeEventWrapper(DroolsController drools2, String topic2, String event) {
+                throw new IllegalArgumentException();
+            }
+        };
+        
         startMgr();
 
         when(controller.isLocked()).thenReturn(true);
@@ -834,14 +835,19 @@ public class PoolingManagerImplTest {
         // create assignments, though they are irrelevant
         mgr.startDistributing(makeAssignments(false));
 
-        // generate exception
-        doThrow(new IllegalArgumentException()).when(factory).decodeEvent(drools, TOPIC2, THE_EVENT);
-
         assertFalse(mgr.beforeOffer(CommInfrastructure.UEB, TOPIC2, THE_EVENT));
     }
 
     @Test
     public void testDecodeEvent_StateEx() throws Exception {
+        // generate exception
+        mgr = new PoolingManagerTest(MY_HOST, controller, poolProps, active) {
+            @Override
+            protected Object decodeEventWrapper(DroolsController drools2, String topic2, String event) {
+                throw new IllegalStateException();
+            }
+        };
+        
         startMgr();
 
         when(controller.isLocked()).thenReturn(true);
@@ -849,9 +855,6 @@ public class PoolingManagerImplTest {
         // create assignments, though they are irrelevant
         mgr.startDistributing(makeAssignments(false));
 
-        // generate exception
-        doThrow(new IllegalStateException()).when(factory).decodeEvent(drools, TOPIC2, THE_EVENT);
-
         assertFalse(mgr.beforeOffer(CommInfrastructure.UEB, TOPIC2, THE_EVENT));
     }
 
@@ -1264,4 +1267,47 @@ public class PoolingManagerImplTest {
         public void apply() throws T;
 
     }
+
+    /**
+     * Manager with overrides.
+     */
+    private class PoolingManagerTest extends PoolingManagerImpl {
+
+        public PoolingManagerTest(String host, PolicyController controller, PoolingProperties props,
+                        CountDownLatch activeLatch) {
+
+            super(host, controller, props, activeLatch);
+        }
+
+        @Override
+        protected ClassExtractors makeClassExtractors(Properties props) {
+            return extractors;
+        }
+
+        @Override
+        protected DmaapManager makeDmaapManager(String topic) throws PoolingFeatureException {
+            gotDmaap = true;
+            return dmaap;
+        }
+
+        @Override
+        protected ScheduledThreadPoolExecutor makeScheduler() {
+            ++schedCount;
+            return sched;
+        }
+
+        @Override
+        protected boolean canDecodeEvent(DroolsController drools2, String topic2) {
+            return (drools2 == drools && TOPIC2.equals(topic2));
+        }
+
+        @Override
+        protected Object decodeEventWrapper(DroolsController drools2, String topic2, String event) {
+            if (drools2 == drools && TOPIC2.equals(topic2) && event == THE_EVENT) {
+                return DECODED_EVENT;
+            } else {
+                return null;
+            }
+        }
+    }
 }
index 13264d6..ce038d2 100644 (file)
@@ -65,13 +65,7 @@ import org.slf4j.LoggerFactory;
 public class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngineFeatureAPI {
 
     private static final Logger logger = LoggerFactory.getLogger(PersistenceFeature.class);
-
-    /** Standard factory used to get various items. */
-    private static Factory stdFactory = new Factory();
-
-    /** Factory used to get various items. */
-    private Factory fact = stdFactory;
-
+    
     /** KieService factory. */
     private KieServices kieSvcFact;
 
@@ -88,15 +82,6 @@ public class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngine
     /** Object used to serialize cleanup of sessioninfo table. */
     private Object cleanupLock = new Object();
 
-    /**
-     * Sets the factory to be used during junit testing.
-     *
-     * @param fact factory to be used
-     */
-    protected void setFactory(Factory fact) {
-        this.fact = fact;
-    }
-
     /**
      * Lookup the adjunct for this feature that is associated with the specified PolicyContainer. If
      * not found, create one.
@@ -132,10 +117,10 @@ public class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngine
     @Override
     public void globalInit(String[] args, String configDir) {
 
-        kieSvcFact = fact.getKieServices();
+        kieSvcFact = getKieServices();
 
         try {
-            persistProps = fact.loadProperties(configDir + "/feature-session-persistence.properties");
+            persistProps = loadProperties(configDir + "/feature-session-persistence.properties");
 
         } catch (IOException e1) {
             logger.error("initializePersistence: ", e1);
@@ -305,12 +290,12 @@ public class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngine
 
             configureSysProps();
 
-            BasicDataSource ds = fact.makeDataSource(getDataSourceProperties());
+            BasicDataSource ds = makeDataSource(getDataSourceProperties());
             DsEmf dsemf = new DsEmf(ds);
 
             try {
                 EntityManagerFactory emf = dsemf.emf;
-                DroolsSessionConnector conn = fact.makeJpaConnector(emf);
+                DroolsSessionConnector conn = makeJpaConnector(emf);
 
                 long desiredSessionId = getSessionId(conn, name);
 
@@ -450,9 +435,9 @@ public class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngine
          */
         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());
+            env.set(EnvironmentName.TRANSACTION, getUserTrans());
+            env.set(EnvironmentName.TRANSACTION_SYNCHRONIZATION_REGISTRY, getTransSyncReg());
+            env.set(EnvironmentName.TRANSACTION_MANAGER, getTransMgr());
         }
 
         /**
@@ -526,7 +511,7 @@ public class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngine
             }
 
             // now do the record deletion
-            try (BasicDataSource ds = fact.makeDataSource(getDataSourceProperties());
+            try (BasicDataSource ds = makeDataSource(getDataSourceProperties());
                     Connection connection = ds.getConnection();
                     PreparedStatement statement =
                             connection.prepareStatement(
@@ -577,7 +562,7 @@ public class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngine
      */
     private Properties getProperties(PolicyContainer container) {
         try {
-            return fact.getPolicyController(container).getProperties();
+            return getPolicyController(container).getProperties();
         } catch (IllegalArgumentException e) {
             logger.error("getProperties exception: ", e);
             return null;
@@ -808,7 +793,7 @@ public class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngine
                 props.put(org.hibernate.cfg.Environment.JPA_JTA_DATASOURCE, bds);
 
                 this.bds = bds;
-                this.emf = fact.makeEntMgrFact(props);
+                this.emf = makeEntMgrFact(props);
 
             } catch (RuntimeException e) {
                 closeDataSource();
@@ -851,99 +836,97 @@ public class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngine
     }
 
     /** Factory for various items. Methods can be overridden for junit testing. */
-    protected static class Factory {
 
-        /**
-         * Gets the transaction manager.
-         *
-         * @return the transaction manager
-         */
-        public TransactionManager getTransMgr() {
-            return com.arjuna.ats.jta.TransactionManager.transactionManager();
-        }
+    /**
+     * Gets the transaction manager.
+     *
+     * @return the transaction manager
+     */
+    protected TransactionManager getTransMgr() {
+        return com.arjuna.ats.jta.TransactionManager.transactionManager();
+    }
 
-        /**
-         * Gets the user transaction.
-         *
-         * @return the user transaction
-         */
-        public UserTransaction getUserTrans() {
-            return com.arjuna.ats.jta.UserTransaction.userTransaction();
-        }
+    /**
+     * Gets the user transaction.
+     *
+     * @return the user transaction
+     */
+    protected UserTransaction getUserTrans() {
+        return com.arjuna.ats.jta.UserTransaction.userTransaction();
+    }
 
-        /**
-         * Gets the transaction synchronization registry.
-         *
-         * @return the transaction synchronization registry
-         */
-        public TransactionSynchronizationRegistry getTransSyncReg() {
-            return SingletonRegistry.transreg;
-        }
+    /**
+     * Gets the transaction synchronization registry.
+     *
+     * @return the transaction synchronization registry
+     */
+    protected TransactionSynchronizationRegistry getTransSyncReg() {
+        return SingletonRegistry.transreg;
+    }
 
-        /**
-         * Gets the KIE services.
-         *
-         * @return the KIE services
-         */
-        public KieServices getKieServices() {
-            return KieServices.Factory.get();
-        }
+    /**
+     * Gets the KIE services.
+     *
+     * @return the KIE services
+     */
+    protected KieServices getKieServices() {
+        return KieServices.Factory.get();
+    }
 
-        /**
-         * Loads properties from a file.
-         *
-         * @param filenm name of the file to load
-         * @return properties, as loaded from the file
-         * @throws IOException if an error occurs reading from the file
-         */
-        public Properties loadProperties(String filenm) throws IOException {
-            return PropertyUtil.getProperties(filenm);
-        }
+    /**
+     * Loads properties from a file.
+     *
+     * @param filenm name of the file to load
+     * @return properties, as loaded from the file
+     * @throws IOException if an error occurs reading from the file
+     */
+    protected Properties loadProperties(String filenm) throws IOException {
+        return PropertyUtil.getProperties(filenm);
+    }
 
-        /**
-         * Makes a Data Source.
-         *
-         * @param dsProps data source properties
-         * @return a new data source
-         */
-        public BasicDataSource makeDataSource(Properties dsProps) {
-            try {
-                return BasicDataSourceFactory.createDataSource(dsProps);
+    /**
+     * Makes a Data Source.
+     *
+     * @param dsProps data source properties
+     * @return a new data source
+     */
+    protected BasicDataSource makeDataSource(Properties dsProps) {
+        try {
+            return BasicDataSourceFactory.createDataSource(dsProps);
 
-            } catch (Exception e) {
-                throw new PersistenceFeatureException(e);
-            }
+        } catch (Exception e) {
+            throw new PersistenceFeatureException(e);
         }
+    }
 
-        /**
-         * Makes a new JPA connector for drools sessions.
-         *
-         * @param emf entity manager factory
-         * @return a new JPA connector for drools sessions
-         */
-        public DroolsSessionConnector makeJpaConnector(EntityManagerFactory emf) {
-            return new JpaDroolsSessionConnector(emf);
-        }
+    /**
+     * Makes a new JPA connector for drools sessions.
+     *
+     * @param emf entity manager factory
+     * @return a new JPA connector for drools sessions
+     */
+    protected DroolsSessionConnector makeJpaConnector(EntityManagerFactory emf) {
+        return new JpaDroolsSessionConnector(emf);
+    }
 
-        /**
-         * Makes a new entity manager factory.
-         *
-         * @param props properties with which the factory should be configured
-         * @return a new entity manager factory
-         */
-        public EntityManagerFactory makeEntMgrFact(Map<String, Object> props) {
-            return Persistence.createEntityManagerFactory("onapsessionsPU", props);
-        }
+    /**
+     * Makes a new entity manager factory.
+     *
+     * @param props properties with which the factory should be configured
+     * @return a new entity manager factory
+     */
+    protected EntityManagerFactory makeEntMgrFact(Map<String, Object> props) {
+        return Persistence.createEntityManagerFactory("onapsessionsPU", props);
+    }
 
-        /**
-         * Gets the policy controller associated with a given policy container.
-         *
-         * @param container container whose controller is to be retrieved
-         * @return the container's controller
-         */
-        public PolicyController getPolicyController(PolicyContainer container) {
-            return PolicyController.factory.get(container.getGroupId(), container.getArtifactId());
-        }
+    /**
+     * Gets the policy controller associated with a given policy container.
+     *
+     * @param container container whose controller is to be retrieved
+     * @return the container's controller
+     */
+    protected PolicyController getPolicyController(PolicyContainer container) {
+        return PolicyController.factory.get(container.getGroupId(), container.getArtifactId());
     }
 
     /**
index 27ac2cc..1bab197 100644 (file)
@@ -83,6 +83,14 @@ import org.slf4j.LoggerFactory;
 
 public class PersistenceFeatureTest {
 
+    private static final String MY_KIE_BASE = "mybase";
+
+    private static final String MY_SESS_NAME = "myname";
+
+    private static final String MISSING_EXCEPTION = "missing exception";
+
+    private static final String EXPECTED = "expected exception";
+
     private static final Logger logger = LoggerFactory.getLogger(PersistenceFeatureTest.class);
 
     private static final String JDBC_DRIVER = "fake.driver";
@@ -113,7 +121,9 @@ public class PersistenceFeatureTest {
     private PolicyController polctlr;
     private PolicyContainer polcont;
     private PolicySession polsess;
-    private PersistenceFeature.Factory fact;
+    private int emfCount;
+    private int jpaCount;
+    private String propName;
 
     private PersistenceFeature feat;
 
@@ -163,22 +173,17 @@ public class PersistenceFeatureTest {
         polcont = mock(PolicyContainer.class);
         polctlr = mock(PolicyController.class);
         polsess = mock(PolicySession.class);
-        fact = mock(PersistenceFeature.Factory.class);
-
-        feat = new PersistenceFeature();
-        feat.setFactory(fact);
+        emfCount = 0;
+        jpaCount = 0;
+        propName = null;
+        
+        feat = new PersistenceFeatureImpl();
 
         props.putAll(stdprops);
 
         System.setProperty("com.arjuna.ats.arjuna.objectstore.objectStoreDir", "target/tm");
         System.setProperty("ObjectStoreEnvironmentBean.objectStoreDir", "target/tm");
 
-        when(fact.getKieServices()).thenReturn(kiesvc);
-        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);
@@ -215,14 +220,11 @@ public class PersistenceFeatureTest {
 
     @Test
     public void testGetContainerAdjunct_New() throws Exception {
-
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
+        setUpKie(MY_SESS_NAME, 999L, true);
         mockDbConn(5);
-        setUpKie("myname", 999L, true);
 
         // force getContainerAdjunct() to be invoked
-        feat.activatePolicySession(polcont, "myname", "mybase");
+        feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
 
         ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap =
                 ArgumentCaptor.forClass(PersistenceFeature.ContainerAdjunct.class);
@@ -234,14 +236,11 @@ public class PersistenceFeatureTest {
 
     @Test
     public void testGetContainerAdjunct_Existing() throws Exception {
-
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
+        setUpKie(MY_SESS_NAME, 999L, true);
         mockDbConn(5);
-        setUpKie("myname", 999L, true);
 
         // force getContainerAdjunct() to be invoked
-        feat.activatePolicySession(polcont, "myname", "mybase");
+        feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
 
         ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap =
                 ArgumentCaptor.forClass(PersistenceFeature.ContainerAdjunct.class);
@@ -253,7 +252,8 @@ public class PersistenceFeatureTest {
 
         // force getContainerAdjunct() to be invoked again
         setUpKie("myname2", 999L, true);
-        feat.activatePolicySession(polcont, "myname2", "mybase");
+        mockDbConn(5);
+        feat.activatePolicySession(polcont, "myname2", MY_KIE_BASE);
 
         // ensure it isn't invoked again
         verify(polcont, times(1)).setAdjunct(any(), any());
@@ -261,18 +261,16 @@ public class PersistenceFeatureTest {
 
     @Test
     public void testGetContainerAdjunct_WrongType() throws Exception {
-
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
+        setUpKie(MY_SESS_NAME, 999L, true);
         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");
+        mockDbConn(5);
+        feat.activatePolicySession(polcont, "myname2", MY_KIE_BASE);
 
         ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap =
                 ArgumentCaptor.forClass(PersistenceFeature.ContainerAdjunct.class);
@@ -293,27 +291,30 @@ public class PersistenceFeatureTest {
         feat.globalInit(null, SRC_TEST_RESOURCES);
 
         // verify that various factory methods were invoked
-        verify(fact).getKieServices();
-        verify(fact).loadProperties("src/test/resources/feature-session-persistence.properties");
+        assertEquals("src/test/resources/feature-session-persistence.properties", propName);
     }
 
     @Test(expected = NullPointerException.class)
     public void testGlobalInitIoEx() throws Exception {
 
-        when(fact.loadProperties(anyString())).thenThrow(new IOException("expected exception"));
+        feat = new PersistenceFeatureImpl() {
+            @Override
+            protected Properties loadProperties(String filenm) throws IOException {
+                throw new IOException(EXPECTED);
+            }
+        };
 
         feat.globalInit(null, SRC_TEST_RESOURCES);
     }
 
     @Test
     public void testActivatePolicySession() throws Exception {
+        setUpKie(MY_SESS_NAME, 999L, true);
         final PreparedStatement ps = mockDbConn(5);
-        setUpKie("myname", 999L, true);
-
-        feat.globalInit(null, SRC_TEST_RESOURCES);
+        
         feat.beforeActivate(null);
 
-        KieSession session = feat.activatePolicySession(polcont, "myname", "mybase");
+        KieSession session = feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
 
         verify(kiestore).loadKieSession(anyLong(), any(), any(), any());
         verify(kiestore, never()).newKieSession(any(), any(), any());
@@ -324,22 +325,20 @@ public class PersistenceFeatureTest {
 
         verify(kieenv, times(4)).set(anyString(), any());
 
-        verify(jpa).get("myname");
+        verify(jpa).get(MY_SESS_NAME);
         verify(jpa).replace(any());
     }
 
     @Test
     public void testActivatePolicySession_NoPersistence() throws Exception {
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
+        setUpKie(MY_SESS_NAME, 999L, true);
         final 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, MY_SESS_NAME, MY_KIE_BASE));
 
         verify(ps, never()).executeUpdate();
         verify(kiestore, never()).loadKieSession(anyLong(), any(), any(), any());
@@ -349,12 +348,10 @@ public class PersistenceFeatureTest {
     /** Verifies that a new KIE session is created when there is no existing session entity. */
     @Test
     public void testActivatePolicySession_New() throws Exception {
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
-        mockDbConn(5);
         setUpKie("noName", 999L, true);
+        mockDbConn(5);
 
-        KieSession session = feat.activatePolicySession(polcont, "myname", "mybase");
+        KieSession session = feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
 
         verify(kiestore, never()).loadKieSession(anyLong(), any(), any(), any());
         verify(kiestore).newKieSession(any(), any(), any());
@@ -363,7 +360,7 @@ public class PersistenceFeatureTest {
 
         verify(kieenv, times(4)).set(anyString(), any());
 
-        verify(jpa).get("myname");
+        verify(jpa).get(MY_SESS_NAME);
         verify(jpa).replace(any());
     }
 
@@ -372,12 +369,10 @@ public class PersistenceFeatureTest {
      */
     @Test
     public void testActivatePolicySession_LoadFailed() throws Exception {
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
+        setUpKie(MY_SESS_NAME, 999L, false);
         mockDbConn(5);
-        setUpKie("myname", 999L, false);
 
-        KieSession session = feat.activatePolicySession(polcont, "myname", "mybase");
+        KieSession session = feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
 
         verify(kiestore).loadKieSession(anyLong(), any(), any(), any());
         verify(kiestore).newKieSession(any(), any(), any());
@@ -386,35 +381,31 @@ public class PersistenceFeatureTest {
 
         verify(kieenv, times(4)).set(anyString(), any());
 
-        verify(jpa).get("myname");
+        verify(jpa).get(MY_SESS_NAME);
 
         ArgumentCaptor<DroolsSession> drools = ArgumentCaptor.forClass(DroolsSession.class);
         verify(jpa).replace(drools.capture());
 
-        assertEquals("myname", drools.getValue().getSessionName());
+        assertEquals(MY_SESS_NAME, drools.getValue().getSessionName());
         assertEquals(100L, drools.getValue().getSessionId());
     }
 
     @Test
     public void testLoadDataSource() throws Exception {
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
+        setUpKie(MY_SESS_NAME, 999L, false);
         mockDbConn(5);
-        setUpKie("myname", 999L, false);
 
-        feat.activatePolicySession(polcont, "myname", "mybase");
+        feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
 
-        verify(fact).makeEntMgrFact(any());
+        assertEquals(1, emfCount);
     }
 
     @Test
     public void testConfigureSysProps() throws Exception {
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
+        setUpKie(MY_SESS_NAME, 999L, false);
         mockDbConn(5);
-        setUpKie("myname", 999L, false);
 
-        feat.activatePolicySession(polcont, "myname", "mybase");
+        feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
 
         assertEquals("60", System.getProperty("com.arjuna.ats.arjuna.coordinator.defaultTimeout"));
         assertEquals(JTA_OSDIR, System.getProperty("com.arjuna.ats.arjuna.objectstore.objectStoreDir"));
@@ -423,12 +414,10 @@ public class PersistenceFeatureTest {
 
     @Test
     public void testConfigureKieEnv() throws Exception {
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
+        setUpKie(MY_SESS_NAME, 999L, false);
         mockDbConn(5);
-        setUpKie("myname", 999L, false);
 
-        feat.activatePolicySession(polcont, "myname", "mybase");
+        feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
 
         verify(kieenv, times(4)).set(any(), any());
 
@@ -442,19 +431,24 @@ public class PersistenceFeatureTest {
 
     @Test
     public void testConfigureKieEnv_RtEx() throws Exception {
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
+        setUpKie(MY_SESS_NAME, 999L, false);
         mockDbConn(5);
-        setUpKie("myname", 999L, false);
-
-        when(fact.getUserTrans()).thenThrow(new IllegalArgumentException("expected exception"));
+        
+        feat = new PersistenceFeatureMockDb() {
+            @Override
+            protected UserTransaction getUserTrans() {
+                throw new IllegalArgumentException(EXPECTED);
+            }
+        };
+        
+        feat.globalInit(null, SRC_TEST_RESOURCES);
 
         try {
-            feat.activatePolicySession(polcont, "myname", "mybase");
-            fail("missing exception");
+            feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
+            fail(MISSING_EXCEPTION);
 
         } catch (IllegalArgumentException ex) {
-            logger.trace("expected exception", ex);
+            logger.trace(EXPECTED, ex);
         }
 
         verify(bds, times(2)).close();
@@ -462,12 +456,10 @@ public class PersistenceFeatureTest {
 
     @Test
     public void testLoadKieSession() throws Exception {
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
+        setUpKie(MY_SESS_NAME, 999L, true);
         mockDbConn(5);
-        setUpKie("myname", 999L, true);
-
-        KieSession session = feat.activatePolicySession(polcont, "myname", "mybase");
+        
+        KieSession session = feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
 
         verify(kiestore).loadKieSession(999L, kiebase, kiecfg, kieenv);
         verify(kiestore, never()).newKieSession(any(), any(), any());
@@ -481,15 +473,13 @@ public class PersistenceFeatureTest {
      */
     @Test
     public void testLoadKieSession_Ex() throws Exception {
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
+        setUpKie(MY_SESS_NAME, 999L, false);
         mockDbConn(5);
-        setUpKie("myname", 999L, false);
 
         when(kiestore.loadKieSession(anyLong(), any(), any(), any()))
-            .thenThrow(new IllegalArgumentException("expected exception"));
+            .thenThrow(new IllegalArgumentException(EXPECTED));
 
-        KieSession session = feat.activatePolicySession(polcont, "myname", "mybase");
+        KieSession session = feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
 
         verify(kiestore).loadKieSession(anyLong(), any(), any(), any());
         verify(kiestore).newKieSession(any(), any(), any());
@@ -499,12 +489,10 @@ public class PersistenceFeatureTest {
 
     @Test
     public void testNewKieSession() throws Exception {
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
+        setUpKie(MY_SESS_NAME, 999L, false);
         mockDbConn(5);
-        setUpKie("myname", 999L, false);
 
-        KieSession session = feat.activatePolicySession(polcont, "myname", "mybase");
+        KieSession session = feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
 
         verify(kiestore).newKieSession(kiebase, null, kieenv);
 
@@ -513,11 +501,10 @@ public class PersistenceFeatureTest {
 
     @Test
     public void testLoadDataSource_DiffSession() throws Exception {
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
+        setUpKie(MY_SESS_NAME, 999L, false);
         mockDbConn(5);
-        setUpKie("myname", 999L, false);
-        feat.activatePolicySession(polcont, "myname", "mybase");
+
+        feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
 
         ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap =
                 ArgumentCaptor.forClass(PersistenceFeature.ContainerAdjunct.class);
@@ -527,16 +514,17 @@ public class PersistenceFeatureTest {
         when(polcont.getAdjunct(any())).thenReturn(adjcap.getValue());
 
         setUpKie("myname2", 999L, false);
+        mockDbConn(5);
 
         // invoke it again
-        feat.activatePolicySession(polcont, "myname2", "mybase");
+        feat.activatePolicySession(polcont, "myname2", MY_KIE_BASE);
 
-        verify(fact, times(2)).makeEntMgrFact(any());
+        assertEquals(2, emfCount);
     }
 
     @Test
     public void testSelectThreadModel_Persistent() throws Exception {
-        setUpKie("myname", 999L, true);
+        setUpKie(MY_SESS_NAME, 999L, true);
 
         ThreadModel model = feat.selectThreadModel(polsess);
         assertNotNull(model);
@@ -545,13 +533,12 @@ public class PersistenceFeatureTest {
 
     @Test
     public void testSelectThreadModel_NotPersistent() throws Exception {
-        when(fact.getPolicyController(any())).thenReturn(polctlr);
         assertNull(feat.selectThreadModel(polsess));
     }
 
     @Test
     public void testSelectThreadModel_Start__Run_Update_Stop() throws Exception {
-        setUpKie("myname", 999L, true);
+        setUpKie(MY_SESS_NAME, 999L, true);
 
         ThreadModel model = feat.selectThreadModel(polsess);
         assertNotNull(model);
@@ -567,17 +554,16 @@ public class PersistenceFeatureTest {
 
     @Test
     public void testDisposeKieSession() throws Exception {
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
-        final ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap =
-                ArgumentCaptor.forClass(PersistenceFeature.ContainerAdjunct.class);
-
+        setUpKie(MY_SESS_NAME, 999L, false);
         mockDbConn(5);
-        setUpKie("myname", 999L, false);
 
-        feat.activatePolicySession(polcont, "myname", "mybase");
+        feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
 
         verify(emf, never()).close();
+
+        final ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap =
+                ArgumentCaptor.forClass(PersistenceFeature.ContainerAdjunct.class);
+        
         verify(polcont).setAdjunct(any(), adjcap.capture());
 
         when(polcont.getAdjunct(any())).thenReturn(adjcap.getValue());
@@ -599,17 +585,16 @@ public class PersistenceFeatureTest {
 
     @Test
     public void testDisposeKieSession_NoPersistence() throws Exception {
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
-        final ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap =
-                ArgumentCaptor.forClass(PersistenceFeature.ContainerAdjunct.class);
-
+        setUpKie(MY_SESS_NAME, 999L, false);
         mockDbConn(5);
-        setUpKie("myname", 999L, false);
 
-        feat.activatePolicySession(polcont, "myname", "mybase");
+        feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
 
         verify(emf, never()).close();
+
+        final ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap =
+                ArgumentCaptor.forClass(PersistenceFeature.ContainerAdjunct.class);
+        
         verify(polcont).setAdjunct(any(), adjcap.capture());
 
         when(polcont.getAdjunct(any())).thenReturn(adjcap.getValue());
@@ -624,17 +609,16 @@ public class PersistenceFeatureTest {
 
     @Test
     public void testDestroyKieSession() throws Exception {
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
-        final ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap =
-                ArgumentCaptor.forClass(PersistenceFeature.ContainerAdjunct.class);
-
+        setUpKie(MY_SESS_NAME, 999L, false);
         mockDbConn(5);
-        setUpKie("myname", 999L, false);
 
-        feat.activatePolicySession(polcont, "myname", "mybase");
+        feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
 
         verify(emf, never()).close();
+
+        final ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap =
+                ArgumentCaptor.forClass(PersistenceFeature.ContainerAdjunct.class);
+        
         verify(polcont).setAdjunct(any(), adjcap.capture());
 
         when(polcont.getAdjunct(any())).thenReturn(adjcap.getValue());
@@ -656,17 +640,16 @@ public class PersistenceFeatureTest {
 
     @Test
     public void testDestroyKieSession_NoPersistence() throws Exception {
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
-        final ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap =
-                ArgumentCaptor.forClass(PersistenceFeature.ContainerAdjunct.class);
-
+        setUpKie(MY_SESS_NAME, 999L, false);
         mockDbConn(5);
-        setUpKie("myname", 999L, false);
 
-        feat.activatePolicySession(polcont, "myname", "mybase");
+        feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
 
         verify(emf, never()).close();
+
+        final ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap =
+                ArgumentCaptor.forClass(PersistenceFeature.ContainerAdjunct.class);
+        
         verify(polcont).setAdjunct(any(), adjcap.capture());
 
         when(polcont.getAdjunct(any())).thenReturn(adjcap.getValue());
@@ -761,13 +744,10 @@ public class PersistenceFeatureTest {
 
     @Test
     public void testGetPersistenceTimeout_Valid() throws Exception {
+        setUpKie(MY_SESS_NAME, 999L, true);
         final PreparedStatement statement = mockDbConn(5);
 
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
-        setUpKie("myname", 999L, true);
-
-        feat.activatePolicySession(polcont, "myname", "mybase");
+        feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
 
         verify(statement).executeUpdate();
     }
@@ -777,13 +757,10 @@ public class PersistenceFeatureTest {
 
         props.remove(DroolsPersistenceProperties.DB_SESSIONINFO_TIMEOUT);
 
+        setUpKie(MY_SESS_NAME, 999L, true);
         final PreparedStatement statement = mockDbConn(0);
 
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
-        setUpKie("myname", 999L, true);
-
-        feat.activatePolicySession(polcont, "myname", "mybase");
+        feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
 
         verify(statement, never()).executeUpdate();
     }
@@ -791,24 +768,21 @@ public class PersistenceFeatureTest {
     @Test
     public void testGetPersistenceTimeout_Invalid() throws Exception {
         props.setProperty(DroolsPersistenceProperties.DB_SESSIONINFO_TIMEOUT, "abc");
+        
+        setUpKie(MY_SESS_NAME, 999L, true);
         final PreparedStatement s = mockDbConn(0);
 
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
-        setUpKie("myname", 999L, true);
-
-        feat.activatePolicySession(polcont, "myname", "mybase");
+        feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
 
         verify(s, never()).executeUpdate();
     }
 
     @Test
     public void testCleanUpSessionInfo() throws Exception {
-        setUpKie("myname", 999L, true);
+        setUpKie(MY_SESS_NAME, 999L, true);
 
         // use a real DB so we can verify that the "delete" works correctly
-        fact = new PartialFactory();
-        feat.setFactory(fact);
+        feat = new PartialFeature();
 
         makeSessionInfoTbl(20000);
 
@@ -819,70 +793,64 @@ public class PersistenceFeatureTest {
         feat.globalInit(null, SRC_TEST_RESOURCES);
 
         feat.beforeStart(null);
-        feat.activatePolicySession(polcont, "myname", "mybase");
+        feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
 
         assertEquals("[1, 4, 5]", getSessions().toString());
     }
 
     @Test
     public void testCleanUpSessionInfo_WithBeforeStart() throws Exception {
+        setUpKie(MY_SESS_NAME, 999L, true);
         final PreparedStatement statement = mockDbConn(0);
 
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
-        setUpKie("myname", 999L, true);
-
         // reset
         feat.beforeStart(null);
 
-        feat.activatePolicySession(polcont, "myname", "mybase");
+        feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
         verify(statement, times(1)).executeUpdate();
 
         // should not clean-up again
-        feat.activatePolicySession(polcont, "myname", "mybase");
-        feat.activatePolicySession(polcont, "myname", "mybase");
+        feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
+        feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
         verify(statement, times(1)).executeUpdate();
 
         // reset
         feat.beforeStart(null);
 
-        feat.activatePolicySession(polcont, "myname", "mybase");
+        feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
         verify(statement, times(2)).executeUpdate();
 
         // should not clean-up again
-        feat.activatePolicySession(polcont, "myname", "mybase");
-        feat.activatePolicySession(polcont, "myname", "mybase");
+        feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
+        feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
         verify(statement, times(2)).executeUpdate();
     }
 
     @Test
     public void testCleanUpSessionInfo_WithBeforeActivate() throws Exception {
+        setUpKie(MY_SESS_NAME, 999L, true);
         final PreparedStatement statement = mockDbConn(0);
 
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
-        setUpKie("myname", 999L, true);
-
         // reset
         feat.beforeActivate(null);
 
-        feat.activatePolicySession(polcont, "myname", "mybase");
+        feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
         verify(statement, times(1)).executeUpdate();
 
         // should not clean-up again
-        feat.activatePolicySession(polcont, "myname", "mybase");
-        feat.activatePolicySession(polcont, "myname", "mybase");
+        feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
+        feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
         verify(statement, times(1)).executeUpdate();
 
         // reset
         feat.beforeActivate(null);
 
-        feat.activatePolicySession(polcont, "myname", "mybase");
+        feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
         verify(statement, times(2)).executeUpdate();
 
         // should not clean-up again
-        feat.activatePolicySession(polcont, "myname", "mybase");
-        feat.activatePolicySession(polcont, "myname", "mybase");
+        feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
+        feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
         verify(statement, times(2)).executeUpdate();
     }
 
@@ -891,32 +859,26 @@ public class PersistenceFeatureTest {
 
         props.remove(DroolsPersistenceProperties.DB_SESSIONINFO_TIMEOUT);
 
+        setUpKie(MY_SESS_NAME, 999L, true);
         final PreparedStatement statement = mockDbConn(0);
 
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
-        setUpKie("myname", 999L, true);
-
-        feat.activatePolicySession(polcont, "myname", "mybase");
+        feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
 
         verify(statement, never()).executeUpdate();
     }
 
     @Test
     public void testCleanUpSessionInfo_NoUrl() throws Exception {
-        final PreparedStatement statement = mockDbConn(0);
-
         props.remove(DroolsPersistenceProperties.DB_URL);
-
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
-        setUpKie("myname", 999L, true);
+        
+        setUpKie(MY_SESS_NAME, 999L, true);
+        final PreparedStatement statement = mockDbConn(0);
 
         try {
-            feat.activatePolicySession(polcont, "myname", "mybase");
-            fail("missing exception");
+            feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
+            fail(MISSING_EXCEPTION);
         } catch (RuntimeException e) {
-            logger.trace("expected exception", e);
+            logger.trace(EXPECTED, e);
         }
 
         verify(statement, never()).executeUpdate();
@@ -924,19 +886,16 @@ public class PersistenceFeatureTest {
 
     @Test
     public void testCleanUpSessionInfo_NoUser() throws Exception {
-        final PreparedStatement statement = mockDbConn(0);
-
         props.remove(DroolsPersistenceProperties.DB_USER);
-
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
-        setUpKie("myname", 999L, true);
+        
+        setUpKie(MY_SESS_NAME, 999L, true);
+        final PreparedStatement statement = mockDbConn(0);
 
         try {
-            feat.activatePolicySession(polcont, "myname", "mybase");
-            fail("missing exception");
+            feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
+            fail(MISSING_EXCEPTION);
         } catch (RuntimeException e) {
-            logger.trace("expected exception", e);
+            logger.trace(EXPECTED, e);
         }
 
         verify(statement, never()).executeUpdate();
@@ -944,19 +903,16 @@ public class PersistenceFeatureTest {
 
     @Test
     public void testCleanUpSessionInfo_NoPassword() throws Exception {
-        final PreparedStatement statement = mockDbConn(0);
-
         props.remove(DroolsPersistenceProperties.DB_PWD);
 
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
-        setUpKie("myname", 999L, true);
+        setUpKie(MY_SESS_NAME, 999L, true);
+        final PreparedStatement statement = mockDbConn(0);
 
         try {
-            feat.activatePolicySession(polcont, "myname", "mybase");
-            fail("missing exception");
+            feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
+            fail(MISSING_EXCEPTION);
         } catch (RuntimeException e) {
-            logger.trace("expected exception", e);
+            logger.trace(EXPECTED, e);
         }
 
         verify(statement, never()).executeUpdate();
@@ -964,162 +920,141 @@ public class PersistenceFeatureTest {
 
     @Test
     public void testCleanUpSessionInfo_SqlEx() throws Exception {
+        setUpKie(MY_SESS_NAME, 999L, true);
         final PreparedStatement statement = mockDbConn(-1);
 
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
-        setUpKie("myname", 999L, true);
-
-        feat.activatePolicySession(polcont, "myname", "mybase");
+        feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
 
         verify(statement).executeUpdate();
     }
 
     @Test
     public void testGetDroolsSessionConnector() throws Exception {
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
+        setUpKie(MY_SESS_NAME, 999L, true);
         mockDbConn(5);
-        setUpKie("myname", 999L, true);
 
-        feat.activatePolicySession(polcont, "myname", "mybase");
+        feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
 
-        verify(fact).makeJpaConnector(emf);
+        assertEquals(1, jpaCount);
     }
 
     @Test
     public void testReplaceSession() throws Exception {
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
-        final ArgumentCaptor<DroolsSession> sesscap = ArgumentCaptor.forClass(DroolsSession.class);
-
+        setUpKie(MY_SESS_NAME, 999L, true);
         mockDbConn(5);
-        setUpKie("myname", 999L, true);
 
-        feat.activatePolicySession(polcont, "myname", "mybase");
+        feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
 
+        final ArgumentCaptor<DroolsSession> sesscap = ArgumentCaptor.forClass(DroolsSession.class);
+        
         verify(jpa).replace(sesscap.capture());
 
-        assertEquals("myname", sesscap.getValue().getSessionName());
+        assertEquals(MY_SESS_NAME, sesscap.getValue().getSessionName());
         assertEquals(999L, sesscap.getValue().getSessionId());
     }
 
     @Test
     public void testIsPersistenceEnabled_Auto() throws Exception {
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
+        setUpKie(MY_SESS_NAME, 999L, true);
         mockDbConn(5);
-        setUpKie("myname", 999L, true);
 
         props.setProperty("persistence.type", "auto");
 
-        assertNotNull(feat.activatePolicySession(polcont, "myname", "mybase"));
+        assertNotNull(feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE));
     }
 
     @Test
     public void testIsPersistenceEnabled_Native() throws Exception {
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
+        setUpKie(MY_SESS_NAME, 999L, true);
         mockDbConn(5);
-        setUpKie("myname", 999L, true);
 
         props.setProperty("persistence.type", "native");
 
-        assertNotNull(feat.activatePolicySession(polcont, "myname", "mybase"));
+        assertNotNull(feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE));
     }
 
     @Test
     public void testIsPersistenceEnabled_None() throws Exception {
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
+        setUpKie(MY_SESS_NAME, 999L, true);
         mockDbConn(5);
-        setUpKie("myname", 999L, true);
 
         props.remove("persistence.type");
 
-        assertNull(feat.activatePolicySession(polcont, "myname", "mybase"));
+        assertNull(feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE));
     }
 
     @Test
     public void testGetProperties_Ex() throws Exception {
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
+        setUpKie(MY_SESS_NAME, 999L, true);
         mockDbConn(5);
-        setUpKie("myname", 999L, true);
 
-        when(fact.getPolicyController(polcont))
-            .thenThrow(new IllegalArgumentException("expected exception"));
+        feat = new PersistenceFeatureMockDb() {
+            @Override
+            protected PolicyController getPolicyController(PolicyContainer container) {
+                throw new IllegalArgumentException(EXPECTED);
+            }
+        };
 
-        assertNull(feat.activatePolicySession(polcont, "myname", "mybase"));
+        assertNull(feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE));
     }
 
     @Test
     public void testGetProperty_Specific() throws Exception {
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
+        setUpKie(MY_SESS_NAME, 999L, true);
         mockDbConn(5);
-        setUpKie("myname", 999L, true);
 
         props.remove("persistence.type");
         props.setProperty("persistence.myname.type", "auto");
 
-        assertNotNull(feat.activatePolicySession(polcont, "myname", "mybase"));
+        assertNotNull(feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE));
     }
 
     @Test
     public void testGetProperty_Specific_None() throws Exception {
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
+        setUpKie(MY_SESS_NAME, 999L, true);
         mockDbConn(5);
-        setUpKie("myname", 999L, true);
 
         props.remove("persistence.type");
         props.setProperty("persistence.xxx.type", "auto");
 
-        assertNull(feat.activatePolicySession(polcont, "myname", "mybase"));
+        assertNull(feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE));
     }
 
     @Test
     public void testGetProperty_Both_SpecificOn() throws Exception {
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
+        setUpKie(MY_SESS_NAME, 999L, true);
         mockDbConn(5);
-        setUpKie("myname", 999L, true);
 
         props.setProperty("persistence.type", "other");
         props.setProperty("persistence.myname.type", "auto");
 
-        assertNotNull(feat.activatePolicySession(polcont, "myname", "mybase"));
+        assertNotNull(feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE));
     }
 
     @Test
     public void testGetProperty_Both_SpecificDisabledOff() throws Exception {
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
+        setUpKie(MY_SESS_NAME, 999L, true);
         mockDbConn(5);
-        setUpKie("myname", 999L, true);
 
         props.setProperty("persistence.type", "auto");
         props.setProperty("persistence.myname.type", "other");
 
-        assertNull(feat.activatePolicySession(polcont, "myname", "mybase"));
+        assertNull(feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE));
     }
 
     @Test
     public void testGetProperty_None() throws Exception {
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
+        setUpKie(MY_SESS_NAME, 999L, true);
         mockDbConn(5);
-        setUpKie("myname", 999L, true);
 
         props.remove("persistence.type");
 
-        assertNull(feat.activatePolicySession(polcont, "myname", "mybase"));
+        assertNull(feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE));
     }
 
     @Test
     public void testPersistenceFeatureException() {
-        SecurityException secex = new SecurityException("expected exception");
+        SecurityException secex = new SecurityException(EXPECTED);
         PersistenceFeatureException ex = new PersistenceFeatureException(secex);
 
         assertEquals(secex, ex.getCause());
@@ -1127,19 +1062,24 @@ public class PersistenceFeatureTest {
 
     @Test
     public void testDsEmf_RtEx() throws Exception {
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
+        setUpKie(MY_SESS_NAME, 999L, false);
         mockDbConn(5);
-        setUpKie("myname", 999L, false);
 
-        when(fact.makeEntMgrFact(any())).thenThrow(new IllegalArgumentException("expected exception"));
+        feat = new PersistenceFeatureMockDb() {
+            @Override
+            protected EntityManagerFactory makeEntMgrFact(Map<String, Object> props) {
+                throw new IllegalArgumentException(EXPECTED);
+            }
+        };
+
+        feat.globalInit(null, SRC_TEST_RESOURCES);
 
         try {
-            feat.activatePolicySession(polcont, "myname", "mybase");
-            fail("missing exception");
+            feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
+            fail(MISSING_EXCEPTION);
 
         } catch (IllegalArgumentException ex) {
-            logger.trace("expected exception", ex);
+            logger.trace(EXPECTED, ex);
         }
 
         verify(bds, times(2)).close();
@@ -1147,12 +1087,10 @@ public class PersistenceFeatureTest {
 
     @Test
     public void testDsEmf_Close_RtEx() throws Exception {
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
+        setUpKie(MY_SESS_NAME, 999L, false);
         mockDbConn(5);
-        setUpKie("myname", 999L, false);
 
-        feat.activatePolicySession(polcont, "myname", "mybase");
+        feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
 
         ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap =
                 ArgumentCaptor.forClass(PersistenceFeature.ContainerAdjunct.class);
@@ -1163,13 +1101,13 @@ public class PersistenceFeatureTest {
         when(polcont.getAdjunct(any())).thenReturn(adjcap.getValue());
 
         try {
-            doThrow(new IllegalArgumentException("expected exception")).when(emf).close();
+            doThrow(new IllegalArgumentException(EXPECTED)).when(emf).close();
 
             feat.destroyKieSession(polsess);
-            fail("missing exception");
+            fail(MISSING_EXCEPTION);
 
         } catch (IllegalArgumentException ex) {
-            logger.trace("expected exception", ex);
+            logger.trace(EXPECTED, ex);
         }
 
         verify(bds, times(2)).close();
@@ -1177,12 +1115,10 @@ public class PersistenceFeatureTest {
 
     @Test
     public void testDsEmf_CloseDataSource_RtEx() throws Exception {
-        feat.globalInit(null, SRC_TEST_RESOURCES);
-
+        setUpKie(MY_SESS_NAME, 999L, false);
         mockDbConn(5);
-        setUpKie("myname", 999L, false);
 
-        feat.activatePolicySession(polcont, "myname", "mybase");
+        feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
 
         ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap =
                 ArgumentCaptor.forClass(PersistenceFeature.ContainerAdjunct.class);
@@ -1193,13 +1129,13 @@ public class PersistenceFeatureTest {
         when(polcont.getAdjunct(any())).thenReturn(adjcap.getValue());
 
         try {
-            doThrow(new SQLException("expected exception")).when(bds).close();
+            doThrow(new SQLException(EXPECTED)).when(bds).close();
 
             feat.destroyKieSession(polsess);
-            fail("missing exception");
+            fail(MISSING_EXCEPTION);
 
         } catch (PersistenceFeatureException ex) {
-            logger.trace("expected exception", ex);
+            logger.trace(EXPECTED, ex);
         }
     }
 
@@ -1236,11 +1172,6 @@ public class PersistenceFeatureTest {
      * @throws Exception exception
      */
     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);
@@ -1263,6 +1194,9 @@ public class PersistenceFeatureTest {
         }
 
         when(kiestore.newKieSession(any(), any(), any())).thenReturn(kiesess);
+
+        feat = new PersistenceFeatureKie();
+        feat.globalInit(null, SRC_TEST_RESOURCES);
     }
 
     /**
@@ -1363,51 +1297,108 @@ public class PersistenceFeatureTest {
         PreparedStatement statement = mock(PreparedStatement.class);
 
         when(bds.getConnection()).thenReturn(connection);
-        when(fact.makeDataSource(any())).thenReturn(bds);
         when(connection.prepareStatement(anyString())).thenReturn(statement);
 
         if (retval < 0) {
             // should throw an exception
-            when(statement.executeUpdate()).thenThrow(new SQLException("expected exception"));
+            when(statement.executeUpdate()).thenThrow(new SQLException(EXPECTED));
 
         } else {
             // should return the value
             when(statement.executeUpdate()).thenReturn(retval);
         }
 
+        feat = new PersistenceFeatureMockDb();
+        feat.globalInit(null, SRC_TEST_RESOURCES);
+
         return statement;
     }
+    
+    /**
+     * Feature with a mock DB.
+     */
+    private class PersistenceFeatureMockDb extends PersistenceFeatureKie {
 
-    /** A partial factory, which exports a few of the real methods, but overrides the rest. */
-    private class PartialFactory extends PersistenceFeature.Factory {
+        @Override
+        protected BasicDataSource makeDataSource(Properties dsProps) {
+            return bds;
+        }
+    }
+    
+    /**
+     * Feature supporting newKieSession.
+     */
+    private class PersistenceFeatureKie extends PersistenceFeatureImpl {
+
+        @Override
+        protected EntityManagerFactory makeEntMgrFact(Map<String, Object> props) {
+            ++emfCount;
+            return emf;
+        }
+
+        @Override
+        protected DroolsSessionConnector makeJpaConnector(EntityManagerFactory emf) {
+            ++jpaCount;
+            return jpa;
+        }
+    }
+    
+    /**
+     * Feature with overrides.
+     */
+    private class PersistenceFeatureImpl extends PartialFeature {
+
+        @Override
+        protected Properties loadProperties(String filenm) throws IOException {
+            propName = filenm;
+            return props;
+        }
+
+        @Override
+        protected BasicDataSource makeDataSource(Properties dsProps) {
+            return null;
+        }
+
+        @Override
+        protected DroolsSessionConnector makeJpaConnector(EntityManagerFactory emf) {
+            ++jpaCount;
+            return null;
+        }
+    }
+    
+    /**
+     * Feature with <i>some</i> overrides.
+     */
+    private class PartialFeature extends PersistenceFeature {
 
         @Override
-        public TransactionManager getTransMgr() {
+        protected TransactionManager getTransMgr() {
             return transmgr;
         }
 
         @Override
-        public UserTransaction getUserTrans() {
+        protected UserTransaction getUserTrans() {
             return usertrans;
         }
 
         @Override
-        public TransactionSynchronizationRegistry getTransSyncReg() {
+        protected TransactionSynchronizationRegistry getTransSyncReg() {
             return transreg;
         }
 
         @Override
-        public KieServices getKieServices() {
+        protected KieServices getKieServices() {
             return kiesvc;
         }
 
         @Override
-        public EntityManagerFactory makeEntMgrFact(Map<String, Object> props) {
+        protected EntityManagerFactory makeEntMgrFact(Map<String, Object> props) {
+            ++emfCount;
             return emf;
         }
 
         @Override
-        public PolicyController getPolicyController(PolicyContainer container) {
+        protected PolicyController getPolicyController(PolicyContainer container) {
             return polctlr;
         }
     }
index 33f4668..487814c 100644 (file)
@@ -34,11 +34,6 @@ public class PolicyResourceLockManager extends SimpleLockManager {
 
     private static Logger logger = LoggerFactory.getLogger(PolicyResourceLockManager.class);
 
-    /**
-     * Used to access various objects.
-     */
-    private static Factory factory = new Factory();
-
     /**
      * Used by junit tests.
      */
@@ -55,19 +50,6 @@ public class PolicyResourceLockManager extends SimpleLockManager {
         return Singleton.instance;
     }
 
-    protected static Factory getFactory() {
-        return factory;
-    }
-
-    /**
-     * Sets the factory to be used by junit tests.
-     * 
-     * @param factory the factory
-     */
-    protected static void setFactory(Factory factory) {
-        PolicyResourceLockManager.factory = factory;
-    }
-
     @Override
     public boolean lock(String resourceId, String owner, int holdSec) {
         if (resourceId == null) {
@@ -205,9 +187,9 @@ public class PolicyResourceLockManager extends SimpleLockManager {
      * @return first non-null value returned by an implementer, <i>continueValue</i> if
      *       they all returned <i>continueValue</i>
      */
-    private static <T> T doIntercept(T continueValue, Function<PolicyResourceLockFeatureApi, T> func) {
+    private <T> T doIntercept(T continueValue, Function<PolicyResourceLockFeatureApi, T> func) {
 
-        for (PolicyResourceLockFeatureApi impl : factory.getImplementers()) {
+        for (PolicyResourceLockFeatureApi impl : getImplementers()) {
             try {
                 T result = func.apply(impl);
                 if (result != continueValue) {
@@ -222,6 +204,17 @@ public class PolicyResourceLockManager extends SimpleLockManager {
         return continueValue;
     }
 
+    // these may be overridden by junit tests
+
+    /**
+     * Get implementers.
+     * 
+     * @return the list of feature implementers
+     */
+    protected List<PolicyResourceLockFeatureApi> getImplementers() {
+        return PolicyResourceLockFeatureApi.impl.getList();
+    }
+
     /**
      * Initialization-on-demand holder idiom.
      */
@@ -235,21 +228,5 @@ public class PolicyResourceLockManager extends SimpleLockManager {
         private Singleton() {
             super();
         }
-
-    }
-
-    /**
-     * Used to access various objects.
-     */
-    public static class Factory {
-
-        /**
-         * Get implementers.
-         * 
-         * @return the list of feature implementers
-         */
-        public List<PolicyResourceLockFeatureApi> getImplementers() {
-            return PolicyResourceLockFeatureApi.impl.getList();
-        }
     }
 }
index 8acafcc..81b52d1 100644 (file)
@@ -37,12 +37,9 @@ import static org.onap.policy.drools.core.lock.TestingUtils.expectException;
 import java.util.Arrays;
 import java.util.LinkedList;
 import java.util.List;
-import org.junit.AfterClass;
 import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.Test;
 import org.onap.policy.drools.core.lock.PolicyResourceLockFeatureApi.OperResult;
-import org.onap.policy.drools.core.lock.PolicyResourceLockManager.Factory;
 
 public class PolicyResourceLockManagerTest {
 
@@ -59,27 +56,12 @@ public class PolicyResourceLockManagerTest {
     private static final String OWNER2 = "owner.two";
     private static final String OWNER3 = "owner.three";
 
-    /**
-     * Saved at the start of the tests and restored once all tests complete.
-     */
-    private static Factory saveFactory;
-
     private PolicyResourceLockFeatureApi impl1;
     private PolicyResourceLockFeatureApi impl2;
     private List<PolicyResourceLockFeatureApi> implList;
 
     private PolicyResourceLockManager mgr;
 
-    @BeforeClass
-    public static void setUpBeforeClass() {
-        saveFactory = PolicyResourceLockManager.getFactory();
-    }
-
-    @AfterClass
-    public static void tearDownAfterClass() {
-        PolicyResourceLockManager.setFactory(saveFactory);
-    }
-
     /**
      * Set up.
      */
@@ -94,15 +76,12 @@ public class PolicyResourceLockManagerTest {
         // list of feature API implementers
         implList = new LinkedList<>(Arrays.asList(impl1, impl2));
 
-        PolicyResourceLockManager.setFactory(new Factory() {
-
+        mgr = new PolicyResourceLockManager() {
             @Override
-            public List<PolicyResourceLockFeatureApi> getImplementers() {
+            protected List<PolicyResourceLockFeatureApi> getImplementers() {
                 return implList;
             }
-        });
-
-        mgr = new PolicyResourceLockManager();
+        };
     }
 
     /**
index 581184e..cd578fc 100644 (file)
@@ -52,11 +52,6 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
      */
     private static final Logger logger = LoggerFactory.getLogger(AggregatedPolicyController.class);
 
-    /**
-     * Used to access various objects.  Can be overridden by junit tests.
-     */
-    private static Factory factory = new Factory();
-
     /**
      * identifier for this policy controller.
      */
@@ -121,14 +116,14 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
 
         // Create/Reuse Readers/Writers for all event sources endpoints
 
-        this.sources = factory.getEndpointManager().addTopicSources(properties);
-        this.sinks = factory.getEndpointManager().addTopicSinks(properties);
+        this.sources = getEndpointManager().addTopicSources(properties);
+        this.sinks = getEndpointManager().addTopicSinks(properties);
 
         initDrools(properties);
         initSinks();
 
         /* persist new properties */
-        factory.getPersistenceManager().storeController(name, properties);
+        getPersistenceManager().storeController(name, properties);
         this.properties = properties;
     }
 
@@ -140,7 +135,7 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
     private void initDrools(Properties properties) {
         try {
             // Register with drools infrastructure
-            this.droolsController = factory.getDroolsFactory().build(properties, sources, sinks);
+            this.droolsController = getDroolsFactory().build(properties, sources, sinks);
         } catch (Exception | LinkageError e) {
             logger.error("{}: cannot init-drools because of {}", this, e.getMessage(), e);
             throw new IllegalArgumentException(e);
@@ -183,7 +178,7 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
             this.properties.setProperty(DroolsProperties.RULES_ARTIFACTID, newDroolsConfiguration.getArtifactId());
             this.properties.setProperty(DroolsProperties.RULES_VERSION, newDroolsConfiguration.getVersion());
 
-            factory.getPersistenceManager().storeController(name, this.properties);
+            getPersistenceManager().storeController(name, this.properties);
 
             this.initDrools(this.properties);
 
@@ -226,7 +221,7 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
     public boolean start() {
         logger.info("{}: start", this);
 
-        for (PolicyControllerFeatureAPI feature : factory.getFeatureProviders()) {
+        for (PolicyControllerFeatureAPI feature : getProviders()) {
             try {
                 if (feature.beforeStart(this)) {
                     return true;
@@ -265,7 +260,7 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
             }
         }
 
-        for (PolicyControllerFeatureAPI feature : factory.getFeatureProviders()) {
+        for (PolicyControllerFeatureAPI feature : getProviders()) {
             try {
                 if (feature.afterStart(this)) {
                     return true;
@@ -286,7 +281,7 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
     public boolean stop() {
         logger.info("{}: stop", this);
 
-        for (PolicyControllerFeatureAPI feature : factory.getFeatureProviders()) {
+        for (PolicyControllerFeatureAPI feature : getProviders()) {
             try {
                 if (feature.beforeStop(this)) {
                     return true;
@@ -315,7 +310,7 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
 
         boolean success = this.droolsController.stop();
 
-        for (PolicyControllerFeatureAPI feature : factory.getFeatureProviders()) {
+        for (PolicyControllerFeatureAPI feature : getProviders()) {
             try {
                 if (feature.afterStop(this)) {
                     return true;
@@ -336,7 +331,7 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
     public void shutdown() {
         logger.info("{}: shutdown", this);
 
-        for (PolicyControllerFeatureAPI feature : factory.getFeatureProviders()) {
+        for (PolicyControllerFeatureAPI feature : getProviders()) {
             try {
                 if (feature.beforeShutdown(this)) {
                     return;
@@ -349,9 +344,9 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
 
         this.stop();
 
-        factory.getDroolsFactory().shutdown(this.droolsController);
+        getDroolsFactory().shutdown(this.droolsController);
 
-        for (PolicyControllerFeatureAPI feature : factory.getFeatureProviders()) {
+        for (PolicyControllerFeatureAPI feature : getProviders()) {
             try {
                 if (feature.afterShutdown(this)) {
                     return;
@@ -370,7 +365,7 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
     public void halt() {
         logger.info("{}: halt", this);
 
-        for (PolicyControllerFeatureAPI feature : factory.getFeatureProviders()) {
+        for (PolicyControllerFeatureAPI feature : getProviders()) {
             try {
                 if (feature.beforeHalt(this)) {
                     return;
@@ -382,10 +377,10 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
         }
 
         this.stop();
-        factory.getDroolsFactory().destroy(this.droolsController);
-        factory.getPersistenceManager().deleteController(this.name);
+        getDroolsFactory().destroy(this.droolsController);
+        getPersistenceManager().deleteController(this.name);
 
-        for (PolicyControllerFeatureAPI feature : factory.getFeatureProviders()) {
+        for (PolicyControllerFeatureAPI feature : getProviders()) {
             try {
                 if (feature.afterHalt(this)) {
                     return;
@@ -405,7 +400,7 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
 
         logger.debug("{}: event offered from {}:{}: {}", this, commType, topic, event);
 
-        for (PolicyControllerFeatureAPI feature : factory.getFeatureProviders()) {
+        for (PolicyControllerFeatureAPI feature : getProviders()) {
             try {
                 if (feature.beforeOffer(this, commType, topic, event)) {
                     return;
@@ -426,7 +421,7 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
 
         boolean success = this.droolsController.offer(topic, event);
 
-        for (PolicyControllerFeatureAPI feature : factory.getFeatureProviders()) {
+        for (PolicyControllerFeatureAPI feature : getProviders()) {
             try {
                 if (feature.afterOffer(this, commType, topic, event, success)) {
                     return;
@@ -446,7 +441,7 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
 
         logger.debug("{}: deliver event to {}:{}: {}", this, commType, topic, event);
 
-        for (PolicyControllerFeatureAPI feature : factory.getFeatureProviders()) {
+        for (PolicyControllerFeatureAPI feature : getProviders()) {
             try {
                 if (feature.beforeDeliver(this, commType, topic, event)) {
                     return true;
@@ -481,7 +476,7 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
 
         boolean success = this.droolsController.deliver(this.topic2Sinks.get(topic), event);
 
-        for (PolicyControllerFeatureAPI feature : factory.getFeatureProviders()) {
+        for (PolicyControllerFeatureAPI feature : getProviders()) {
             try {
                 if (feature.afterDeliver(this, commType, topic, event, success)) {
                     return success;
@@ -510,7 +505,7 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
     public boolean lock() {
         logger.info("{}: lock", this);
 
-        for (PolicyControllerFeatureAPI feature : factory.getFeatureProviders()) {
+        for (PolicyControllerFeatureAPI feature : getProviders()) {
             try {
                 if (feature.beforeLock(this)) {
                     return true;
@@ -534,7 +529,7 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
 
         boolean success = this.droolsController.lock();
 
-        for (PolicyControllerFeatureAPI feature : factory.getFeatureProviders()) {
+        for (PolicyControllerFeatureAPI feature : getProviders()) {
             try {
                 if (feature.afterLock(this)) {
                     return true;
@@ -556,7 +551,7 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
 
         logger.info("{}: unlock", this);
 
-        for (PolicyControllerFeatureAPI feature : factory.getFeatureProviders()) {
+        for (PolicyControllerFeatureAPI feature : getProviders()) {
             try {
                 if (feature.beforeUnlock(this)) {
                     return true;
@@ -577,7 +572,7 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
 
         boolean success = this.droolsController.unlock();
 
-        for (PolicyControllerFeatureAPI feature : factory.getFeatureProviders()) {
+        for (PolicyControllerFeatureAPI feature : getProviders()) {
             try {
                 if (feature.afterUnlock(this)) {
                     return true;
@@ -639,26 +634,22 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
                 + ", locked=" + locked + ", droolsController=" + droolsController + "]";
     }
 
-    /**
-     * Factory to access various objects.  Can be overridden by junit tests.
-     */
-    public static class Factory {
-        
-        public SystemPersistence getPersistenceManager() {
-            return SystemPersistence.manager;
-        }
+    // the following methods may be overridden by junit tests
+    
+    protected SystemPersistence getPersistenceManager() {
+        return SystemPersistence.manager;
+    }
 
-        public TopicEndpoint getEndpointManager() {
-            return TopicEndpoint.manager;
-        }
+    protected TopicEndpoint getEndpointManager() {
+        return TopicEndpoint.manager;
+    }
 
-        public DroolsControllerFactory getDroolsFactory() {
-            return DroolsController.factory;
-        }
+    protected DroolsControllerFactory getDroolsFactory() {
+        return DroolsController.factory;
+    }
 
-        public List<PolicyControllerFeatureAPI> getFeatureProviders() {
-            return PolicyControllerFeatureAPI.providers.getList();
-        }
+    protected List<PolicyControllerFeatureAPI> getProviders() {
+        return PolicyControllerFeatureAPI.providers.getList();
     }
 }
 
index 4f26419..bb944fc 100644 (file)
@@ -37,9 +37,7 @@ import java.util.List;
 import java.util.Properties;
 import java.util.function.BiConsumer;
 import java.util.function.Consumer;
-import org.junit.AfterClass;
 import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.Test;
 import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
 import org.onap.policy.common.endpoints.event.comm.TopicEndpoint;
@@ -50,16 +48,9 @@ import org.onap.policy.drools.controller.DroolsControllerFactory;
 import org.onap.policy.drools.features.PolicyControllerFeatureAPI;
 import org.onap.policy.drools.persistence.SystemPersistence;
 import org.onap.policy.drools.protocol.configuration.DroolsConfiguration;
-import org.onap.policy.drools.system.internal.AggregatedPolicyController.Factory;
-import org.powermock.reflect.Whitebox;
 
 public class AggregatedPolicyControllerTest {
 
-    /**
-     * Name of the "factory" field within the {@link AggregatedPolicyController} class.
-     */
-    private static final String FACTORY_FIELD = "factory";
-
     private static final String AGG_NAME = "agg-name";
     private static final String SINK_TOPIC1 = "sink-a";
     private static final String SINK_TOPIC2 = "sink-b";
@@ -78,10 +69,7 @@ public class AggregatedPolicyControllerTest {
     private static final String GROUP2 = "group-b";
     private static final String VERSION2 = "version-b";
 
-    private static Factory savedFactory;
-
     private Properties properties;
-    private Factory factory;
     private TopicEndpoint endpointMgr;
     private List<TopicSource> sources;
     private TopicSource source1;
@@ -98,16 +86,6 @@ public class AggregatedPolicyControllerTest {
     private PolicyControllerFeatureAPI prov2;
     private AggregatedPolicyController apc;
 
-    @BeforeClass
-    public static void setUpBeforeClass() {
-        savedFactory = Whitebox.getInternalState(AggregatedPolicyController.class, FACTORY_FIELD);
-    }
-
-    @AfterClass
-    public static void tearDownAfterClass() {
-        Whitebox.setInternalState(AggregatedPolicyController.class, FACTORY_FIELD, savedFactory);
-    }
-
     /**
      * Initializes the object to be tested.
      */
@@ -158,26 +136,16 @@ public class AggregatedPolicyControllerTest {
 
         providers = Arrays.asList(prov1, prov2);
 
-        factory = mock(Factory.class);
-        Whitebox.setInternalState(AggregatedPolicyController.class, FACTORY_FIELD, factory);
-
-        when(factory.getEndpointManager()).thenReturn(endpointMgr);
-        when(factory.getPersistenceManager()).thenReturn(persist);
-        when(factory.getDroolsFactory()).thenReturn(droolsFactory);
-        when(factory.getFeatureProviders()).thenReturn(providers);
-
-        apc = new AggregatedPolicyController(AGG_NAME, properties);
+        apc = new AggregatedPolicyControllerImpl(AGG_NAME, properties);
     }
 
     @Test
     public void testFactory() {
-        assertNotNull(savedFactory);
-
-        Factory factory = new Factory();
-        assertNotNull(factory.getDroolsFactory());
-        assertNotNull(factory.getEndpointManager());
-        assertNotNull(factory.getFeatureProviders());
-        assertNotNull(factory.getPersistenceManager());
+        apc = new AggregatedPolicyController(AGG_NAME, properties);
+        assertNotNull(apc.getDroolsFactory());
+        assertNotNull(apc.getEndpointManager());
+        assertNotNull(apc.getProviders());
+        assertNotNull(apc.getPersistenceManager());
     }
 
     @Test
@@ -187,14 +155,22 @@ public class AggregatedPolicyControllerTest {
 
     @Test(expected = IllegalArgumentException.class)
     public void testInitDrools_Ex() {
-        when(factory.getDroolsFactory()).thenThrow(new RuntimeException(EXPECTED));
-        new AggregatedPolicyController(AGG_NAME, properties);
+        new AggregatedPolicyControllerImpl(AGG_NAME, properties) {
+            @Override
+            protected DroolsControllerFactory getDroolsFactory() {
+                throw new RuntimeException(EXPECTED);
+            }            
+        };
     }
 
     @Test(expected = IllegalArgumentException.class)
     public void testInitDrools_Error() {
-        when(factory.getDroolsFactory()).thenThrow(new LinkageError(EXPECTED));
-        new AggregatedPolicyController(AGG_NAME, properties);
+        new AggregatedPolicyControllerImpl(AGG_NAME, properties) {
+            @Override
+            protected DroolsControllerFactory getDroolsFactory() {
+                throw new LinkageError(EXPECTED);
+            }            
+        };
     }
 
     @Test
@@ -945,4 +921,34 @@ public class AggregatedPolicyControllerTest {
         assertThrows(AssertionError.class, () -> verifyAfter.accept(prov1));
         assertThrows(AssertionError.class, () -> verifyAfter.accept(prov2));
     }
+    
+    /**
+     * Controller with overrides.
+     */
+    private class AggregatedPolicyControllerImpl extends AggregatedPolicyController {
+
+        public AggregatedPolicyControllerImpl(String name, Properties properties) {
+            super(name, properties);
+        }
+
+        @Override
+        protected SystemPersistence getPersistenceManager() {
+            return persist;
+        }
+
+        @Override
+        protected TopicEndpoint getEndpointManager() {
+            return endpointMgr;
+        }
+
+        @Override
+        protected DroolsControllerFactory getDroolsFactory() {
+            return droolsFactory;
+        }
+
+        @Override
+        protected List<PolicyControllerFeatureAPI> getProviders() {
+            return providers;
+        }        
+    }
 }