Support multiple Policy/Controller types using 'controller.type' property 26/110126/6
authorStraubs, Ralph (rs8887) <rs8887@att.com>
Mon, 13 Jul 2020 14:26:50 +0000 (10:26 -0400)
committerjhh <jorge.hernandez-herrero@att.com>
Tue, 21 Jul 2020 13:42:21 +0000 (08:42 -0500)
It provides a feature base to allow for custom Policy
and Drools Controllers.

Issue-ID: POLICY-2415
Change-Id: Ibe3f11e3ecd925537ffd03d2420bb3b8214029c9
Signed-off-by: Straubs, Ralph (rs8887) <rs8887@att.com>
Signed-off-by: jhh <jorge.hernandez-herrero@att.com>
policy-core/src/main/java/org/onap/policy/drools/properties/DroolsPropertyConstants.java
policy-management/src/main/java/org/onap/policy/drools/controller/DroolsControllerFactory.java
policy-management/src/main/java/org/onap/policy/drools/controller/IndexedDroolsControllerFactory.java
policy-management/src/main/java/org/onap/policy/drools/features/DroolsControllerFeatureApi.java
policy-management/src/main/java/org/onap/policy/drools/features/PolicyControllerFeatureApi.java
policy-management/src/main/java/org/onap/policy/drools/system/IndexedPolicyControllerFactory.java
policy-management/src/main/java/org/onap/policy/drools/system/internal/AggregatedPolicyController.java
policy-management/src/test/java/org/onap/policy/drools/controller/DroolsControllerFactoryTest.java
policy-management/src/test/java/org/onap/policy/drools/system/PolicyControllerFactoryTest.java
policy-management/src/test/resources/META-INF/services/org.onap.policy.drools.features.DroolsControllerFeatureApi [new file with mode: 0644]
policy-management/src/test/resources/META-INF/services/org.onap.policy.drools.features.PolicyControllerFeatureApi [new file with mode: 0644]

index f14486b..197c972 100644 (file)
@@ -2,7 +2,7 @@
  * ============LICENSE_START=======================================================
  * policy-core
  * ================================================================================
- * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017-2020 AT&T Intellectual Property. All rights reserved.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -26,6 +26,8 @@ public class DroolsPropertyConstants {
 
     public static final String PROPERTY_CONTROLLER_NAME = "controller.name";
 
+    public static final String PROPERTY_CONTROLLER_TYPE = "controller.type";
+
     public static final String DEFAULT_CONTROLLER_POLICY_TYPE_VERSION = "1.0.0";
     public static final String PROPERTY_CONTROLLER_POLICY_TYPES = "controller.policy.types";
 
index 7652a67..a355f6f 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * ============LICENSE_START=======================================================
- * policy-management
+ * ONAP
  * ================================================================================
- * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017-2020 AT&T Intellectual Property. All rights reserved.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -49,6 +49,7 @@ public interface DroolsControllerFactory {
     /**
      * Explicit construction of a Drools Controller.
      *
+     * @param properties properties containing initialization parameters
      * @param groupId maven group id of drools artifact
      * @param artifactId maven artifact id of drools artifact
      * @param version maven version id of drools artifact
@@ -59,7 +60,7 @@ public interface DroolsControllerFactory {
      * @throws IllegalArgumentException with invalid parameters
      * @throws LinkageError Failure to link rules and models in Drools Libraries
      */
-    DroolsController build(String groupId, String artifactId, String version,
+    DroolsController build(Properties properties, String groupId, String artifactId, String version,
         List<TopicCoderFilterConfiguration> decoderConfigurations,
         List<TopicCoderFilterConfiguration> encoderConfigurations) throws LinkageError;
 
index 6d42ba5..e8234a4 100644 (file)
@@ -24,6 +24,7 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Properties;
 import org.onap.policy.common.endpoints.event.comm.Topic;
 import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
@@ -32,6 +33,8 @@ import org.onap.policy.common.endpoints.event.comm.TopicSource;
 import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties;
 import org.onap.policy.drools.controller.internal.MavenDroolsController;
 import org.onap.policy.drools.controller.internal.NullDroolsController;
+import org.onap.policy.drools.features.DroolsControllerFeatureApi;
+import org.onap.policy.drools.features.DroolsControllerFeatureApiConstants;
 import org.onap.policy.drools.properties.DroolsPropertyConstants;
 import org.onap.policy.drools.protocol.coders.JsonProtocolFilter;
 import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration;
@@ -48,12 +51,12 @@ class IndexedDroolsControllerFactory implements DroolsControllerFactory {
     /**
      * logger.
      */
-    private static Logger logger = LoggerFactory.getLogger(IndexedDroolsControllerFactory.class);
+    private static final Logger logger = LoggerFactory.getLogger(IndexedDroolsControllerFactory.class);
 
     /**
      * Policy Controller Name Index.
      */
-    protected HashMap<String, DroolsController> droolsControllers = new HashMap<>();
+    protected Map<String, DroolsController> droolsControllers = new HashMap<>();
 
     /**
      * Null Drools Controller.
@@ -97,11 +100,12 @@ class IndexedDroolsControllerFactory implements DroolsControllerFactory {
         List<TopicCoderFilterConfiguration> topics2DecodedClasses2Filters = codersAndFilters(properties, eventSources);
         List<TopicCoderFilterConfiguration> topics2EncodedClasses2Filters = codersAndFilters(properties, eventSinks);
 
-        return this.build(groupId, artifactId, version, topics2DecodedClasses2Filters, topics2EncodedClasses2Filters);
+        return this.build(properties, groupId, artifactId, version,
+                topics2DecodedClasses2Filters, topics2EncodedClasses2Filters);
     }
 
     @Override
-    public DroolsController build(String newGroupId, String newArtifactId, String newVersion,
+    public DroolsController build(Properties properties, String newGroupId, String newArtifactId, String newVersion,
             List<TopicCoderFilterConfiguration> decoderConfigurations,
             List<TopicCoderFilterConfiguration> encoderConfigurations) throws LinkageError {
 
@@ -148,16 +152,51 @@ class IndexedDroolsControllerFactory implements DroolsControllerFactory {
 
         /* new drools controller */
 
-        DroolsController controller = new MavenDroolsController(newGroupId, newArtifactId, newVersion,
-                decoderConfigurations, encoderConfigurations);
+        DroolsController controller = null;
+        for (DroolsControllerFeatureApi feature: getProviders()) {
+            try {
+                controller = feature.beforeInstance(properties,
+                        newGroupId, newArtifactId, newVersion,
+                        decoderConfigurations, encoderConfigurations);
+                if (controller != null) {
+                    logger.info("feature {} ({}) beforeInstance() has intercepted drools controller {}:{}:{}",
+                            feature.getName(), feature.getSequenceNumber(),
+                            newGroupId, newArtifactId, newVersion);
+                    break;
+                }
+            } catch (RuntimeException r) {
+                logger.error("feature {} ({}) beforeInstance() of drools controller {}:{}:{} failed",
+                        feature.getName(), feature.getSequenceNumber(),
+                        newGroupId, newArtifactId, newVersion, r);
+            }
+        }
+
+        if (controller == null) {
+            controller = new MavenDroolsController(newGroupId, newArtifactId, newVersion, decoderConfigurations,
+                    encoderConfigurations);
+        }
 
         synchronized (this) {
             droolsControllers.put(controllerId, controller);
         }
 
+        for (DroolsControllerFeatureApi feature: getProviders()) {
+            try {
+                feature.afterInstance(controller, properties);
+            } catch (RuntimeException r) {
+                logger.error("feature {} ({}) afterInstance() of drools controller {}:{}:{} failed",
+                        feature.getName(), feature.getSequenceNumber(),
+                        newGroupId, newArtifactId, newVersion, r);
+            }
+        }
+
         return controller;
     }
 
+    protected List<DroolsControllerFeatureApi> getProviders() {
+        return DroolsControllerFeatureApiConstants.getProviders().getList();
+    }
+
     /**
      * find out decoder classes and filters.
      *
index abf524e..bb11bb6 100644 (file)
@@ -2,7 +2,7 @@
  * ============LICENSE_START=======================================================
  * ONAP
  * ================================================================================
- * Copyright (C) 2018-2019 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2018-2020 AT&T Intellectual Property. All rights reserved.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 
 package org.onap.policy.drools.features;
 
+import java.util.List;
+import java.util.Properties;
 import org.onap.policy.common.endpoints.event.comm.TopicSink;
 import org.onap.policy.common.utils.services.OrderedService;
 import org.onap.policy.drools.controller.DroolsController;
+import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration;
 
 /**
  * Drools Controller Feature API.   Hooks into the Drools Controller operations.
  */
 public interface DroolsControllerFeatureApi extends OrderedService {
 
+    /**
+     * intercepts the instantiation of a DroolsController.
+     *
+     * @param properties controller properties
+     * @param groupId group id coordinate
+     * @param artifactId artifact id coordinate
+     * @param version version coordinate
+     * @param decoderConfigurations decoder configurations
+     * @param encoderConfigurations encoder configurations
+     *
+     * @return a Drools Controller or 'null' for no intercept
+     */
+    default DroolsController beforeInstance(Properties properties,
+        String groupId, String artifactId, String version,
+        List<TopicCoderFilterConfiguration> decoderConfigurations,
+        List<TopicCoderFilterConfiguration> encoderConfigurations) {
+        return null;
+    }
+
+    /**
+     * called after a DroolsController is instantiated.
+     *
+     * @param droolsController drools controller
+     * @param properties controller properties
+     *
+     * @return True if this feature intercepts and takes ownership of the operation
+     *         preventing the invocation of lower priority features. False, otherwise
+     */
+    default boolean afterInstance(DroolsController droolsController, Properties properties) {
+        return false;
+    }
+
     /**
      * intercepts before the Drools Controller gives the Policy Container a fact to
      * insert into its Policy Sessions.
index d11863f..f022bf1 100644 (file)
@@ -57,6 +57,32 @@ public interface PolicyControllerFeatureApi extends OrderedService {
         return false;
     }
 
+    /**
+     * called before the actual instantiation of a Policy Controller.
+     *
+     * @param name name of the controller
+     * @param properties configuration parameters in the form of properties
+     *
+     * @return a Policy Controller or 'null for no intercept.
+     */
+    default PolicyController beforeInstance(String name, Properties properties) {
+        return null;
+    }
+
+    /**
+     * called after the Policy Controller is instantiated.
+     *
+     * @param controller policy controller
+     * @param properties configuration parameters in the form of properties
+     *
+     * @return true if this feature intercepts and takes ownership
+     *     of the operation preventing the invocation of
+     *     lower priority features.   False, otherwise.
+     */
+    default boolean afterInstance(PolicyController controller, Properties properties) {
+        return false;
+    }
+
     /**
      * intercept before the Policy Controller is started.
      *
index 6956a45..c03535b 100644 (file)
@@ -24,6 +24,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Properties;
 import org.onap.policy.common.gson.annotation.GsonJsonIgnore;
 import org.onap.policy.drools.controller.DroolsController;
@@ -44,13 +45,13 @@ class IndexedPolicyControllerFactory implements PolicyControllerFactory {
     /**
      * Policy Controller Name Index.
      */
-    private final HashMap<String, PolicyController> policyControllers =
+    private final Map<String, PolicyController> policyControllers =
             new HashMap<>();
 
     /**
      * Group/Artifact Ids Index.
      */
-    private final HashMap<String, PolicyController> coordinates2Controller =
+    private final Map<String, PolicyController> coordinates2Controller =
             new HashMap<>();
 
     /**
@@ -380,7 +381,35 @@ class IndexedPolicyControllerFactory implements PolicyControllerFactory {
     // these methods can be overridden by junit tests
 
     protected PolicyController newPolicyController(String name, Properties properties) {
-        return new AggregatedPolicyController(name, properties);
+        PolicyController controller = null;
+        for (PolicyControllerFeatureApi feature: getProviders()) {
+            try {
+                controller = feature.beforeInstance(name, properties);
+                if (controller != null) {
+                    logger.info("feature {} ({}) beforeInstance() has intercepted controller {}",
+                            feature.getName(), feature.getSequenceNumber(), name);
+                    break;
+                }
+            } catch (RuntimeException r) {
+                logger.error("feature {} ({}) beforeInstance() of controller {} failed",
+                        feature.getName(), feature.getSequenceNumber(), name, r);
+            }
+        }
+
+        if (controller == null) {
+            controller = new AggregatedPolicyController(name, properties);
+        }
+
+        for (PolicyControllerFeatureApi feature: getProviders()) {
+            try {
+                feature.afterInstance(controller, properties);
+            } catch (RuntimeException r) {
+                logger.error("feature {} ({}) afterInstance() of controller {} failed ",
+                        feature.getName(), feature.getSequenceNumber(), name, r);
+            }
+        }
+
+        return controller;
     }
 
     protected List<PolicyControllerFeatureApi> getProviders() {
index 8eb2f85..4e23dab 100644 (file)
@@ -73,12 +73,12 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
     /**
      * Abstracted Event Sources List regardless communication technology.
      */
-    private final List<TopicSource> sources;
+    protected final List<TopicSource> sources;
 
     /**
      * Abstracted Event Sinks List regardless communication technology.
      */
-    private final List<TopicSink> sinks;
+    protected final List<TopicSink> sinks;
 
     /**
      * Mapping topics to sinks.
@@ -102,7 +102,7 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
     /**
      * Policy Drools Controller.
      */
-    private final AtomicReference<DroolsController> droolsController = new AtomicReference<>();
+    protected final AtomicReference<DroolsController> droolsController = new AtomicReference<>();
 
     /**
      * Properties used to initialize controller.
@@ -190,7 +190,7 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
      *
      * @throws IllegalArgumentException if invalid parameters are passed in
      */
-    private void initDrools(Properties properties) {
+    protected void initDrools(Properties properties) {
         try {
             // Register with drools infrastructure
             this.droolsController.set(getDroolsFactory().build(properties, sources, sinks));
index 7733ca1..0330147 100644 (file)
@@ -22,15 +22,26 @@ package org.onap.policy.drools.controller;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.onap.policy.drools.properties.DroolsPropertyConstants.PROPERTY_CONTROLLER_TYPE;
 
 import java.util.List;
 import java.util.Properties;
 import org.junit.Test;
+import org.onap.policy.drools.controller.internal.NullDroolsController;
+import org.onap.policy.drools.features.DroolsControllerFeatureApi;
+import org.onap.policy.drools.properties.DroolsPropertyConstants;
+import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration;
 
 public class DroolsControllerFactoryTest {
 
+    private static final String DROOLS_CONTROLLER_BUILDER_TAG = "DroolsControllerFactoryTest";
+    public static final String TEST_GROUP_ID = "testGroupId";
+    public static final String TEST_ARTIFACT_ID = "testArtifactId";
+    public static final String TEST_VERSION = "testVersion";
+
     @Test
     public void testBuildNullController() {
         Properties droolsProps = new Properties();
@@ -95,6 +106,28 @@ public class DroolsControllerFactoryTest {
         return DroolsControllerConstants.NO_VERSION.equals(droolsController.getVersion());
     }
 
+    @Test
+    public void testControllerType() {
+        DroolsControllerFactory droolsFactory = new IndexedDroolsControllerFactory();
+        Properties props = new Properties();
+
+        // this should build a 'NullDroolsController'
+        DroolsController ctrl1 = droolsFactory.build(props, null, null);
+        assertSame(NullDroolsController.class, ctrl1.getClass());
+
+        props.setProperty(PROPERTY_CONTROLLER_TYPE, DROOLS_CONTROLLER_BUILDER_TAG);
+        props.setProperty(DroolsPropertyConstants.RULES_GROUPID, TEST_GROUP_ID);
+        props.setProperty(DroolsPropertyConstants.RULES_ARTIFACTID, TEST_ARTIFACT_ID);
+        props.setProperty(DroolsPropertyConstants.RULES_VERSION, TEST_VERSION);
+
+        // this should build a 'TestDroolsController'
+        DroolsController ctrl2 = droolsFactory.build(props, null, null);
+        assertSame(TestDroolsController.class, ctrl2.getClass());
+
+        // verify that we can find the controller in the factory table
+        assertSame(ctrl2, droolsFactory.get(ctrl2.getGroupId(), ctrl2.getArtifactId(), null));
+    }
+
     private boolean isActualController(DroolsController droolsController) {
         if (droolsController == null) {
             return false;
@@ -110,4 +143,44 @@ public class DroolsControllerFactoryTest {
 
         return droolsController.getVersion() != null && droolsController.getVersion().substring(0, 1).matches("[0-9]");
     }
+
+    /**
+     * This class provides an alternate DroolsController implementation,
+     * for the purpose of easy identification within a Junit test.
+     */
+    public static class TestDroolsController extends NullDroolsController {
+        @Override
+        public String getGroupId() {
+            return TEST_GROUP_ID;
+        }
+
+        @Override
+        public String getArtifactId() {
+            return TEST_ARTIFACT_ID;
+        }
+    }
+
+    /**
+     * An instance of this class is created by 'IndexedDroolsControllerFactory',
+     * using features. It does the build operation when the value of the
+     * 'controller.type' property matches the value of DROOLS_CONTROLLER_BUILDER_TAG.
+     */
+    public static class DroolsBuilder implements DroolsControllerFeatureApi {
+        @Override
+        public int getSequenceNumber() {
+            return 1;
+        }
+
+        @Override
+        public DroolsController beforeInstance(Properties properties,
+                String groupId, String artifactId, String version,
+                List<TopicCoderFilterConfiguration> decoderConfigurations,
+                List<TopicCoderFilterConfiguration> encoderConfigurations) {
+
+            if (DROOLS_CONTROLLER_BUILDER_TAG.equals(properties.getProperty(PROPERTY_CONTROLLER_TYPE))) {
+                return new TestDroolsController();
+            }
+            return null;
+        }
+    }
 }
index 1c5eb61..818f8fc 100644 (file)
@@ -24,12 +24,14 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
 import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
+import static org.onap.policy.drools.properties.DroolsPropertyConstants.PROPERTY_CONTROLLER_TYPE;
 
 import java.util.Arrays;
 import java.util.Collections;
@@ -39,10 +41,15 @@ import org.junit.Before;
 import org.junit.Test;
 import org.onap.policy.common.utils.gson.GsonTestUtils;
 import org.onap.policy.drools.controller.DroolsController;
+import org.onap.policy.drools.controller.internal.NullDroolsController;
+import org.onap.policy.drools.features.DroolsControllerFeatureApi;
 import org.onap.policy.drools.features.PolicyControllerFeatureApi;
+import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration;
 import org.onap.policy.drools.protocol.configuration.DroolsConfiguration;
+import org.onap.policy.drools.system.internal.AggregatedPolicyController;
 
 public class PolicyControllerFactoryTest {
+    private static final String POLICY_CONTROLLER_BUILDER_TAG = "PolicyControllerFactoryTest";
 
     private static final String MY_NAME = "my-name-a";
     private static final String MY_NAME2 = "my-name-b";
@@ -403,6 +410,30 @@ public class PolicyControllerFactoryTest {
         assertEquals(feature2, ipc.getFeatureProvider(FEATURE2));
     }
 
+    @Test
+    public void testControllerType() {
+        PolicyControllerFactory factory = new IndexedPolicyControllerFactory();
+        Properties props = new Properties();
+
+        // this should build an 'AggregatedPolicyController'
+        final String name1 = "ctrl1";
+        PolicyController ctrl1 = factory.build(name1, props);
+
+        // this should build a 'TestPolicyController'
+        final String name2 = "ctrl2";
+        props.setProperty(PROPERTY_CONTROLLER_TYPE, POLICY_CONTROLLER_BUILDER_TAG);
+        PolicyController ctrl2 = factory.build(name2, props);
+
+        // verify controller types
+        assertSame(AggregatedPolicyController.class, ctrl1.getClass());
+        assertSame(TestPolicyController.class, ctrl2.getClass());
+        assertSame(NullDroolsController.class, ctrl2.getDrools().getClass());
+
+        // verify controller lookups
+        assertSame(ctrl1, factory.get(name1));
+        assertSame(ctrl2, factory.get(name2));
+    }
+
     /**
      * Factory with overrides.
      */
@@ -427,4 +458,58 @@ public class PolicyControllerFactoryTest {
             return providers;
         }
     }
+
+    /**
+     * This class provides an alternate PolicyController implementation,
+     * for the purpose of easy identification within a junit test.
+     */
+    public static class TestPolicyController extends AggregatedPolicyController {
+        public TestPolicyController(String name, Properties properties) {
+            super(name, properties);
+        }
+    }
+
+    /**
+     * An instance of this class is created by 'IndexedPolicyControllerFactory',
+     * using features. It does the build operation when the value of the
+     * 'controller.type' property matches the value of POLICY_CONTROLLER_BUILDER_TAG.
+     */
+    public static class PolicyBuilder implements PolicyControllerFeatureApi {
+        @Override
+        public int getSequenceNumber() {
+            return 1;
+        }
+
+        @Override
+        public PolicyController beforeInstance(String name, Properties properties) {
+            if (POLICY_CONTROLLER_BUILDER_TAG.equals(properties.getProperty(PROPERTY_CONTROLLER_TYPE))) {
+                return new TestPolicyController(name, properties);
+            }
+            return null;
+        }
+    }
+
+    /**
+     * An instance of this class is created by 'IndexedDroolsControllerFactory',
+     * using features. It does the build operation when the value of the
+     * 'controller.type' property matches the value of POLICY_CONTROLLER_BUILDER_TAG.
+     */
+    public static class DroolsBuilder implements DroolsControllerFeatureApi {
+        @Override
+        public int getSequenceNumber() {
+            return 1;
+        }
+
+        @Override
+        public DroolsController beforeInstance(Properties properties,
+                String groupId, String artifactId, String version,
+                List<TopicCoderFilterConfiguration> decoderConfigurations,
+                List<TopicCoderFilterConfiguration> encoderConfigurations) {
+
+            if (POLICY_CONTROLLER_BUILDER_TAG.equals(properties.getProperty(PROPERTY_CONTROLLER_TYPE))) {
+                return new NullDroolsController();
+            }
+            return null;
+        }
+    }
 }
diff --git a/policy-management/src/test/resources/META-INF/services/org.onap.policy.drools.features.DroolsControllerFeatureApi b/policy-management/src/test/resources/META-INF/services/org.onap.policy.drools.features.DroolsControllerFeatureApi
new file mode 100644 (file)
index 0000000..3c765a7
--- /dev/null
@@ -0,0 +1,2 @@
+org.onap.policy.drools.controller.DroolsControllerFactoryTest$DroolsBuilder
+org.onap.policy.drools.system.PolicyControllerFactoryTest$DroolsBuilder
diff --git a/policy-management/src/test/resources/META-INF/services/org.onap.policy.drools.features.PolicyControllerFeatureApi b/policy-management/src/test/resources/META-INF/services/org.onap.policy.drools.features.PolicyControllerFeatureApi
new file mode 100644 (file)
index 0000000..2a4408a
--- /dev/null
@@ -0,0 +1 @@
+org.onap.policy.drools.system.PolicyControllerFactoryTest$PolicyBuilder