Resolve mapping between TOSCA policies and APEX policy models

Change-Id: Ifaedc5074bcc51a5d495e342feae89b6a2aac1cf
Issue-ID: POLICY-1626
Signed-off-by: a.sreekumar <ajith.sreekumar@est.tech>
diff --git a/services/services-engine/pom.xml b/services/services-engine/pom.xml
index 0fafa09..a4a8776 100644
--- a/services/services-engine/pom.xml
+++ b/services/services-engine/pom.xml
@@ -63,6 +63,17 @@
             <artifactId>mockito-all</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.onap.policy.models</groupId>
+            <artifactId>policy-models-pdp</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>javax.ws.rs</groupId>
+                    <artifactId>javax.ws.rs-api</artifactId>
+                </exclusion>
+            </exclusions>
+            <version>${version.policy.models}</version>
+        </dependency>
     </dependencies>
 
     <build>
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/main/ApexActivator.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/main/ApexActivator.java
index 3aa1f17..2c3fac1 100644
--- a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/main/ApexActivator.java
+++ b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/main/ApexActivator.java
@@ -24,17 +24,24 @@
 import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Map.Entry;
-
+import java.util.stream.Stream;
+import lombok.Getter;
 import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
+import org.onap.policy.apex.model.basicmodel.handling.ApexModelException;
 import org.onap.policy.apex.model.basicmodel.service.ModelService;
+import org.onap.policy.apex.model.policymodel.concepts.AxPolicyModel;
+import org.onap.policy.apex.model.policymodel.handling.PolicyModelMerger;
 import org.onap.policy.apex.model.utilities.TextFileUtils;
 import org.onap.policy.apex.service.engine.engdep.EngDepMessagingService;
+import org.onap.policy.apex.service.engine.event.ApexEventException;
 import org.onap.policy.apex.service.engine.runtime.EngineService;
 import org.onap.policy.apex.service.engine.runtime.impl.EngineServiceImpl;
 import org.onap.policy.apex.service.parameters.ApexParameters;
+import org.onap.policy.apex.service.parameters.engineservice.EngineServiceParameters;
 import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerParameters;
 import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerPeeredMode;
 import org.onap.policy.common.parameters.ParameterService;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifier;
 import org.slf4j.ext.XLogger;
 import org.slf4j.ext.XLoggerFactory;
 
@@ -45,11 +52,14 @@
  * @author Liam Fallon (liam.fallon@ericsson.com)
  */
 public class ApexActivator {
+    private static final String APEX_ENGINE_FAILED_MSG = "Apex engine failed to start as a service";
+
     // The logger for this class
     private static final XLogger LOGGER = XLoggerFactory.getXLogger(ApexActivator.class);
 
-    // The parameters of this Apex activator
-    private final ApexParameters apexParameters;
+    // The parameters of the Apex activator when running with multiple policies
+    @Getter
+    private Map<ToscaPolicyIdentifier, ApexParameters> apexParametersMap;
 
     // Event unmarshalers are used to receive events asynchronously into Apex
     private final Map<String, ApexEventUnmarshaller> unmarshallerMap = new LinkedHashMap<>();
@@ -62,13 +72,16 @@
     // and synchronous events from the engine.
     private ApexEngineServiceHandler engineServiceHandler = null;
 
+    // The engine service
+    private EngineService apexEngineService;
+
     /**
      * Instantiate the activator for the Apex engine as a complete service.
      *
-     * @param parameters the apex parameters for the Apex service
+     * @param parametersMap the apex parameters map for the Apex service
      */
-    public ApexActivator(final ApexParameters parameters) {
-        apexParameters = parameters;
+    public ApexActivator(Map<ToscaPolicyIdentifier, ApexParameters> parametersMap) {
+        apexParametersMap = parametersMap;
     }
 
     /**
@@ -80,73 +93,130 @@
         LOGGER.debug("Apex engine starting as a service . . .");
 
         try {
-            // Create engine with specified thread count
-            LOGGER.debug("starting apex engine service . . .");
-            final EngineService apexEngineService =
-                    EngineServiceImpl.create(apexParameters.getEngineServiceParameters());
+            ApexParameters apexParameters = apexParametersMap.values().iterator().next();
+            // totalInstanceCount is the sum of instance counts required as per each policy
+            int totalInstanceCount = apexParametersMap.values().stream()
+                .mapToInt(p -> p.getEngineServiceParameters().getInstanceCount()).sum();
+            apexParameters.getEngineServiceParameters().setInstanceCount(totalInstanceCount);
+            instantiateEngine(apexParameters);
+            Map<ToscaPolicyIdentifier, AxPolicyModel> policyModelsMap = new LinkedHashMap<>();
+            Map<String, EventHandlerParameters> inputParametersMap = new LinkedHashMap<>();
+            Map<String, EventHandlerParameters> outputParametersMap = new LinkedHashMap<>();
 
-            // Instantiate and start the messaging service for Deployment
-            LOGGER.debug("starting apex deployment service . . .");
-            final EngDepMessagingService engDepService = new EngDepMessagingService(apexEngineService,
-                    apexParameters.getEngineServiceParameters().getDeploymentPort());
-            engDepService.start();
-
-            // Create the engine holder to hold the engine's references and act as an event receiver
-            engineServiceHandler = new ApexEngineServiceHandler(apexEngineService, engDepService);
-
-            // Check if a policy model file has been specified
-            if (apexParameters.getEngineServiceParameters().getPolicyModelFileName() != null) {
-                LOGGER.debug("deploying policy model in \""
-                        + apexParameters.getEngineServiceParameters().getPolicyModelFileName()
+            for (Entry<ToscaPolicyIdentifier, ApexParameters> apexParamsEntry : apexParametersMap.entrySet()) {
+                ApexParameters apexParams = apexParamsEntry.getValue();
+                boolean duplicateInputParameterExist =
+                    apexParams.getEventInputParameters().keySet().stream().anyMatch(inputParametersMap::containsKey);
+                boolean duplicateOutputParameterExist =
+                    apexParams.getEventOutputParameters().keySet().stream().anyMatch(outputParametersMap::containsKey);
+                if (duplicateInputParameterExist || duplicateOutputParameterExist) {
+                    LOGGER.error("I/O Parameters for " + apexParamsEntry.getKey().getName() + ":"
+                        + apexParamsEntry.getKey().getVersion()
+                        + " has duplicates. So this policy is not executed");
+                    apexParametersMap.remove(apexParamsEntry.getKey());
+                    continue;
+                } else {
+                    inputParametersMap.putAll(apexParams.getEventInputParameters());
+                    outputParametersMap.putAll(apexParams.getEventOutputParameters());
+                }
+                // Check if a policy model file has been specified
+                if (apexParams.getEngineServiceParameters().getPolicyModelFileName() != null) {
+                    LOGGER.debug("deploying policy model in \""
+                        + apexParams.getEngineServiceParameters().getPolicyModelFileName()
                         + "\" to the apex engines . . .");
 
-                // Set the policy model in the engine
-                final String policyModelString = TextFileUtils
-                        .getTextFileAsString(apexParameters.getEngineServiceParameters().getPolicyModelFileName());
-                apexEngineService.updateModel(apexParameters.getEngineServiceParameters().getEngineKey(),
-                        policyModelString, true);
+                    final String policyModelString = TextFileUtils
+                        .getTextFileAsString(apexParams.getEngineServiceParameters().getPolicyModelFileName());
+                    AxPolicyModel policyModel = EngineServiceImpl
+                        .createModel(apexParams.getEngineServiceParameters().getEngineKey(), policyModelString);
+                    policyModelsMap.put(apexParamsEntry.getKey(), policyModel);
+                }
             }
-
-            // Producer parameters specify what event marshalers to handle events leaving Apex are
-            // set up and how they are set up
-            for (final Entry<String, EventHandlerParameters> outputParameters : apexParameters
-                    .getEventOutputParameters().entrySet()) {
-                final ApexEventMarshaller marshaller = new ApexEventMarshaller(outputParameters.getKey(),
-                        apexParameters.getEngineServiceParameters(), outputParameters.getValue());
-                marshaller.init();
-                apexEngineService.registerActionListener(outputParameters.getKey(), marshaller);
-                marshallerMap.put(outputParameters.getKey(), marshaller);
-            }
-
-            // Consumer parameters specify what event unmarshalers to handle events coming into Apex
-            // are set up and how they are set up
-            for (final Entry<String, EventHandlerParameters> inputParameters : apexParameters.getEventInputParameters()
-                    .entrySet()) {
-                final ApexEventUnmarshaller unmarshaller = new ApexEventUnmarshaller(inputParameters.getKey(),
-                        apexParameters.getEngineServiceParameters(), inputParameters.getValue());
-                unmarshallerMap.put(inputParameters.getKey(), unmarshaller);
-                unmarshaller.init(engineServiceHandler);
-            }
-
-            setUpmarshalerPairings();
+            AxPolicyModel finalPolicyModel = aggregatePolicyModels(policyModelsMap);
+            // Set the policy model in the engine
+            apexEngineService.updateModel(apexParameters.getEngineServiceParameters().getEngineKey(),
+                finalPolicyModel, true);
+            setUpMarshallerAndUnmarshaller(apexParameters.getEngineServiceParameters(), inputParametersMap,
+                outputParametersMap);
+            setUpmarshalerPairings(inputParametersMap);
         } catch (final Exception e) {
-            LOGGER.debug("Apex engine failed to start as a service", e);
-            throw new ApexActivatorException("Apex engine failed to start as a service", e);
+            LOGGER.debug(APEX_ENGINE_FAILED_MSG, e);
+            throw new ApexActivatorException(APEX_ENGINE_FAILED_MSG, e);
         }
 
         LOGGER.debug("Apex engine started as a service");
     }
 
+    private AxPolicyModel aggregatePolicyModels(Map<ToscaPolicyIdentifier, AxPolicyModel> policyModelsMap) {
+        Map.Entry<ToscaPolicyIdentifier, AxPolicyModel> firstEntry = policyModelsMap.entrySet().iterator().next();
+        Stream<Entry<ToscaPolicyIdentifier, AxPolicyModel>> policyModelStream =
+            policyModelsMap.entrySet().stream().skip(1);
+        Entry<ToscaPolicyIdentifier, AxPolicyModel> finalPolicyModelEntry =
+            policyModelStream.reduce(firstEntry, ((entry1, entry2) -> {
+                try {
+                    entry1.setValue(
+                        PolicyModelMerger.getMergedPolicyModel(entry1.getValue(), entry2.getValue(), true, true));
+                } catch (ApexModelException exc) {
+                    LOGGER.error("Policy model for " + entry2.getKey().getName() + ":" + entry2.getKey().getVersion()
+                        + " is having duplicates. So this policy is not executed", exc.getMessage());
+                    apexParametersMap.remove(entry2.getKey());
+                }
+                return entry1;
+            }));
+        return finalPolicyModelEntry.getValue();
+    }
+
+    private void setUpMarshallerAndUnmarshaller(EngineServiceParameters engineServiceParameters,
+        Map<String, EventHandlerParameters> inputParametersMap, Map<String, EventHandlerParameters> outputParametersMap)
+        throws ApexEventException {
+        // Producer parameters specify what event marshalers to handle events leaving Apex are
+        // set up and how they are set up
+        for (Entry<String, EventHandlerParameters> outputParameters : outputParametersMap.entrySet()) {
+            final ApexEventMarshaller marshaller = new ApexEventMarshaller(outputParameters.getKey(),
+                engineServiceParameters, outputParameters.getValue());
+            marshaller.init();
+            apexEngineService.registerActionListener(outputParameters.getKey(), marshaller);
+            marshallerMap.put(outputParameters.getKey(), marshaller);
+        }
+        // Consumer parameters specify what event unmarshalers to handle events coming into Apex
+        // are set up and how they are set up
+        for (final Entry<String, EventHandlerParameters> inputParameters : inputParametersMap.entrySet()) {
+            final ApexEventUnmarshaller unmarshaller = new ApexEventUnmarshaller(inputParameters.getKey(),
+                engineServiceParameters, inputParameters.getValue());
+            unmarshallerMap.put(inputParameters.getKey(), unmarshaller);
+            unmarshaller.init(engineServiceHandler);
+        }
+    }
+
+    private void instantiateEngine(ApexParameters apexParameters) throws ApexException {
+        if (null != apexEngineService
+            && apexEngineService.getKey().equals(apexParameters.getEngineServiceParameters().getEngineKey())) {
+            throw new ApexException("Apex Engine already initialized.");
+        }
+        // Create engine with specified thread count
+        LOGGER.debug("starting apex engine service . . .");
+        apexEngineService = EngineServiceImpl.create(apexParameters.getEngineServiceParameters());
+
+        // Instantiate and start the messaging service for Deployment
+        LOGGER.debug("starting apex deployment service . . .");
+        final EngDepMessagingService engDepService = new EngDepMessagingService(apexEngineService,
+                apexParameters.getEngineServiceParameters().getDeploymentPort());
+        engDepService.start();
+
+        // Create the engine holder to hold the engine's references and act as an event receiver
+        engineServiceHandler = new ApexEngineServiceHandler(apexEngineService, engDepService);
+    }
+
     /**
      * Set up unmarshaler/marshaler pairing for synchronized event handling. We only need to
      * traverse the unmarshalers because the
      * unmarshalers and marshalers are paired one to one uniquely so if we find a
      * synchronized unmarshaler we'll also find its
      * paired marshaler
+     * @param inputParametersMap the apex parameters
      */
-    private void setUpmarshalerPairings() {
-        for (final Entry<String, EventHandlerParameters> inputParameters : apexParameters.getEventInputParameters()
-                .entrySet()) {
+    private void setUpmarshalerPairings(Map<String, EventHandlerParameters> inputParametersMap) {
+        for (final Entry<String, EventHandlerParameters> inputParameters : inputParametersMap.entrySet()) {
             final ApexEventUnmarshaller unmarshaller = unmarshallerMap.get(inputParameters.getKey());
 
             // Pair up peered unmarshalers and marshalers
@@ -193,13 +263,4 @@
         ModelService.clear();
         ParameterService.clear();
     }
-
-    /**
-     * Get the parameters used by the adapter.
-     *
-     * @return the parameters of the adapter
-     */
-    public ApexParameters getApexParameters() {
-        return apexParameters;
-    }
 }
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/main/ApexMain.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/main/ApexMain.java
index 3bf842c..4600690 100644
--- a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/main/ApexMain.java
+++ b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/main/ApexMain.java
@@ -23,6 +23,8 @@
 
 import java.util.Arrays;
 import java.util.Base64;
+import java.util.LinkedHashMap;
+import java.util.Map;
 import java.util.Map.Entry;
 import lombok.Getter;
 import lombok.Setter;
@@ -30,6 +32,7 @@
 import org.onap.policy.apex.service.parameters.ApexParameterHandler;
 import org.onap.policy.apex.service.parameters.ApexParameters;
 import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerParameters;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifier;
 import org.slf4j.ext.XLogger;
 import org.slf4j.ext.XLoggerFactory;
 
@@ -39,13 +42,16 @@
  * @author Liam Fallon (liam.fallon@ericsson.com)
  */
 public class ApexMain {
+    private static final String APEX_SERVICE_FAILED_MSG = "start of Apex service failed";
+
     private static final XLogger LOGGER = XLoggerFactory.getXLogger(ApexMain.class);
 
     // The Apex Activator that activates the Apex engine
     private ApexActivator activator;
 
-    // The parameters read in from JSON
-    private ApexParameters parameters;
+    // The parameters read in from JSON for each policy
+    @Getter
+    private Map<ToscaPolicyIdentifier, ApexParameters> apexParametersMap;
 
     @Getter
     @Setter(lombok.AccessLevel.PRIVATE)
@@ -54,55 +60,20 @@
     /**
      * Instantiates the Apex service.
      *
-     * @param args the commaind line arguments
+     * @param args the command line arguments
      */
     public ApexMain(final String[] args) {
         LOGGER.entry("Starting Apex service with parameters " + Arrays.toString(args) + " . . .");
-
-        // Check the arguments
-        final ApexCommandLineArguments arguments = new ApexCommandLineArguments();
+        apexParametersMap = new LinkedHashMap<>();
         try {
-            // The arguments return a string if there is a message to print and we should exit
-            final String argumentMessage = arguments.parse(args);
-            if (argumentMessage != null) {
-                LOGGER.info(argumentMessage);
-                return;
-            }
-
-            // Validate that the arguments are sane
-            arguments.validate();
-        } catch (final ApexException e) {
-            LOGGER.error("start of Apex service failed", e);
+            apexParametersMap.put(new ToscaPolicyIdentifier(), populateApexParameters(args));
+        } catch (ApexException e) {
+            LOGGER.error(APEX_SERVICE_FAILED_MSG, e);
             return;
         }
 
-        // Read the parameters
-        try {
-            parameters = new ApexParameterHandler().getParameters(arguments);
-        } catch (final Exception e) {
-            LOGGER.error("start of Apex service failed", e);
-            return;
-        }
-
-        // Set incoming Java properties
-        setJavaProperties(parameters);
-
-        // Set the name of the event handler parameters for producers and consumers
-        for (final Entry<String, EventHandlerParameters> ehParameterEntry : parameters.getEventOutputParameters()
-            .entrySet()) {
-            if (!ehParameterEntry.getValue().checkSetName()) {
-                ehParameterEntry.getValue().setName(ehParameterEntry.getKey());
-            }
-        }
-        for (final Entry<String, EventHandlerParameters> ehParameterEntry : parameters.getEventInputParameters()
-            .entrySet()) {
-            if (!ehParameterEntry.getValue().checkSetName()) {
-                ehParameterEntry.getValue().setName(ehParameterEntry.getKey());
-            }
-        }
-
         // Now, create the activator for the Apex service
-        activator = new ApexActivator(parameters);
+        activator = new ApexActivator(apexParametersMap);
 
         // Start the activator
         try {
@@ -119,12 +90,92 @@
     }
 
     /**
-     * Get the parameters specified in JSON.
+     * Instantiates the Apex service for multiple policies.
      *
-     * @return the parameters
+     * @param policyArgumentsMap the map with command line arguments as value and policy-id as key
+     * @throws ApexException on errors
      */
-    public ApexParameters getParameters() {
-        return parameters;
+    public ApexMain(Map<ToscaPolicyIdentifier, String[]> policyArgumentsMap) throws ApexException {
+        apexParametersMap = new LinkedHashMap<>();
+        for ( Entry<ToscaPolicyIdentifier, String[]> policyArgsEntry: policyArgumentsMap.entrySet()) {
+            try {
+                apexParametersMap.put(policyArgsEntry.getKey(), populateApexParameters(policyArgsEntry.getValue()));
+            } catch (ApexException e) {
+                LOGGER.error("Invalid arguments specified for policy - " + policyArgsEntry.getKey().getName() + ":"
+                    + policyArgsEntry.getKey().getVersion(), e);
+            }
+        }
+        if (apexParametersMap.isEmpty()) {
+            LOGGER.error(APEX_SERVICE_FAILED_MSG);
+            return;
+        }
+        // Now, create the activator for the Apex service
+        activator = new ApexActivator(apexParametersMap);
+
+        // Start the activator
+        try {
+            activator.initialize();
+            apexParametersMap = activator.getApexParametersMap();
+            setAlive(true);
+        } catch (final ApexActivatorException e) {
+            LOGGER.error(APEX_SERVICE_FAILED_MSG, e);
+            activator.terminate();
+            return;
+        }
+
+        // Add a shutdown hook to shut everything down in an orderly manner
+        Runtime.getRuntime().addShutdownHook(new ApexMainShutdownHookClass());
+        LOGGER.exit("Started Apex");
+    }
+
+    private ApexParameters populateApexParameters(String[] args) throws ApexException {
+        // Check the arguments
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments();
+        try {
+            // The arguments return a string if there is a message to print and we should exit
+            final String argumentMessage = arguments.parse(args);
+            if (argumentMessage != null) {
+                LOGGER.info(argumentMessage);
+                throw new ApexException(argumentMessage);
+            }
+
+            // Validate that the arguments are sane
+            arguments.validate();
+        } catch (final ApexException e) {
+            LOGGER.error("Arguments validation failed.", e);
+            throw new ApexException("Arguments validation failed.", e);
+        }
+
+        ApexParameters axParameters;
+        // Read the parameters
+        try {
+            ApexParameterHandler apexParameterHandler = new ApexParameterHandler();
+            // In case of multiple policies received from PAP, do not clear ParameterService if parameters of one policy
+            // already registered
+            apexParameterHandler.setKeepParameterServiceFlag(null != apexParametersMap && !apexParametersMap.isEmpty());
+            axParameters = apexParameterHandler.getParameters(arguments);
+        } catch (final Exception e) {
+            LOGGER.error("Cannot create APEX Parameters from the arguments provided.", e);
+            throw new ApexException("Cannot create APEX Parameters from the arguments provided.", e);
+        }
+
+        // Set incoming Java properties
+        setJavaProperties(axParameters);
+
+        // Set the name of the event handler parameters for producers and consumers
+        for (final Entry<String, EventHandlerParameters> ehParameterEntry : axParameters.getEventOutputParameters()
+            .entrySet()) {
+            if (!ehParameterEntry.getValue().checkSetName()) {
+                ehParameterEntry.getValue().setName(ehParameterEntry.getKey());
+            }
+        }
+        for (final Entry<String, EventHandlerParameters> ehParameterEntry : axParameters.getEventInputParameters()
+            .entrySet()) {
+            if (!ehParameterEntry.getValue().checkSetName()) {
+                ehParameterEntry.getValue().setName(ehParameterEntry.getKey());
+            }
+        }
+        return axParameters;
     }
 
     /**
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/runtime/impl/EngineServiceImpl.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/runtime/impl/EngineServiceImpl.java
index e9edd40..1524257 100644
--- a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/runtime/impl/EngineServiceImpl.java
+++ b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/runtime/impl/EngineServiceImpl.java
@@ -1,19 +1,20 @@
 /*-
  * ============LICENSE_START=======================================================
  *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
+ *  Modifications Copyright (C) 2019 Nordix Foundation.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *      http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
- * 
+ *
  * SPDX-License-Identifier: Apache-2.0
  * ============LICENSE_END=========================================================
  */
@@ -28,7 +29,6 @@
 import java.util.Map.Entry;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.LinkedBlockingQueue;
-
 import org.onap.policy.apex.context.ContextException;
 import org.onap.policy.apex.core.infrastructure.threading.ApplicationThreadFactory;
 import org.onap.policy.apex.core.infrastructure.threading.ThreadUtilities;
@@ -134,13 +134,13 @@
             LOGGER.warn("Engine service configuration parameters is null");
             throw new ApexException("engine service configuration parameters are null");
         }
-        
+
         final GroupValidationResult validation = config.validate();
         if (!validation.isValid()) {
             LOGGER.warn("Invalid engine service configuration parameters: {}" + validation.getResult());
             throw new ApexException("Invalid engine service configuration parameters: " + validation);
         }
-        
+
         final AxArtifactKey engineServiceKey = config.getEngineKey();
         final int threadCount = config.getInstanceCount();
 
@@ -235,6 +235,24 @@
     @Override
     public void updateModel(final AxArtifactKey incomingEngineServiceKey, final String apexModelString,
                     final boolean forceFlag) throws ApexException {
+        AxPolicyModel apexPolicyModel = createModel(incomingEngineServiceKey, apexModelString);
+
+        // Update the model
+        updateModel(incomingEngineServiceKey, apexPolicyModel, forceFlag);
+
+        LOGGER.exit();
+    }
+
+    /**
+    * Method to create model.
+    *
+    * @param incomingEngineServiceKey incoming engine service key
+    * @param apexModelString apex model string
+    * @return apexPolicyModel the policy model
+    * @throws ApexException apex exception
+    */
+    public static AxPolicyModel createModel(final AxArtifactKey incomingEngineServiceKey, final String apexModelString)
+        throws ApexException {
         // Check if the engine service key specified is sane
         if (incomingEngineServiceKey == null) {
             String message = ENGINE_KEY_NOT_SPECIFIED;
@@ -260,11 +278,7 @@
             LOGGER.error(message, e);
             throw new ApexException(message, e);
         }
-
-        // Update the model
-        updateModel(incomingEngineServiceKey, apexPolicyModel, forceFlag);
-
-        LOGGER.exit();
+        return apexPolicyModel;
     }
 
     /**
@@ -314,7 +328,7 @@
 
     /**
      * Execute the model update on the engine instances.
-     * 
+     *
      * @param incomingEngineServiceKey the engine service key to update
      * @param apexModel the model to update the engines with
      * @param forceFlag if true, ignore compatibility problems
@@ -322,7 +336,7 @@
      */
     private void executeModelUpdate(final AxArtifactKey incomingEngineServiceKey, final AxPolicyModel apexModel,
                     final boolean forceFlag) throws ApexException {
-        
+
         if (!isStopped()) {
             stopEngines(incomingEngineServiceKey);
         }
@@ -458,7 +472,7 @@
 
         // Start the engine
         engineWorkerMap.get(engineKey).start(engineKey);
-        
+
         // Check if periodic events should be turned on
         if (periodicEventPeriod > 0) {
             startPeriodicEvents(periodicEventPeriod);
@@ -478,7 +492,7 @@
             periodicEventGenerator.cancel();
             periodicEventGenerator = null;
         }
-        
+
         // Stop each engine
         for (final EngineService engine : engineWorkerMap.values()) {
             if (engine.getState() != AxEngineState.STOPPED) {
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/ApexParameterHandler.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/ApexParameterHandler.java
index 4312793..c1ef50b 100644
--- a/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/ApexParameterHandler.java
+++ b/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/ApexParameterHandler.java
@@ -1,6 +1,7 @@
 /*-
  * ============LICENSE_START=======================================================
  *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
+ *  Modifications Copyright (C) 2019 Nordix Foundation.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -22,9 +23,8 @@
 
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
-
 import java.io.FileReader;
-
+import lombok.Setter;
 import org.onap.policy.apex.core.engine.EngineParameters;
 import org.onap.policy.apex.service.engine.main.ApexCommandLineArguments;
 import org.onap.policy.apex.service.parameters.carriertechnology.CarrierTechnologyParameters;
@@ -46,6 +46,9 @@
 public class ApexParameterHandler {
     private static final XLogger LOGGER = XLoggerFactory.getXLogger(ApexParameterHandler.class);
 
+    @Setter
+    private boolean keepParameterServiceFlag;
+
     /**
      * Read the parameters from the parameter file.
      *
@@ -54,8 +57,11 @@
      * @throws ParameterException on parameter exceptions
      */
     public ApexParameters getParameters(final ApexCommandLineArguments arguments) throws ParameterException {
-        // Clear all existing parameters
-        ParameterService.clear();
+        // when populating parameters for multiple policies, do not clear the ParameterService already registered
+        // otherwise clear all existing parameters
+        if (!keepParameterServiceFlag) {
+            ParameterService.clear();
+        }
 
         ApexParameters parameters = null;
 
@@ -112,8 +118,12 @@
             LOGGER.info(returnMessage);
         }
 
-        // Register the parameters with the parameter service
-        registerParameters(parameters);
+        // engine parameters in multiple policies are expected to be same.
+        // no need to do registration if already registered
+        if (!keepParameterServiceFlag) {
+            // Register the parameters with the parameter service
+            registerParameters(parameters);
+        }
 
         return parameters;
     }
diff --git a/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/main/ApexMainTest.java b/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/main/ApexMainTest.java
index 6ed3c75..86ae99e 100644
--- a/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/main/ApexMainTest.java
+++ b/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/main/ApexMainTest.java
@@ -5,15 +5,15 @@
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *      http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
- * 
+ *
  * SPDX-License-Identifier: Apache-2.0
  * ============LICENSE_END=========================================================
  */
@@ -26,10 +26,14 @@
 import java.io.ByteArrayOutputStream;
 import java.io.OutputStream;
 import java.io.PrintStream;
-
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.After;
 import org.junit.Test;
 import org.onap.policy.apex.core.infrastructure.threading.ThreadUtilities;
 import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
+import org.onap.policy.apex.service.parameters.ApexParameters;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifier;
 
 /**
  * Test the ApexMain class.
@@ -37,6 +41,16 @@
 public class ApexMainTest {
     private PrintStream stdout = System.out;
 
+    /**
+     * Method for cleanup after each test.
+     *
+     * @throws Exception if an error occurs
+     */
+    @After
+    public void teardown() throws Exception {
+        System.setOut(stdout);
+    }
+
     @Test
     public void testNullParameters() throws ApexException {
         OutputStream outContent = new ByteArrayOutputStream();
@@ -47,8 +61,6 @@
 
         final String outString = outContent.toString();
 
-        System.setOut(stdout);
-
         assertTrue(outString.contains("Apex configuration file was not specified as an argument"));
     }
 
@@ -65,8 +77,6 @@
 
         final String outString = outContent.toString();
 
-        System.setOut(stdout);
-
         assertTrue(outString.contains("invalid command line arguments specified : Unrecognized option: -whee"));
     }
 
@@ -83,8 +93,6 @@
 
         final String outString = outContent.toString();
 
-        System.setOut(stdout);
-
         assertTrue(outString.contains("usage: org.onap.policy.apex.service.engine.main.ApexMain [options...]"));
     }
 
@@ -101,8 +109,6 @@
 
         final String outString = outContent.toString();
 
-        System.setOut(stdout);
-
         assertTrue(outString.contains("parameter group has status INVALID"));
     }
 
@@ -114,14 +120,13 @@
         String[] args = { "-c", "src/test/resources/parameters/correctParams.json" };
 
         final ApexMain apexMain = new ApexMain(args);
-        assertEquals("MyApexEngine", apexMain.getParameters().getEngineServiceParameters().getName());
+        assertEquals("MyApexEngine",
+            apexMain.getApexParametersMap().values().iterator().next().getEngineServiceParameters().getName());
         ThreadUtilities.sleep(200);
         apexMain.shutdown();
 
         final String outString = outContent.toString();
 
-        System.setOut(stdout);
-
         assertTrue(outString.contains("Added the action listener to the engine"));
     }
 
@@ -133,7 +138,8 @@
         String[] args = { "-c", "src/test/resources/parameters/correctParamsJavaProperties.json" };
 
         final ApexMain apexMain = new ApexMain(args);
-        assertEquals("MyApexEngine", apexMain.getParameters().getEngineServiceParameters().getName());
+        assertEquals("MyApexEngine",
+            apexMain.getApexParametersMap().values().iterator().next().getEngineServiceParameters().getName());
 
         assertEquals("trust-store-file", System.getProperty("javax.net.ssl.trustStore"));
         assertEquals("Pol1cy_0nap", System.getProperty("javax.net.ssl.trustStorePassword"));
@@ -143,8 +149,55 @@
         ThreadUtilities.sleep(10000);
         final String outString = outContent.toString();
 
-        System.setOut(stdout);
-
         assertTrue(outString.contains("Added the action listener to the engine"));
     }
+
+    @Test
+    public void testCorrectParametersWithMultiplePolicies() throws ApexException {
+        OutputStream outContent = new ByteArrayOutputStream();
+        System.setOut(new PrintStream(outContent));
+        Map<ToscaPolicyIdentifier, String[]> argsMap = new HashMap<ToscaPolicyIdentifier, String[]>();
+        String[] args = {"-c", "src/test/resources/parameters/correctParams.json", "-m",
+            "src/test/resources/policymodels/SmallModel.json"};
+        argsMap.put(new ToscaPolicyIdentifier("id1", "v1"), args);
+        final ApexMain apexMain = new ApexMain(argsMap);
+        ApexParameters apexParam = (ApexParameters) apexMain.getApexParametersMap().values().toArray()[0];
+        assertEquals("MyApexEngine", apexParam.getEngineServiceParameters().getName());
+        apexMain.shutdown();
+        final String outString = outContent.toString();
+        assertTrue(outString.contains("Added the action listener to the engine"));
+    }
+
+    @Test
+    public void testInCorrectParametersWithMultiplePolicies() throws ApexException {
+        OutputStream outContent = new ByteArrayOutputStream();
+        System.setOut(new PrintStream(outContent));
+        Map<ToscaPolicyIdentifier, String[]> argsMap = new HashMap<ToscaPolicyIdentifier, String[]>();
+        String[] args = {"-c", "src/test/resources/parameters/correctParams.json", "-m",
+            "src/test/resources/policymodels/SmallModel.json"};
+        argsMap.put(new ToscaPolicyIdentifier("id1", "v1"), args);
+        argsMap.put(new ToscaPolicyIdentifier("id2", "v2"), args);
+        final ApexMain apexMain = new ApexMain(argsMap);
+        ApexParameters apexParam = (ApexParameters) apexMain.getApexParametersMap().values().toArray()[0];
+        assertEquals("MyApexEngine", apexParam.getEngineServiceParameters().getName());
+        apexMain.shutdown();
+        final String outString = outContent.toString();
+        assertTrue(outString.contains("I/O Parameters for id2:v2 has duplicates. So this policy is not executed"));
+        assertTrue(apexMain.getApexParametersMap().size() == 1); // only id1:v1 is kept in the map, id2:v2 failed
+    }
+
+    @Test
+    public void testInvalidArgsWithMultiplePolicies() throws ApexException {
+        OutputStream outContent = new ByteArrayOutputStream();
+        System.setOut(new PrintStream(outContent));
+        Map<ToscaPolicyIdentifier, String[]> argsMap = new HashMap<ToscaPolicyIdentifier, String[]>();
+        String[] args = {"-c", "file1", "-m", "file2"};
+        argsMap.put(new ToscaPolicyIdentifier("id1", "v1"), args);
+        final ApexMain apexMain = new ApexMain(argsMap);
+        final String outString = outContent.toString();
+        apexMain.shutdown();
+        assertTrue(
+            outString.contains("Arguments validation failed") && outString.contains("start of Apex service failed"));
+        assertTrue(apexMain.getApexParametersMap().isEmpty()); // No policy is running in the engine
+    }
 }
diff --git a/services/services-onappf/src/main/java/org/onap/policy/apex/services/onappf/handler/ApexEngineHandler.java b/services/services-onappf/src/main/java/org/onap/policy/apex/services/onappf/handler/ApexEngineHandler.java
index 4f68b90..1953939 100644
--- a/services/services-onappf/src/main/java/org/onap/policy/apex/services/onappf/handler/ApexEngineHandler.java
+++ b/services/services-onappf/src/main/java/org/onap/policy/apex/services/onappf/handler/ApexEngineHandler.java
@@ -21,17 +21,21 @@
 package org.onap.policy.apex.services.onappf.handler;
 
 import com.google.gson.JsonObject;
-
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Path;
-
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
 import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
 import org.onap.policy.apex.service.engine.main.ApexMain;
 import org.onap.policy.apex.services.onappf.exception.ApexStarterException;
 import org.onap.policy.common.utils.coder.CoderException;
 import org.onap.policy.common.utils.coder.StandardCoder;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -46,31 +50,41 @@
     private ApexMain apexMain;
 
     /**
-     * Constructs the object. Extracts the apex config and model files and instantiates the apex engine.
+     * Constructs the object. Extracts the config and model files from each policy and instantiates the apex engine.
      *
-     * @param properties the properties which contains the policies and configurations received from pap
-     * @throws ApexStarterException if the apex engine instantiation failed using the properties passed
+     * @param policies the list of policies
+     * @throws ApexStarterException if the apex engine instantiation failed using the policies passed
      */
-    public ApexEngineHandler(final Object properties) throws ApexStarterException {
-        final StandardCoder standardCoder = new StandardCoder();
-        String policyModel;
-        String apexConfig;
-        try {
-            JsonObject body = standardCoder.decode(standardCoder.encode(properties), JsonObject.class);
-            final JsonObject engineServiceParameters = body.get("engineServiceParameters").getAsJsonObject();
-            policyModel = standardCoder.encode(engineServiceParameters.get("policy_type_impl"));
-            engineServiceParameters.remove("policy_type_impl");
-            apexConfig = standardCoder.encode(body);
-        } catch (final CoderException e) {
-            throw new ApexStarterException(e);
+    public ApexEngineHandler(List<ToscaPolicy> policies)  throws ApexStarterException {
+        Map<ToscaPolicyIdentifier, String[]> policyArgsMap = new LinkedHashMap<>();
+        for (ToscaPolicy policy : policies) {
+            Object properties = policy.getProperties().get("content");
+            final StandardCoder standardCoder = new StandardCoder();
+            String policyModel;
+            String apexConfig;
+            try {
+                JsonObject body = standardCoder.decode(standardCoder.encode(properties), JsonObject.class);
+                final JsonObject engineServiceParameters = body.get("engineServiceParameters").getAsJsonObject();
+                policyModel = standardCoder.encode(engineServiceParameters.get("policy_type_impl"));
+                engineServiceParameters.remove("policy_type_impl");
+                apexConfig = standardCoder.encode(body);
+            } catch (final CoderException e) {
+                throw new ApexStarterException(e);
+            }
+
+            final String modelFilePath = createFile(policyModel, "modelFile");
+
+            final String apexConfigFilePath = createFile(apexConfig, "apexConfigFile");
+            final String[] apexArgs = { "-c", apexConfigFilePath, "-m", modelFilePath };
+            policyArgsMap.put(policy.getIdentifier(), apexArgs);
         }
 
-        final String modelFilePath = createFile(policyModel, "modelFile");
-
-        final String apexConfigFilePath = createFile(apexConfig, "apexConfigFile");
-        final String[] apexArgs = { "-c", apexConfigFilePath, "-m", modelFilePath };
         LOGGER.debug("Starting apex engine.");
-        apexMain = new ApexMain(apexArgs);
+        try {
+            apexMain = new ApexMain(policyArgsMap);
+        } catch (ApexException e) {
+            throw new ApexStarterException(e);
+        }
     }
 
     /**
@@ -100,6 +114,13 @@
     }
 
     /**
+     * Method that return the list of running policies in the apex engine.
+     */
+    public List<ToscaPolicyIdentifier> getRunningPolicies() {
+        return new ArrayList<>(apexMain.getApexParametersMap().keySet());
+    }
+
+    /**
      * Method to shut down the apex engine.
      */
     public void shutdown() throws ApexStarterException {
diff --git a/services/services-onappf/src/main/java/org/onap/policy/apex/services/onappf/handler/PdpStateChangeMessageHandler.java b/services/services-onappf/src/main/java/org/onap/policy/apex/services/onappf/handler/PdpStateChangeMessageHandler.java
index 8658150..fd95b47 100644
--- a/services/services-onappf/src/main/java/org/onap/policy/apex/services/onappf/handler/PdpStateChangeMessageHandler.java
+++ b/services/services-onappf/src/main/java/org/onap/policy/apex/services/onappf/handler/PdpStateChangeMessageHandler.java
@@ -20,6 +20,7 @@
 
 package org.onap.policy.apex.services.onappf.handler;
 
+import java.util.HashSet;
 import java.util.List;
 import org.onap.policy.apex.services.onappf.ApexStarterConstants;
 import org.onap.policy.apex.services.onappf.comm.PdpStatusPublisher;
@@ -31,6 +32,7 @@
 import org.onap.policy.models.pdp.enums.PdpResponseStatus;
 import org.onap.policy.models.pdp.enums.PdpState;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -93,30 +95,60 @@
                 pdpResponseDetails = pdpMessageHandler.createPdpResonseDetails(pdpStateChangeMsg.getRequestId(),
                         PdpResponseStatus.SUCCESS, "State changed to active. No policies found.");
             } else {
-                try {
-                    // assumed that the apex policies list contains only one entry.
-                    final ApexEngineHandler apexEngineHandler =
-                            new ApexEngineHandler(policies.get(0).getProperties().get("content"));
-                    Registry.registerOrReplace(ApexStarterConstants.REG_APEX_ENGINE_HANDLER, apexEngineHandler);
-                    if (apexEngineHandler.isApexEngineRunning()) {
-                        pdpResponseDetails = pdpMessageHandler.createPdpResonseDetails(pdpStateChangeMsg.getRequestId(),
-                            PdpResponseStatus.SUCCESS, "Apex engine started. State changed to active.");
-                        pdpStatusContext.setState(PdpState.ACTIVE);
-                    } else {
-                        pdpResponseDetails = pdpMessageHandler.createPdpResonseDetails(pdpStateChangeMsg.getRequestId(),
-                            PdpResponseStatus.FAIL, "Apex engine failed to start. State cannot be changed to active.");
-                    }
-                } catch (final ApexStarterException e) {
-                    LOGGER.error("Pdp update failed as the policies couldn't be undeployed.", e);
-                    pdpResponseDetails = pdpMessageHandler.createPdpResonseDetails(pdpStateChangeMsg.getRequestId(),
-                            PdpResponseStatus.FAIL, "Apex engine service running failed. " + e.getMessage());
-                }
+                pdpResponseDetails = startApexEngine(pdpStateChangeMsg, pdpStatusContext, pdpMessageHandler, policies);
             }
         }
         return pdpResponseDetails;
     }
 
     /**
+     * Method to start apex engine.
+     *
+     * @param pdpStateChangeMsg pdp state change message
+     * @param pdpStatusContext pdp status in memory
+     * @param pdpMessageHandler the pdp message handler
+     * @param policies list of policies
+     * @return pdp response details
+     */
+    private PdpResponseDetails startApexEngine(final PdpStateChange pdpStateChangeMsg, final PdpStatus pdpStatusContext,
+        final PdpMessageHandler pdpMessageHandler, final List<ToscaPolicy> policies) {
+        PdpResponseDetails pdpResponseDetails;
+        try {
+            final ApexEngineHandler apexEngineHandler = new ApexEngineHandler(policies);
+            Registry.registerOrReplace(ApexStarterConstants.REG_APEX_ENGINE_HANDLER, apexEngineHandler);
+            if (apexEngineHandler.isApexEngineRunning()) {
+                List<ToscaPolicyIdentifier> runningPolicies = apexEngineHandler.getRunningPolicies();
+                // only the policies which are succesfully executed should be there in the heartbeat
+                pdpStatusContext.setPolicies(runningPolicies);
+                if (new HashSet<>(runningPolicies)
+                    .equals(new HashSet<>(pdpMessageHandler.getToscaPolicyIdentifiers(policies)))) {
+                    pdpResponseDetails =
+                        pdpMessageHandler.createPdpResonseDetails(pdpStateChangeMsg.getRequestId(),
+                            PdpResponseStatus.SUCCESS, "Apex engine started. State changed to active.");
+                } else {
+                    StringBuilder message = new StringBuilder(
+                        "Apex engine started. But, only the following polices are running - ");
+                    for (ToscaPolicyIdentifier policy : runningPolicies) {
+                        message.append(policy.getName()).append(":").append(policy.getVersion()).append("  ");
+                    }
+                    message.append(". Other policies failed execution. Please see the logs for more details.");
+                    pdpResponseDetails = pdpMessageHandler.createPdpResonseDetails(
+                        pdpStateChangeMsg.getRequestId(), PdpResponseStatus.SUCCESS, message.toString());
+                }
+                pdpStatusContext.setState(PdpState.ACTIVE);
+            } else {
+                pdpResponseDetails = pdpMessageHandler.createPdpResonseDetails(pdpStateChangeMsg.getRequestId(),
+                    PdpResponseStatus.FAIL, "Apex engine failed to start. State cannot be changed to active.");
+            }
+        } catch (final ApexStarterException e) {
+            LOGGER.error("Pdp State Change failed.", e);
+            pdpResponseDetails = pdpMessageHandler.createPdpResonseDetails(pdpStateChangeMsg.getRequestId(),
+                    PdpResponseStatus.FAIL, "Apex engine service running failed. " + e.getMessage());
+        }
+        return pdpResponseDetails;
+    }
+
+    /**
      * Method to handle when the new state from pap is passive.
      *
      * @param pdpStateChangeMsg pdp state change message
diff --git a/services/services-onappf/src/main/java/org/onap/policy/apex/services/onappf/handler/PdpUpdateMessageHandler.java b/services/services-onappf/src/main/java/org/onap/policy/apex/services/onappf/handler/PdpUpdateMessageHandler.java
index d807dc5..ecc0bec 100644
--- a/services/services-onappf/src/main/java/org/onap/policy/apex/services/onappf/handler/PdpUpdateMessageHandler.java
+++ b/services/services-onappf/src/main/java/org/onap/policy/apex/services/onappf/handler/PdpUpdateMessageHandler.java
@@ -20,6 +20,8 @@
 
 package org.onap.policy.apex.services.onappf.handler;
 
+import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
 import org.onap.policy.apex.services.onappf.ApexStarterConstants;
 import org.onap.policy.apex.services.onappf.comm.PdpStatusPublisher;
@@ -31,6 +33,7 @@
 import org.onap.policy.models.pdp.concepts.PdpUpdate;
 import org.onap.policy.models.pdp.enums.PdpResponseStatus;
 import org.onap.policy.models.pdp.enums.PdpState;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -54,27 +57,11 @@
         PdpResponseDetails pdpResponseDetails = null;
         if (pdpUpdateMsg.appliesTo(pdpStatusContext.getName(), pdpStatusContext.getPdpGroup(),
                 pdpStatusContext.getPdpSubgroup())) {
-            final PdpStatusPublisher pdpStatusPublisher = Registry.get(ApexStarterConstants.REG_PDP_STATUS_PUBLISHER);
             if (checkIfAlreadyHandled(pdpUpdateMsg, pdpStatusContext)) {
                 pdpResponseDetails = pdpMessageHandler.createPdpResonseDetails(pdpUpdateMsg.getRequestId(),
                         PdpResponseStatus.SUCCESS, "Pdp already updated");
             } else {
-                if (null != pdpUpdateMsg.getPdpHeartbeatIntervalMs() && pdpUpdateMsg.getPdpHeartbeatIntervalMs() > 0
-                        && pdpStatusPublisher.getInterval() != pdpUpdateMsg.getPdpHeartbeatIntervalMs()) {
-                    updateInterval(pdpUpdateMsg.getPdpHeartbeatIntervalMs());
-                }
-                pdpStatusContext.setPdpGroup(pdpUpdateMsg.getPdpGroup());
-                pdpStatusContext.setPdpSubgroup(pdpUpdateMsg.getPdpSubgroup());
-                pdpStatusContext
-                        .setPolicies(new PdpMessageHandler().getToscaPolicyIdentifiers(pdpUpdateMsg.getPolicies()));
-                if (pdpStatusContext.getState().equals(PdpState.ACTIVE)) {
-                    pdpResponseDetails = startOrStopApexEngineBasedOnPolicies(pdpUpdateMsg, pdpMessageHandler);
-                }
-                Registry.registerOrReplace(ApexStarterConstants.REG_APEX_TOSCA_POLICY_LIST, pdpUpdateMsg.getPolicies());
-                if (null == pdpResponseDetails) {
-                    pdpResponseDetails = pdpMessageHandler.createPdpResonseDetails(pdpUpdateMsg.getRequestId(),
-                            PdpResponseStatus.SUCCESS, "Pdp update successful.");
-                }
+                pdpResponseDetails = handlePdpUpdate(pdpUpdateMsg, pdpMessageHandler, pdpStatusContext);
             }
             final PdpStatusPublisher pdpStatusPublisherTemp =
                     Registry.get(ApexStarterConstants.REG_PDP_STATUS_PUBLISHER);
@@ -86,6 +73,47 @@
     }
 
     /**
+     * Method to do pdp update.
+     *
+     * @param pdpUpdateMsg the pdp update message
+     * @param pdpMessageHandler the message handler
+     * @param pdpStatusContext the pdp status in memory
+     * @return pdpResponseDetails the pdp response
+     */
+    private PdpResponseDetails handlePdpUpdate(final PdpUpdate pdpUpdateMsg, final PdpMessageHandler pdpMessageHandler,
+        final PdpStatus pdpStatusContext) {
+        PdpResponseDetails pdpResponseDetails = null;
+        final PdpStatusPublisher pdpStatusPublisher = Registry.get(ApexStarterConstants.REG_PDP_STATUS_PUBLISHER);
+        if (null != pdpUpdateMsg.getPdpHeartbeatIntervalMs() && pdpUpdateMsg.getPdpHeartbeatIntervalMs() > 0
+                && pdpStatusPublisher.getInterval() != pdpUpdateMsg.getPdpHeartbeatIntervalMs()) {
+            updateInterval(pdpUpdateMsg.getPdpHeartbeatIntervalMs());
+        }
+        pdpStatusContext.setPdpGroup(pdpUpdateMsg.getPdpGroup());
+        pdpStatusContext.setPdpSubgroup(pdpUpdateMsg.getPdpSubgroup());
+        pdpStatusContext
+                .setPolicies(new PdpMessageHandler().getToscaPolicyIdentifiers(pdpUpdateMsg.getPolicies()));
+        Registry.registerOrReplace(ApexStarterConstants.REG_APEX_TOSCA_POLICY_LIST, pdpUpdateMsg.getPolicies());
+        if (pdpStatusContext.getState().equals(PdpState.ACTIVE)) {
+            pdpResponseDetails = startOrStopApexEngineBasedOnPolicies(pdpUpdateMsg, pdpMessageHandler);
+
+            ApexEngineHandler apexEngineHandler = Registry.get(ApexStarterConstants.REG_APEX_ENGINE_HANDLER);
+            // in hearbeat while in active state, only the policies which are running should be there.
+            // if some policy fails, that shouldn't go in the heartbeat.
+            // If no policies are running, then the policy list in the heartbeat can be empty
+            if (null != apexEngineHandler && apexEngineHandler.isApexEngineRunning()) {
+                pdpStatusContext.setPolicies(apexEngineHandler.getRunningPolicies());
+            } else {
+                pdpStatusContext.setPolicies(Collections.emptyList());
+            }
+        }
+        if (null == pdpResponseDetails) {
+            pdpResponseDetails = pdpMessageHandler.createPdpResonseDetails(pdpUpdateMsg.getRequestId(),
+                    PdpResponseStatus.SUCCESS, "Pdp update successful.");
+        }
+        return pdpResponseDetails;
+    }
+
+    /**
      * Method to start or stop apex engine based on the list of policies received from pap. When current state is
      * active, if PAP sends PdpUpdate with empty policies list, stop apex engine, or, if there is a change in policies,
      * stop the current running policies and the deploy the new ones.
@@ -118,6 +146,8 @@
         if (null != apexEngineHandler && apexEngineHandler.isApexEngineRunning()) {
             try {
                 apexEngineHandler.shutdown();
+                pdpResponseDetails = pdpMessageHandler.createPdpResonseDetails(pdpUpdateMsg.getRequestId(),
+                    PdpResponseStatus.SUCCESS, "Pdp update successful. No policies are running.");
             } catch (final ApexStarterException e) {
                 LOGGER.error("Pdp update failed as the policies couldn't be undeployed.", e);
                 pdpResponseDetails = pdpMessageHandler.createPdpResonseDetails(pdpUpdateMsg.getRequestId(),
@@ -134,12 +164,24 @@
             if (null != apexEngineHandler && apexEngineHandler.isApexEngineRunning()) {
                 apexEngineHandler.shutdown();
             }
-            apexEngineHandler =
-                    new ApexEngineHandler(pdpUpdateMsg.getPolicies().get(0).getProperties().get("content"));
+            apexEngineHandler = new ApexEngineHandler(pdpUpdateMsg.getPolicies());
             Registry.registerOrReplace(ApexStarterConstants.REG_APEX_ENGINE_HANDLER, apexEngineHandler);
             if (apexEngineHandler.isApexEngineRunning()) {
-                pdpResponseDetails = pdpMessageHandler.createPdpResonseDetails(pdpUpdateMsg.getRequestId(),
-                    PdpResponseStatus.SUCCESS, "Apex engine started and policies are running.");
+                List<ToscaPolicyIdentifier> runningPolicies = apexEngineHandler.getRunningPolicies();
+                if (new HashSet<>(runningPolicies)
+                    .equals(new HashSet<>(pdpMessageHandler.getToscaPolicyIdentifiers(pdpUpdateMsg.getPolicies())))) {
+                    pdpResponseDetails = pdpMessageHandler.createPdpResonseDetails(pdpUpdateMsg.getRequestId(),
+                        PdpResponseStatus.SUCCESS, "Apex engine started and policies are running.");
+                } else {
+                    StringBuilder message =
+                        new StringBuilder("Apex engine started. But, only the following polices are running - ");
+                    for (ToscaPolicyIdentifier policy : runningPolicies) {
+                        message.append(policy.getName()).append(":").append(policy.getVersion()).append("  ");
+                    }
+                    message.append(". Other policies failed execution. Please see the logs for more details.");
+                    pdpResponseDetails = pdpMessageHandler.createPdpResonseDetails(pdpUpdateMsg.getRequestId(),
+                        PdpResponseStatus.SUCCESS, message.toString());
+                }
             } else {
                 pdpResponseDetails = pdpMessageHandler.createPdpResonseDetails(pdpUpdateMsg.getRequestId(),
                     PdpResponseStatus.FAIL, "Apex engine failed to start.");
diff --git a/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/TestApexStarterActivator.java b/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/TestApexStarterActivator.java
index c8f889f..77ffa53 100644
--- a/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/TestApexStarterActivator.java
+++ b/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/TestApexStarterActivator.java
@@ -56,7 +56,7 @@
     @Before
     public void setUp() throws Exception {
         Registry.newRegistry();
-        final String[] apexStarterConfigParameters = { "-c", "src/test/resources/ApexStarterConfigParameters.json"};
+        final String[] apexStarterConfigParameters = { "-c", "src/test/resources/ApexStarterConfigParametersNoop.json"};
         final ApexStarterCommandLineArguments arguments =
                 new ApexStarterCommandLineArguments(apexStarterConfigParameters);
         final ApexStarterParameterGroup parGroup = new ApexStarterParameterHandler().getParameters(arguments);
diff --git a/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/TestApexStarterMain.java b/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/TestApexStarterMain.java
index 68d3025..2fcfe88 100644
--- a/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/TestApexStarterMain.java
+++ b/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/TestApexStarterMain.java
@@ -27,9 +27,6 @@
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
-import org.onap.policy.apex.services.onappf.ApexStarterActivator;
-import org.onap.policy.apex.services.onappf.ApexStarterConstants;
-import org.onap.policy.apex.services.onappf.ApexStarterMain;
 import org.onap.policy.apex.services.onappf.exception.ApexStarterException;
 import org.onap.policy.apex.services.onappf.parameters.CommonTestData;
 import org.onap.policy.common.utils.services.Registry;
@@ -67,7 +64,7 @@
 
     @Test
     public void testApexStarter() throws ApexStarterException {
-        final String[] apexStarterConfigParameters = { "-c", "src/test/resources/ApexStarterConfigParameters.json"};
+        final String[] apexStarterConfigParameters = { "-c", "src/test/resources/ApexStarterConfigParametersNoop.json"};
         apexStarter = new ApexStarterMain(apexStarterConfigParameters);
         assertTrue(apexStarter.getParameters().isValid());
         assertEquals(CommonTestData.APEX_STARTER_GROUP_NAME, apexStarter.getParameters().getName());
diff --git a/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/comm/TestListenerUtils.java b/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/comm/TestListenerUtils.java
new file mode 100644
index 0000000..78d9d76
--- /dev/null
+++ b/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/comm/TestListenerUtils.java
@@ -0,0 +1,99 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.services.onappf.comm;
+
+import com.google.gson.JsonObject;
+import java.io.File;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import org.onap.policy.common.utils.coder.CoderException;
+import org.onap.policy.common.utils.coder.StandardCoder;
+import org.onap.policy.models.pdp.concepts.PdpStateChange;
+import org.onap.policy.models.pdp.concepts.PdpStatus;
+import org.onap.policy.models.pdp.concepts.PdpUpdate;
+import org.onap.policy.models.pdp.enums.PdpState;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
+
+public class TestListenerUtils {
+
+    /**
+     * Method to create PdpUpdate message from the arguments passed.
+     *
+     * @param pdpStatus pdp status
+     * @param toscaPolicies list of tosca policies
+     *
+     * @return PdpUpdate message
+     */
+    public static PdpUpdate createPdpUpdateMsg(final PdpStatus pdpStatus, List<ToscaPolicy> toscaPolicies ) {
+        final PdpUpdate pdpUpdateMsg = new PdpUpdate();
+        pdpUpdateMsg.setDescription("dummy pdp status for test");
+        pdpUpdateMsg.setPdpGroup("pdpGroup");
+        pdpUpdateMsg.setPdpSubgroup("pdpSubgroup");
+        pdpUpdateMsg.setName(pdpStatus.getName());
+        pdpUpdateMsg.setPdpHeartbeatIntervalMs(Long.valueOf(3000));
+        pdpUpdateMsg.setPolicies(toscaPolicies);
+        return pdpUpdateMsg;
+    }
+
+    /**
+     * Method to create ToscaPolicy using the arguments passed.
+     *
+     * @param policyName the name of the policy
+     * @param policyVersion the version of the policy
+     * @param policyFilePath the path of the policy content
+     *
+     * @return PdpUpdate message
+     * @throws CoderException exception while reading the file to object
+     */
+    public static ToscaPolicy createToscaPolicy(String policyName, String policyVersion, String policyFilePath)
+        throws CoderException {
+        final ToscaPolicy toscaPolicy = new ToscaPolicy();
+        toscaPolicy.setType("apexpolicytype");
+        toscaPolicy.setVersion(policyVersion);
+        toscaPolicy.setName(policyName);
+        final Map<String, Object> propertiesMap = new LinkedHashMap<>();
+        Object properties = new StandardCoder().decode(new File(policyFilePath), JsonObject.class);
+        propertiesMap.put("content", properties);
+        toscaPolicy.setProperties(propertiesMap);
+        return toscaPolicy;
+    }
+
+    /**
+     * Method to create PdpStateChange message from the arguments passed.
+     *
+     * @param state the new pdp state
+     * @param pdpGroup name of the pdpGroup
+     * @param pdpSubgroup name of the pdpSubGroup
+     * @param name the name of the message
+     *
+     * @return PdpStateChange message
+     */
+    public static PdpStateChange createPdpStateChangeMsg(PdpState state, String pdpGroup, String pdpSubgroup,
+        String name) {
+        final PdpStateChange pdpStateChangeMsg = new PdpStateChange();
+        pdpStateChangeMsg.setState(state);
+        pdpStateChangeMsg.setPdpGroup(pdpGroup);
+        pdpStateChangeMsg.setPdpSubgroup(pdpSubgroup);
+        pdpStateChangeMsg.setName(name);
+        return pdpStateChangeMsg;
+    }
+}
diff --git a/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/comm/TestPdpStateChangeListener.java b/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/comm/TestPdpStateChangeListener.java
index c475b50..7f7de3b 100644
--- a/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/comm/TestPdpStateChangeListener.java
+++ b/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/comm/TestPdpStateChangeListener.java
@@ -23,16 +23,15 @@
 package org.onap.policy.apex.services.onappf.comm;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
+import java.io.ByteArrayOutputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Paths;
+import java.io.OutputStream;
+import java.io.PrintStream;
 import java.util.ArrayList;
-import java.util.LinkedHashMap;
 import java.util.List;
-import java.util.Map;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -40,9 +39,11 @@
 import org.onap.policy.apex.services.onappf.ApexStarterCommandLineArguments;
 import org.onap.policy.apex.services.onappf.ApexStarterConstants;
 import org.onap.policy.apex.services.onappf.exception.ApexStarterException;
+import org.onap.policy.apex.services.onappf.handler.ApexEngineHandler;
 import org.onap.policy.apex.services.onappf.parameters.ApexStarterParameterGroup;
 import org.onap.policy.apex.services.onappf.parameters.ApexStarterParameterHandler;
 import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
+import org.onap.policy.common.utils.coder.CoderException;
 import org.onap.policy.common.utils.services.Registry;
 import org.onap.policy.models.pdp.concepts.PdpStateChange;
 import org.onap.policy.models.pdp.concepts.PdpStatus;
@@ -61,6 +62,8 @@
     private static final CommInfrastructure INFRA = CommInfrastructure.NOOP;
     private static final String TOPIC = "my-topic";
     private ApexStarterActivator activator;
+    private ApexEngineHandler apexEngineHandler;
+    private PrintStream stdout = System.out;
 
     /**
      * Method for setup before each test.
@@ -74,7 +77,7 @@
         pdpUpdateMessageListener = new PdpUpdateListener();
         pdpStateChangeListener = new PdpStateChangeListener();
         Registry.newRegistry();
-        final String[] apexStarterConfigParameters = { "-c", "src/test/resources/ApexStarterConfigParameters.json" };
+        final String[] apexStarterConfigParameters = {"-c", "src/test/resources/ApexStarterConfigParametersNoop.json"};
         final ApexStarterCommandLineArguments arguments = new ApexStarterCommandLineArguments();
         ApexStarterParameterGroup parameterGroup;
         // The arguments return a string if there is a message to print and we should
@@ -101,55 +104,25 @@
      */
     @After
     public void teardown() throws Exception {
-
+        System.setOut(stdout);
+        apexEngineHandler =
+            Registry.getOrDefault(ApexStarterConstants.REG_APEX_ENGINE_HANDLER, ApexEngineHandler.class, null);
+        if (null != apexEngineHandler && apexEngineHandler.isApexEngineRunning()) {
+            apexEngineHandler.shutdown();
+        }
         // clear the apex starter activator
         if (activator != null && activator.isAlive()) {
             activator.terminate();
         }
     }
 
-    /**
-     * Method to initiate a PdpUpdate.
-     *
-     * @param instance the instance id
-     * @return PdpUpdate the pdp update message
-     */
-    private PdpUpdate performPdpUpdate(final String instance) {
-        final PdpUpdate pdpUpdateMsg = new PdpUpdate();
-        pdpUpdateMsg.setDescription("dummy pdp status for test");
-        pdpUpdateMsg.setPdpGroup("pdpGroup");
-        pdpUpdateMsg.setPdpSubgroup("pdpSubgroup");
-        pdpUpdateMsg.setName(instance);
-        final ToscaPolicy toscaPolicy = new ToscaPolicy();
-        toscaPolicy.setType("apexpolicytype");
-        toscaPolicy.setVersion("1.0");
-        final Map<String, Object> propertiesMap = new LinkedHashMap<>();
-
-        String properties;
-        try {
-            properties = new String(Files.readAllBytes(Paths.get("src\\test\\resources\\dummyProperties.json")),
-                    StandardCharsets.UTF_8);
-            propertiesMap.put("content", properties);
-        } catch (final IOException e) {
-            propertiesMap.put("content", "");
-        }
-        toscaPolicy.setProperties(propertiesMap);
-        final List<ToscaPolicy> toscaPolicies = new ArrayList<ToscaPolicy>();
-        toscaPolicies.add(toscaPolicy);
-        pdpUpdateMsg.setPolicies(toscaPolicies);
-        pdpUpdateMessageListener.onTopicEvent(INFRA, TOPIC, null, pdpUpdateMsg);
-        return pdpUpdateMsg;
-    }
-
     @Test
     public void testPdpStateChangeMessageListener_passivetopassive() {
         final PdpStatus pdpStatus = Registry.get(ApexStarterConstants.REG_PDP_STATUS_OBJECT);
-        performPdpUpdate(pdpStatus.getName());
-        final PdpStateChange pdpStateChangeMsg = new PdpStateChange();
-        pdpStateChangeMsg.setState(PdpState.PASSIVE);
-        pdpStateChangeMsg.setPdpGroup("pdpGroup");
-        pdpStateChangeMsg.setPdpSubgroup("pdpSubgroup");
-        pdpStateChangeMsg.setName(pdpStatus.getName());
+        pdpUpdateMessageListener.onTopicEvent(INFRA, TOPIC, null,
+            TestListenerUtils.createPdpUpdateMsg(pdpStatus, new ArrayList<ToscaPolicy>()));
+        PdpStateChange pdpStateChangeMsg =
+            TestListenerUtils.createPdpStateChangeMsg(PdpState.PASSIVE, "pdpGroup", "pdpSubgroup", pdpStatus.getName());
         pdpStateChangeListener.onTopicEvent(INFRA, TOPIC, null, pdpStateChangeMsg);
 
         assertEquals(pdpStatus.getState(), pdpStateChangeMsg.getState());
@@ -158,15 +131,57 @@
     @Test
     public void testPdpStateChangeMessageListener_activetoactive() {
         final PdpStatus pdpStatus = Registry.get(ApexStarterConstants.REG_PDP_STATUS_OBJECT);
-        performPdpUpdate(pdpStatus.getName());
+        pdpUpdateMessageListener.onTopicEvent(INFRA, TOPIC, null,
+            TestListenerUtils.createPdpUpdateMsg(pdpStatus, new ArrayList<ToscaPolicy>()));
         pdpStatus.setState(PdpState.ACTIVE);
-        final PdpStateChange pdpStateChangeMsg = new PdpStateChange();
-        pdpStateChangeMsg.setState(PdpState.ACTIVE);
-        pdpStateChangeMsg.setPdpGroup("pdpGroup");
-        pdpStateChangeMsg.setPdpSubgroup("pdpSubgroup");
-        pdpStateChangeMsg.setName(pdpStatus.getName());
+        PdpStateChange pdpStateChangeMsg =
+            TestListenerUtils.createPdpStateChangeMsg(PdpState.ACTIVE, "pdpGroup", "pdpSubgroup", pdpStatus.getName());
         pdpStateChangeListener.onTopicEvent(INFRA, TOPIC, null, pdpStateChangeMsg);
 
         assertEquals(pdpStatus.getState(), pdpStateChangeMsg.getState());
     }
+
+    @Test
+    public void testPdpStateChangeMessageListener() throws InterruptedException, CoderException {
+        OutputStream outContent = new ByteArrayOutputStream();
+        System.setOut(new PrintStream(outContent));
+        final PdpStatus pdpStatus = Registry.get(ApexStarterConstants.REG_PDP_STATUS_OBJECT);
+        pdpUpdateMessageListener.onTopicEvent(INFRA, TOPIC, null,
+            TestListenerUtils.createPdpUpdateMsg(pdpStatus, new ArrayList<ToscaPolicy>()));
+        PdpStateChange pdpStateChangeMsg =
+            TestListenerUtils.createPdpStateChangeMsg(PdpState.ACTIVE, "pdpGroup", "pdpSubgroup", pdpStatus.getName());
+        pdpStateChangeListener.onTopicEvent(INFRA, TOPIC, null, pdpStateChangeMsg);
+        assertTrue(outContent.toString().contains("State changed to active. No policies found."));
+
+        final ToscaPolicy toscaPolicy =
+            TestListenerUtils.createToscaPolicy("apex policy name", "1.0", "src/test/resources/dummyProperties.json");
+        final List<ToscaPolicy> toscaPolicies = new ArrayList<ToscaPolicy>();
+        toscaPolicies.add(toscaPolicy);
+        final PdpUpdate pdpUpdateMsg = TestListenerUtils.createPdpUpdateMsg(pdpStatus, toscaPolicies);
+        pdpUpdateMessageListener.onTopicEvent(INFRA, TOPIC, null, pdpUpdateMsg);
+        assertTrue(outContent.toString().contains("Apex engine started and policies are running."));
+        assertEquals(PdpState.ACTIVE, pdpStatus.getState());
+    }
+
+    @Test
+    public void testPdpStateChangeMessageListener_activetopassive() throws InterruptedException, CoderException {
+        final PdpStatus pdpStatus = Registry.get(ApexStarterConstants.REG_PDP_STATUS_OBJECT);
+        final ToscaPolicy toscaPolicy =
+            TestListenerUtils.createToscaPolicy("apex policy name", "1.0", "src/test/resources/dummyProperties.json");
+        final List<ToscaPolicy> toscaPolicies = new ArrayList<ToscaPolicy>();
+        toscaPolicies.add(toscaPolicy);
+        final PdpUpdate pdpUpdateMsg = TestListenerUtils.createPdpUpdateMsg(pdpStatus, toscaPolicies);
+        pdpUpdateMessageListener.onTopicEvent(INFRA, TOPIC, null, pdpUpdateMsg);
+        PdpStateChange pdpStateChangeMsg =
+            TestListenerUtils.createPdpStateChangeMsg(PdpState.ACTIVE, "pdpGroup", "pdpSubgroup", pdpStatus.getName());
+        pdpStateChangeListener.onTopicEvent(INFRA, TOPIC, null, pdpStateChangeMsg);
+        pdpStateChangeMsg =
+            TestListenerUtils.createPdpStateChangeMsg(PdpState.PASSIVE, "pdpGroup", "pdpSubgroup", pdpStatus.getName());
+        OutputStream outContent = new ByteArrayOutputStream();
+        System.setOut(new PrintStream(outContent));
+        pdpStateChangeListener.onTopicEvent(INFRA, TOPIC, null, pdpStateChangeMsg);
+        final String outString = outContent.toString();
+        assertTrue(outString.contains("Apex pdp state changed from Active to Passive."));
+        assertEquals(PdpState.PASSIVE, pdpStatus.getState());
+    }
 }
diff --git a/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/comm/TestPdpUpdateListener.java b/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/comm/TestPdpUpdateListener.java
index 7007978..05656af 100644
--- a/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/comm/TestPdpUpdateListener.java
+++ b/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/comm/TestPdpUpdateListener.java
@@ -2,7 +2,6 @@
  * ============LICENSE_START=======================================================
  *  Copyright (C) 2019 Nordix Foundation.
  *  Modifications Copyright (C) 2019 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.
@@ -23,16 +22,15 @@
 package org.onap.policy.apex.services.onappf.comm;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
+import java.io.ByteArrayOutputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Paths;
+import java.io.OutputStream;
+import java.io.PrintStream;
 import java.util.ArrayList;
-import java.util.LinkedHashMap;
 import java.util.List;
-import java.util.Map;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -40,13 +38,17 @@
 import org.onap.policy.apex.services.onappf.ApexStarterCommandLineArguments;
 import org.onap.policy.apex.services.onappf.ApexStarterConstants;
 import org.onap.policy.apex.services.onappf.exception.ApexStarterException;
+import org.onap.policy.apex.services.onappf.handler.ApexEngineHandler;
 import org.onap.policy.apex.services.onappf.handler.PdpMessageHandler;
 import org.onap.policy.apex.services.onappf.parameters.ApexStarterParameterGroup;
 import org.onap.policy.apex.services.onappf.parameters.ApexStarterParameterHandler;
 import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
+import org.onap.policy.common.utils.coder.CoderException;
 import org.onap.policy.common.utils.services.Registry;
+import org.onap.policy.models.pdp.concepts.PdpStateChange;
 import org.onap.policy.models.pdp.concepts.PdpStatus;
 import org.onap.policy.models.pdp.concepts.PdpUpdate;
+import org.onap.policy.models.pdp.enums.PdpState;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
 
 /**
@@ -56,9 +58,12 @@
  */
 public class TestPdpUpdateListener {
     private PdpUpdateListener pdpUpdateMessageListener;
+    private PdpStateChangeListener pdpStateChangeListener;
     private static final CommInfrastructure INFRA = CommInfrastructure.NOOP;
     private static final String TOPIC = "my-topic";
     private ApexStarterActivator activator;
+    private ApexEngineHandler apexEngineHandler;
+    private PrintStream stdout = System.out;
 
     /**
      * Method for setup before each test.
@@ -70,7 +75,7 @@
     @Before
     public void setUp() throws ApexStarterException, FileNotFoundException, IOException {
         Registry.newRegistry();
-        final String[] apexStarterConfigParameters = { "-c", "src/test/resources/ApexStarterConfigParameters.json" };
+        final String[] apexStarterConfigParameters = {"-c", "src/test/resources/ApexStarterConfigParametersNoop.json"};
         final ApexStarterCommandLineArguments arguments = new ApexStarterCommandLineArguments();
         ApexStarterParameterGroup parameterGroup;
         // The arguments return a string if there is a message to print and we should
@@ -89,6 +94,7 @@
         Registry.register(ApexStarterConstants.REG_APEX_STARTER_ACTIVATOR, activator);
         activator.initialize();
         pdpUpdateMessageListener = new PdpUpdateListener();
+        pdpStateChangeListener = new PdpStateChangeListener();
     }
 
     /**
@@ -98,7 +104,12 @@
      */
     @After
     public void teardown() throws Exception {
-
+        System.setOut(stdout);
+        apexEngineHandler =
+            Registry.getOrDefault(ApexStarterConstants.REG_APEX_ENGINE_HANDLER, ApexEngineHandler.class, null);
+        if (null != apexEngineHandler && apexEngineHandler.isApexEngineRunning()) {
+            apexEngineHandler.shutdown();
+        }
         // clear the apex starter activator
         if (activator != null && activator.isAlive()) {
             activator.terminate();
@@ -106,35 +117,88 @@
     }
 
     @Test
-    public void testPdpUpdateMssageListener() {
+    public void testPdpUpdateMssageListener() throws CoderException {
         final PdpStatus pdpStatus = Registry.get(ApexStarterConstants.REG_PDP_STATUS_OBJECT);
-        final PdpUpdate pdpUpdateMsg = new PdpUpdate();
-        pdpUpdateMsg.setDescription("dummy pdp status for test");
-        pdpUpdateMsg.setPdpGroup("pdpGroup");
-        pdpUpdateMsg.setPdpSubgroup("pdpSubgroup");
-        pdpUpdateMsg.setName(pdpStatus.getName());
-        pdpUpdateMsg.setPdpHeartbeatIntervalMs(Long.valueOf(3000));
-        final ToscaPolicy toscaPolicy = new ToscaPolicy();
-        toscaPolicy.setType("apexpolicytype");
-        toscaPolicy.setVersion("1.0");
-        toscaPolicy.setName("apex policy name");
-        final Map<String, Object> propertiesMap = new LinkedHashMap<>();
-        String properties;
-        try {
-            properties = new String(Files.readAllBytes(Paths.get("src\\test\\resources\\dummyProperties.json")),
-                    StandardCharsets.UTF_8);
-            propertiesMap.put("content", properties);
-        } catch (final IOException e) {
-            propertiesMap.put("content", "");
-        }
-        toscaPolicy.setProperties(propertiesMap);
+        final ToscaPolicy toscaPolicy =
+            TestListenerUtils.createToscaPolicy("apex policy name", "1.0", "src/test/resources/dummyProperties.json");
         final List<ToscaPolicy> toscaPolicies = new ArrayList<ToscaPolicy>();
         toscaPolicies.add(toscaPolicy);
-        pdpUpdateMsg.setPolicies(toscaPolicies);
+        final PdpUpdate pdpUpdateMsg = TestListenerUtils.createPdpUpdateMsg(pdpStatus, toscaPolicies);
         pdpUpdateMessageListener.onTopicEvent(INFRA, TOPIC, null, pdpUpdateMsg);
         assertEquals(pdpStatus.getPdpGroup(), pdpUpdateMsg.getPdpGroup());
         assertEquals(pdpStatus.getPdpSubgroup(), pdpUpdateMsg.getPdpSubgroup());
         assertEquals(pdpStatus.getPolicies(),
                 new PdpMessageHandler().getToscaPolicyIdentifiers(pdpUpdateMsg.getPolicies()));
     }
+
+    @Test
+    public void testPdpUpdateMssageListener_success() throws InterruptedException, CoderException {
+        OutputStream outContent = new ByteArrayOutputStream();
+        System.setOut(new PrintStream(outContent));
+        final PdpStatus pdpStatus = Registry.get(ApexStarterConstants.REG_PDP_STATUS_OBJECT);
+        pdpUpdateMessageListener.onTopicEvent(INFRA, TOPIC, null,
+            TestListenerUtils.createPdpUpdateMsg(pdpStatus, new ArrayList<ToscaPolicy>()));
+        PdpStateChange pdpStateChangeMsg =
+            TestListenerUtils.createPdpStateChangeMsg(PdpState.ACTIVE, "pdpGroup", "pdpSubgroup", pdpStatus.getName());
+        pdpStateChangeListener.onTopicEvent(INFRA, TOPIC, null, pdpStateChangeMsg);
+        final ToscaPolicy toscaPolicy =
+            TestListenerUtils.createToscaPolicy("apex policy name", "1.0", "src/test/resources/dummyProperties.json");
+        final List<ToscaPolicy> toscaPolicies = new ArrayList<ToscaPolicy>();
+        toscaPolicies.add(toscaPolicy);
+        final PdpUpdate pdpUpdateMsg = TestListenerUtils.createPdpUpdateMsg(pdpStatus, toscaPolicies);
+        pdpUpdateMessageListener.onTopicEvent(INFRA, TOPIC, null, pdpUpdateMsg);
+        final String outString = outContent.toString();
+        assertEquals(pdpStatus.getPdpGroup(), pdpUpdateMsg.getPdpGroup());
+        assertEquals(pdpStatus.getPdpSubgroup(), pdpUpdateMsg.getPdpSubgroup());
+        assertEquals(pdpStatus.getPolicies(),
+                new PdpMessageHandler().getToscaPolicyIdentifiers(pdpUpdateMsg.getPolicies()));
+        assertTrue(outString.contains("Apex engine started and policies are running."));
+    }
+
+    @Test
+    public void testPdpUpdateMssageListener_undeploy() throws InterruptedException, CoderException {
+        final PdpStatus pdpStatus = Registry.get(ApexStarterConstants.REG_PDP_STATUS_OBJECT);
+        pdpUpdateMessageListener.onTopicEvent(INFRA, TOPIC, null,
+            TestListenerUtils.createPdpUpdateMsg(pdpStatus, new ArrayList<ToscaPolicy>()));
+        PdpStateChange pdpStateChangeMsg =
+            TestListenerUtils.createPdpStateChangeMsg(PdpState.ACTIVE, "pdpGroup", "pdpSubgroup", pdpStatus.getName());
+        pdpStateChangeListener.onTopicEvent(INFRA, TOPIC, null, pdpStateChangeMsg);
+        final ToscaPolicy toscaPolicy =
+            TestListenerUtils.createToscaPolicy("apex policy name", "1.0", "src/test/resources/dummyProperties.json");
+        final List<ToscaPolicy> toscaPolicies = new ArrayList<ToscaPolicy>();
+        toscaPolicies.add(toscaPolicy);
+        final PdpUpdate pdpUpdateMsg = TestListenerUtils.createPdpUpdateMsg(pdpStatus, toscaPolicies);
+        pdpUpdateMessageListener.onTopicEvent(INFRA, TOPIC, null, pdpUpdateMsg);
+        OutputStream outContent = new ByteArrayOutputStream();
+        System.setOut(new PrintStream(outContent));
+        pdpUpdateMessageListener.onTopicEvent(INFRA, TOPIC, null,
+            TestListenerUtils.createPdpUpdateMsg(pdpStatus, new ArrayList<ToscaPolicy>()));
+        final String outString = outContent.toString();
+        assertTrue(outString.contains("Pdp update successful. No policies are running."));
+
+    }
+
+    @Test
+    public void testPdpUpdateMssageListener_multi_policy_duplicate()
+        throws InterruptedException, ApexStarterException, CoderException {
+        OutputStream outContent = new ByteArrayOutputStream();
+        System.setOut(new PrintStream(outContent));
+        final PdpStatus pdpStatus = Registry.get(ApexStarterConstants.REG_PDP_STATUS_OBJECT);
+        final ToscaPolicy toscaPolicy =
+            TestListenerUtils.createToscaPolicy("apex policy name", "1.0", "src/test/resources/dummyProperties.json");
+        final ToscaPolicy toscaPolicy2 =
+            TestListenerUtils.createToscaPolicy("apexpolicy2", "1.0", "src/test/resources/dummyProperties.json");
+        final List<ToscaPolicy> toscaPolicies = new ArrayList<ToscaPolicy>();
+        toscaPolicies.add(toscaPolicy);
+        toscaPolicies.add(toscaPolicy2);
+        final PdpUpdate pdpUpdateMsg = TestListenerUtils.createPdpUpdateMsg(pdpStatus, toscaPolicies);
+        pdpUpdateMessageListener.onTopicEvent(INFRA, TOPIC, null, pdpUpdateMsg);
+        PdpStateChange pdpStateChangeMsg =
+            TestListenerUtils.createPdpStateChangeMsg(PdpState.ACTIVE, "pdpGroup", "pdpSubgroup", pdpStatus.getName());
+        pdpStateChangeListener.onTopicEvent(INFRA, TOPIC, null, pdpStateChangeMsg);
+        final String outString = outContent.toString();
+        assertTrue(outString.contains(
+            "Apex engine started. But, only the following polices are running - apex policy name:1.0  . "
+            + "Other policies failed execution. Please see the logs for more details."));
+    }
 }
diff --git a/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/parameters/dummyclasses/DummyStateFinalizerExecutor.java b/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/parameters/dummyclasses/DummyStateFinalizerExecutor.java
new file mode 100644
index 0000000..cdbd27b
--- /dev/null
+++ b/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/parameters/dummyclasses/DummyStateFinalizerExecutor.java
@@ -0,0 +1,42 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2018 Ericsson. All rights reserved.
+ *  Modifications Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.services.onappf.parameters.dummyclasses;
+
+import java.util.Map;
+import java.util.Properties;
+import org.onap.policy.apex.context.ContextException;
+import org.onap.policy.apex.core.engine.executor.StateFinalizerExecutor;
+import org.onap.policy.apex.core.engine.executor.exception.StateMachineException;
+
+/**
+ * Dummy state finalizer executor for testing.
+ */
+public class DummyStateFinalizerExecutor extends StateFinalizerExecutor {
+    public DummyStateFinalizerExecutor() {}
+
+    @Override
+    public String execute(final long executionId, final Properties executorProperties,
+            final Map<String, Object> newIncomingFields) throws StateMachineException, ContextException {
+
+        return "stateOutput0";
+    }
+}
diff --git a/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/parameters/dummyclasses/DummyTaskExecutor.java b/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/parameters/dummyclasses/DummyTaskExecutor.java
new file mode 100644
index 0000000..d3fa9b5
--- /dev/null
+++ b/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/parameters/dummyclasses/DummyTaskExecutor.java
@@ -0,0 +1,58 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2018 Ericsson. All rights reserved.
+ *  Modifications Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.services.onappf.parameters.dummyclasses;
+
+import java.util.Map;
+import java.util.Properties;
+import org.onap.policy.apex.context.ContextException;
+import org.onap.policy.apex.core.engine.event.EnEvent;
+import org.onap.policy.apex.core.engine.executor.TaskExecutor;
+import org.onap.policy.apex.core.engine.executor.exception.StateMachineException;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.policy.apex.model.policymodel.concepts.AxTask;
+
+/**
+ * Dummy task executor for testing.
+ */
+public class DummyTaskExecutor extends TaskExecutor {
+    public DummyTaskExecutor() {}
+
+    @Override
+    public void prepare() throws StateMachineException {}
+
+    @Override
+    public Map<String, Object> execute(final long executionId, final Properties executorProperties,
+            final Map<String, Object> newIncomingFields) throws StateMachineException, ContextException {
+
+        AxArtifactKey event0Key = new AxArtifactKey("Event0:0.0.1");
+        return new EnEvent(event0Key);
+    }
+
+    @Override
+    public AxTask getSubject() {
+        AxArtifactKey taskKey = new AxArtifactKey("FirstTask:0.0.1");
+        return new AxTask(taskKey);
+    }
+
+    @Override
+    public void cleanUp() throws StateMachineException {}
+}
diff --git a/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/parameters/dummyclasses/DummyTaskSelectExecutor.java b/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/parameters/dummyclasses/DummyTaskSelectExecutor.java
new file mode 100644
index 0000000..b27ff6e
--- /dev/null
+++ b/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/parameters/dummyclasses/DummyTaskSelectExecutor.java
@@ -0,0 +1,49 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2018 Ericsson. All rights reserved.
+ *  Modifications Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.services.onappf.parameters.dummyclasses;
+
+import java.util.Properties;
+import org.onap.policy.apex.context.ContextException;
+import org.onap.policy.apex.core.engine.event.EnEvent;
+import org.onap.policy.apex.core.engine.executor.TaskSelectExecutor;
+import org.onap.policy.apex.core.engine.executor.exception.StateMachineException;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+
+/**
+ * Dummy task selection executor for testing.
+ */
+public class DummyTaskSelectExecutor extends TaskSelectExecutor {
+    public DummyTaskSelectExecutor() {}
+
+    @Override
+    public void prepare() throws StateMachineException {}
+
+    @Override
+    public AxArtifactKey execute(final long executionId, final Properties executorProperties,
+            final EnEvent newIncomingEvent) throws StateMachineException, ContextException {
+
+        return new AxArtifactKey("task:0.0.1");
+    }
+
+    @Override
+    public void cleanUp() throws StateMachineException {}
+}
diff --git a/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/parameters/dummyclasses/SuperDooperExecutorParameters.java b/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/parameters/dummyclasses/SuperDooperExecutorParameters.java
new file mode 100644
index 0000000..cbcd23c
--- /dev/null
+++ b/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/parameters/dummyclasses/SuperDooperExecutorParameters.java
@@ -0,0 +1,39 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
+ *  Modifications Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.services.onappf.parameters.dummyclasses;
+
+import org.onap.policy.apex.core.engine.ExecutorParameters;
+
+/**
+ * Dummy executor parameters.
+ */
+public class SuperDooperExecutorParameters extends ExecutorParameters {
+
+    /**
+     * Instantiates a new super dooper executor parameters.
+     */
+    public SuperDooperExecutorParameters() {
+        this.setTaskExecutorPluginClass(DummyTaskExecutor.class.getName());
+        this.setTaskSelectionExecutorPluginClass(DummyTaskSelectExecutor.class.getName());
+        this.setStateFinalizerExecutorPluginClass(DummyStateFinalizerExecutor.class.getName());
+    }
+}
diff --git a/services/services-onappf/src/test/resources/ApexStarterConfigParametersNoop.json b/services/services-onappf/src/test/resources/ApexStarterConfigParametersNoop.json
new file mode 100644
index 0000000..bce20da
--- /dev/null
+++ b/services/services-onappf/src/test/resources/ApexStarterConfigParametersNoop.json
@@ -0,0 +1,28 @@
+{
+    "name":"ApexStarterParameterGroup",
+    "restServerParameters": {
+        "host": "0.0.0.0",
+        "port": 6969,
+        "userName": "healthcheck",
+        "password": "zb!XztG34",
+        "https": true
+    },
+    "pdpStatusParameters":{
+        "timeIntervalMs": 120000,
+        "pdpType":"apex",
+        "description":"Pdp Heartbeat",
+        "supportedPolicyTypes":[{"name":"onap.policies.controlloop.operational.Apex","version":"1.0.0"}]
+    },
+    "topicParameterGroup": {
+        "topicSources" : [ {
+            "topic" : "my-topic",
+            "servers" : [ "my-server" ],
+            "topicCommInfrastructure" : "noop"
+        }],
+        "topicSinks" : [ {
+            "topic" : "my-topic",
+            "servers" : [ "my-server" ],
+            "topicCommInfrastructure" : "noop"
+        }]
+    }
+}
\ No newline at end of file
diff --git a/services/services-onappf/src/test/resources/TestPojoEvent.json b/services/services-onappf/src/test/resources/TestPojoEvent.json
new file mode 100644
index 0000000..ce2cb2b
--- /dev/null
+++ b/services/services-onappf/src/test/resources/TestPojoEvent.json
@@ -0,0 +1,15 @@
+{
+    "anInt": 1,
+    "anInteger": 2,
+    "someString": "a string",
+    "testSubPojo": {
+        "anInt": 10,
+        "anInteger": 20,
+        "someString": "a sub string",
+        "testSubSubPojo": {
+            "anInt": 100,
+            "anInteger": 200,
+            "someString": "a sub sub string"
+        }
+    }
+}
diff --git a/services/services-onappf/src/test/resources/dummyProperties.json b/services/services-onappf/src/test/resources/dummyProperties.json
index 849b86e..daf2d50 100644
--- a/services/services-onappf/src/test/resources/dummyProperties.json
+++ b/services/services-onappf/src/test/resources/dummyProperties.json
@@ -1,43 +1,497 @@
 {
-    "engineServiceParameters": {
-        "name": "MyApexEngine",
-        "version": "0.0.1",
-        "id": 45,
-        "instanceCount": 2,
-        "deploymentPort": 65522,
-        "policy_type_impl": "onap.policies.controlloop.operational.apex.sampledomain.Impl",
-        "engineParameters": {
-            "executorParameters": {
-                "JAVASCRIPT": {
-                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+  "engineServiceParameters": {
+    "name": "MyApexEngine",
+    "version": "0.0.1",
+    "id": 45,
+    "instanceCount": 2,
+    "deploymentPort": 65522,
+    "policy_type_impl": {
+      "apexPolicyModel": {
+        "key": {
+          "name": "SmallModel",
+          "version": "0.0.1"
+        },
+        "keyInformation": {
+          "key": {
+            "name": "SmallModel_KeyInfo",
+            "version": "0.0.1"
+          },
+          "keyInfoMap": {
+            "entry": [
+              {
+                "key": {
+                  "name": "BasicContextAlbum",
+                  "version": "0.0.1"
+                },
+                "value": {
+                  "key": {
+                    "name": "BasicContextAlbum",
+                    "version": "0.0.1"
+                  },
+                  "UUID": "fec1b353-b35f-4384-b7d9-69622059c248",
+                  "description": "Generated description for a concept called \"BasicContextAlbum\" with version \"0.0.1\" and UUID \"fec1b353-b35f-4384-b7d9-69622059c248\""
                 }
-            }
+              },
+              {
+                "key": {
+                  "name": "BasicEvent",
+                  "version": "0.0.1"
+                },
+                "value": {
+                  "key": {
+                    "name": "BasicEvent",
+                    "version": "0.0.1"
+                  },
+                  "UUID": "cc8d3c1a-e975-459a-bcd2-69f423eaa1f3",
+                  "description": "Generated description for a concept called \"BasicEvent\" with version \"0.0.1\" and UUID \"cc8d3c1a-e975-459a-bcd2-69f423eaa1f3\""
+                }
+              },
+              {
+                "key": {
+                  "name": "BasicPolicy",
+                  "version": "0.0.1"
+                },
+                "value": {
+                  "key": {
+                    "name": "BasicPolicy",
+                    "version": "0.0.1"
+                  },
+                  "UUID": "d0c5d8ee-5fe7-4978-89ce-4a3e69cad043",
+                  "description": "Generated description for a concept called \"BasicPolicy\" with version \"0.0.1\" and UUID \"d0c5d8ee-5fe7-4978-89ce-4a3e69cad043\""
+                }
+              },
+              {
+                "key": {
+                  "name": "BasicTask",
+                  "version": "0.0.1"
+                },
+                "value": {
+                  "key": {
+                    "name": "BasicTask",
+                    "version": "0.0.1"
+                  },
+                  "UUID": "c5651414-fc1c-493b-878d-75f0ce685c36",
+                  "description": "Generated description for a concept called \"BasicTask\" with version \"0.0.1\" and UUID \"c5651414-fc1c-493b-878d-75f0ce685c36\""
+                }
+              },
+              {
+                "key": {
+                  "name": "IntType",
+                  "version": "0.0.1"
+                },
+                "value": {
+                  "key": {
+                    "name": "IntType",
+                    "version": "0.0.1"
+                  },
+                  "UUID": "790ff718-8dc0-44e0-89d8-1b3bbe238310",
+                  "description": "Generated description for a concept called \"IntType\" with version \"0.0.1\" and UUID \"790ff718-8dc0-44e0-89d8-1b3bbe238310\""
+                }
+              },
+              {
+                "key": {
+                  "name": "SmallModel",
+                  "version": "0.0.1"
+                },
+                "value": {
+                  "key": {
+                    "name": "SmallModel",
+                    "version": "0.0.1"
+                  },
+                  "UUID": "a1bd1f4e-713b-456b-b1a8-bb48beee28e8",
+                  "description": "Generated description for a concept called \"SmallModel\" with version \"0.0.1\" and UUID \"a1bd1f4e-713b-456b-b1a8-bb48beee28e8\""
+                }
+              },
+              {
+                "key": {
+                  "name": "SmallModel_Albums",
+                  "version": "0.0.1"
+                },
+                "value": {
+                  "key": {
+                    "name": "SmallModel_Albums",
+                    "version": "0.0.1"
+                  },
+                  "UUID": "72bed9af-ab7d-3379-b9f7-b5eca5c9ef22",
+                  "description": "Generated description for concept referred to by key \"SmallModel_Albums:0.0.1\""
+                }
+              },
+              {
+                "key": {
+                  "name": "SmallModel_Events",
+                  "version": "0.0.1"
+                },
+                "value": {
+                  "key": {
+                    "name": "SmallModel_Events",
+                    "version": "0.0.1"
+                  },
+                  "UUID": "796dc6b0-627d-34ae-a5e2-1bc4b4b486b8",
+                  "description": "Generated description for concept referred to by key \"SmallModel_Events:0.0.1\""
+                }
+              },
+              {
+                "key": {
+                  "name": "SmallModel_KeyInfo",
+                  "version": "0.0.1"
+                },
+                "value": {
+                  "key": {
+                    "name": "SmallModel_KeyInfo",
+                    "version": "0.0.1"
+                  },
+                  "UUID": "b4876774-6907-3d27-a2b8-f05737c5ee4a",
+                  "description": "Generated description for concept referred to by key \"SmallModel_KeyInfo:0.0.1\""
+                }
+              },
+              {
+                "key": {
+                  "name": "SmallModel_Policies",
+                  "version": "0.0.1"
+                },
+                "value": {
+                  "key": {
+                    "name": "SmallModel_Policies",
+                    "version": "0.0.1"
+                  },
+                  "UUID": "5bcf946b-67be-3190-a906-f954896f999f",
+                  "description": "Generated description for concept referred to by key \"SmallModel_Policies:0.0.1\""
+                }
+              },
+              {
+                "key": {
+                  "name": "SmallModel_Schemas",
+                  "version": "0.0.1"
+                },
+                "value": {
+                  "key": {
+                    "name": "SmallModel_Schemas",
+                    "version": "0.0.1"
+                  },
+                  "UUID": "c25bf5c3-7f1e-3667-b8a9-971ba21517bc",
+                  "description": "Generated description for concept referred to by key \"SmallModel_Schemas:0.0.1\""
+                }
+              },
+              {
+                "key": {
+                  "name": "SmallModel_Tasks",
+                  "version": "0.0.1"
+                },
+                "value": {
+                  "key": {
+                    "name": "SmallModel_Tasks",
+                    "version": "0.0.1"
+                  },
+                  "UUID": "43b015ca-2ed1-3a35-b103-e8a5aa68f1ef",
+                  "description": "Generated description for concept referred to by key \"SmallModel_Tasks:0.0.1\""
+                }
+              }
+            ]
+          }
+        },
+        "policies": {
+          "key": {
+            "name": "SmallModel_Policies",
+            "version": "0.0.1"
+          },
+          "policyMap": {
+            "entry": [
+              {
+                "key": {
+                  "name": "BasicPolicy",
+                  "version": "0.0.1"
+                },
+                "value": {
+                  "policyKey": {
+                    "name": "BasicPolicy",
+                    "version": "0.0.1"
+                  },
+                  "template": "FREEFORM",
+                  "state": {
+                    "entry": [
+                      {
+                        "key": "OnlyState",
+                        "value": {
+                          "stateKey": {
+                            "parentKeyName": "BasicPolicy",
+                            "parentKeyVersion": "0.0.1",
+                            "parentLocalName": "NULL",
+                            "localName": "OnlyState"
+                          },
+                          "trigger": {
+                            "name": "BasicEvent",
+                            "version": "0.0.1"
+                          },
+                          "stateOutputs": {
+                            "entry": [
+                              {
+                                "key": "OnlyOutput",
+                                "value": {
+                                  "key": {
+                                    "parentKeyName": "BasicPolicy",
+                                    "parentKeyVersion": "0.0.1",
+                                    "parentLocalName": "OnlyState",
+                                    "localName": "OnlyOutput"
+                                  },
+                                  "outgoingEvent": {
+                                    "name": "BasicEvent",
+                                    "version": "0.0.1"
+                                  },
+                                  "nextState": {
+                                    "parentKeyName": "NULL",
+                                    "parentKeyVersion": "0.0.0",
+                                    "parentLocalName": "NULL",
+                                    "localName": "NULL"
+                                  }
+                                }
+                              }
+                            ]
+                          },
+                          "contextAlbumReference": [
+                            {
+                              "name": "BasicContextAlbum",
+                              "version": "0.0.1"
+                            }
+                          ],
+                          "taskSelectionLogic": {
+                            "key": "NULL",
+                            "logicFlavour": "UNDEFINED",
+                            "logic": ""
+                          },
+                          "stateFinalizerLogicMap": {
+                            "entry": []
+                          },
+                          "defaultTask": {
+                            "name": "BasicTask",
+                            "version": "0.0.1"
+                          },
+                          "taskReferences": {
+                            "entry": [
+                              {
+                                "key": {
+                                  "name": "BasicTask",
+                                  "version": "0.0.1"
+                                },
+                                "value": {
+                                  "key": {
+                                    "parentKeyName": "BasicPolicy",
+                                    "parentKeyVersion": "0.0.1",
+                                    "parentLocalName": "OnlyState",
+                                    "localName": "BasicTask"
+                                  },
+                                  "outputType": "DIRECT",
+                                  "output": {
+                                    "parentKeyName": "BasicPolicy",
+                                    "parentKeyVersion": "0.0.1",
+                                    "parentLocalName": "OnlyState",
+                                    "localName": "OnlyOutput"
+                                  }
+                                }
+                              }
+                            ]
+                          }
+                        }
+                      }
+                    ]
+                  },
+                  "firstState": "OnlyState"
+                }
+              }
+            ]
+          }
+        },
+        "tasks": {
+          "key": {
+            "name": "SmallModel_Tasks",
+            "version": "0.0.1"
+          },
+          "taskMap": {
+            "entry": [
+              {
+                "key": {
+                  "name": "BasicTask",
+                  "version": "0.0.1"
+                },
+                "value": {
+                  "key": {
+                    "name": "BasicTask",
+                    "version": "0.0.1"
+                  },
+                  "inputFields": {
+                    "entry": [
+                      {
+                        "key": "intPar",
+                        "value": {
+                          "key": "intPar",
+                          "fieldSchemaKey": {
+                            "name": "IntType",
+                            "version": "0.0.1"
+                          },
+                          "optional": false
+                        }
+                      }
+                    ]
+                  },
+                  "outputFields": {
+                    "entry": [
+                      {
+                        "key": "intPar",
+                        "value": {
+                          "key": "intPar",
+                          "fieldSchemaKey": {
+                            "name": "IntType",
+                            "version": "0.0.1"
+                          },
+                          "optional": false
+                        }
+                      }
+                    ]
+                  },
+                  "taskParameters": {
+                    "entry": []
+                  },
+                  "contextAlbumReference": [
+                    {
+                      "name": "BasicContextAlbum",
+                      "version": "0.0.1"
+                    }
+                  ],
+                  "taskLogic": {
+                    "key": "TaskLogic",
+                    "logicFlavour": "JAVASCRIPT",
+                    "logic": "executor.logger.debug(executor.subject.id);\nvar gc = executor.getContextAlbum(\"BasicContextAlbum\");\nexecutor.logger.debug(gc.name);\nexecutor.logger.debug(executor.inFields);\n\nexecutor.logger.debug(executor.eo);\n\nvar returnValue = executor.isTrue;"
+                  }
+                }
+              }
+            ]
+          }
+        },
+        "events": {
+          "key": {
+            "name": "SmallModel_Events",
+            "version": "0.0.1"
+          },
+          "eventMap": {
+            "entry": [
+              {
+                "key": {
+                  "name": "BasicEvent",
+                  "version": "0.0.1"
+                },
+                "value": {
+                  "key": {
+                    "name": "BasicEvent",
+                    "version": "0.0.1"
+                  },
+                  "nameSpace": "org.onap.policy.apex.events",
+                  "source": "source",
+                  "target": "target",
+                  "parameter": {
+                    "entry": [
+                      {
+                        "key": "intPar",
+                        "value": {
+                          "key": "intPar",
+                          "fieldSchemaKey": {
+                            "name": "IntType",
+                            "version": "0.0.1"
+                          },
+                          "optional": false
+                        }
+                      }
+                    ]
+                  }
+                }
+              }
+            ]
+          }
+        },
+        "albums": {
+          "key": {
+            "name": "SmallModel_Albums",
+            "version": "0.0.1"
+          },
+          "albums": {
+            "entry": [
+              {
+                "key": {
+                  "name": "BasicContextAlbum",
+                  "version": "0.0.1"
+                },
+                "value": {
+                  "key": {
+                    "name": "BasicContextAlbum",
+                    "version": "0.0.1"
+                  },
+                  "scope": "GLOBAL",
+                  "isWritable": true,
+                  "itemSchema": {
+                    "name": "IntType",
+                    "version": "0.0.1"
+                  }
+                }
+              }
+            ]
+          }
+        },
+        "schemas": {
+          "key": {
+            "name": "SmallModel_Schemas",
+            "version": "0.0.1"
+          },
+          "schemas": {
+            "entry": [
+              {
+                "key": {
+                  "name": "IntType",
+                  "version": "0.0.1"
+                },
+                "value": {
+                  "key": {
+                    "name": "IntType",
+                    "version": "0.0.1"
+                  },
+                  "schemaFlavour": "Java",
+                  "schemaDefinition": "java.lang.Integer"
+                }
+              }
+            ]
+          }
         }
+      }
     },
-    "eventOutputParameters": {
-        "FirstProducer": {
-            "carrierTechnologyParameters": {
-                "carrierTechnology": "FILE",
-                "parameters": {
-                    "standardIo": true
-                }
-            },
-            "eventProtocolParameters": {
-                "eventProtocol": "JSON"
-            }
+    "engineParameters": {
+      "executorParameters": {
+        "JAVASCRIPT": {
+          "parameterClassName": "org.onap.policy.apex.services.onappf.parameters.dummyclasses.SuperDooperExecutorParameters"
         }
-    },
-    "eventInputParameters": {
-        "TheFileConsumer1": {
-            "carrierTechnologyParameters": {
-                "carrierTechnology": "FILE",
-                "parameters": {
-                    "fileName": "src/test/resources/events/TestPojoEvent.json"
-                }
-            },
-            "eventProtocolParameters": {
-                "eventProtocol": "JSON"
-            }
-        }
+      }
     }
+  },
+  "eventOutputParameters": {
+    "FirstProducer": {
+      "carrierTechnologyParameters": {
+        "carrierTechnology": "FILE",
+        "parameters": {
+          "standardIo": true
+        }
+      },
+      "eventProtocolParameters": {
+        "eventProtocol": "JSON"
+      }
+    }
+  },
+  "eventInputParameters": {
+    "TheFileConsumer1": {
+      "carrierTechnologyParameters": {
+        "carrierTechnology": "FILE",
+        "parameters": {
+          "fileName": "src/test/resources/TestPojoEvent.json"
+        }
+      },
+      "eventProtocolParameters": {
+        "eventProtocol": "JSON"
+      }
+    }
+  }
 }
\ No newline at end of file