--- /dev/null
+/*-
+ * ============LICENSE_START=======================================================
+ * policy engine
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.drools;
+
+public interface PolicyEngineListener {
+    
+    /**
+     * Any class that implements this interface will
+     * be notified of a new event on the queue in the
+     * PolicyEngineJUnitImpl 
+     * 
+     * @param topic a key to the queue that contains
+     *        the event
+     */
+    public void newEventNotification(String topic);
+
+}
 
 
 package org.onap.policy.drools.impl;
 
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.LinkedList;
+import java.util.List;
 import java.util.Map;
 import java.util.Queue;
 
 import org.slf4j.LoggerFactory;
 
 import org.onap.policy.drools.PolicyEngine;
+import org.onap.policy.drools.PolicyEngineListener;
 
 public class PolicyEngineJUnitImpl implements PolicyEngine {
 
        private static final Logger logger = LoggerFactory.getLogger(PolicyEngineJUnitImpl.class);
        private Map<String, Map<String, Queue<Object>>> busMap = new HashMap<String, Map<String, Queue<Object>>>();
-
+       private List<PolicyEngineListener> listeners = new ArrayList<>();
+       
+       /**
+        * Adds all objects that implement PolicyEngineListener
+     * to the notification list when an event occurs
+     * 
+        * @param listener an object that is interest in knowing
+        * about events published to the PolicyEngine
+        */
+       public void addListener(PolicyEngineListener listener) {
+           listeners.add(listener);
+       }
+       
+       /**
+        * Notifies all listeners about a new event
+        * @param topic the topic in which the notification
+        * was sent to
+        */
+       public void notifyListeners(String topic) {
+           for (PolicyEngineListener listener: listeners) {
+               listener.newEventNotification(topic);
+           }
+       }
+       
        @Override
        public boolean deliver(String busType, String topic, Object obj) {
                if (obj instanceof ControlLoopNotification) {
                }
                if (obj instanceof Request) {
                        Request request = (Request) obj;
-                       logger.debug("Request: {} subrequst {}", request.Action, request.CommonHeader.SubRequestID);
+                       logger.debug("Request: {} subrequest {}", request.Action, request.CommonHeader.SubRequestID);
                }
                else if (obj instanceof LCMRequestWrapper) {
                    LCMRequestWrapper dmaapRequest = (LCMRequestWrapper) obj;
                // Get the topic queue
                //
                logger.debug("queueing");
-               return topicMap.get(topic).add(obj);
+               boolean res = topicMap.get(topic).add(obj);
+               notifyListeners(topic);
+               return res;
        }
        
        public Object   subscribe(String busType, String topic) {
 
+++ /dev/null
-/*-
- * ============LICENSE_START=======================================================
- * demo
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *      http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-package org.onap.policy.template.demo;
-
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.io.IOException;
-import java.net.URLEncoder;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.time.Instant;
-import java.util.HashMap;
-import java.util.UUID;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.kie.api.KieServices;
-import org.kie.api.builder.KieBuilder;
-import org.kie.api.builder.KieFileSystem;
-import org.kie.api.builder.Message;
-import org.kie.api.builder.ReleaseId;
-import org.kie.api.builder.Results;
-import org.kie.api.builder.model.KieModuleModel;
-import org.kie.api.runtime.KieContainer;
-import org.kie.api.runtime.KieSession;
-import org.kie.api.runtime.rule.FactHandle;
-import org.onap.policy.controlloop.ControlLoopEventStatus;
-import org.onap.policy.controlloop.ControlLoopLogger;
-import org.onap.policy.controlloop.ControlLoopTargetType;
-import org.onap.policy.controlloop.VirtualControlLoopEvent;
-import org.onap.policy.controlloop.impl.ControlLoopLoggerStdOutImpl;
-import org.onap.policy.controlloop.policy.ControlLoopPolicy;
-import org.onap.policy.drools.http.server.HttpServletServer;
-import org.onap.policy.drools.impl.PolicyEngineJUnitImpl;
-import org.onap.policy.so.util.Serialization;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-
-public class TestSO {
-
-       private static final Logger log = LoggerFactory.getLogger(TestSO.class);
-       
-       static{
-                /* Set environment properties */
-                Util.setAAIProps();
-                Util.setSOProps();
-                Util.setPUProp();
-       }
-       
-       @BeforeClass
-       public static void setUpSimulator() {
-               try {
-                       Util.buildAaiSim();
-                       Util.buildSoSim();
-                       Util.buildGuardSim();
-               } catch (Exception e) {
-                       fail(e.getMessage());
-               }
-       }
-
-       @AfterClass
-       public static void tearDownSimulator() {
-               HttpServletServer.factory.destroy();
-       }
-       
-       @Test
-       public void testvDNS() throws IOException {
-               
-               final String yaml = "src/test/resources/yaml/policy_ControlLoop_SO-test.yaml";
-               
-               //
-               // Pull info from the yaml
-               //
-               final Util.Pair<ControlLoopPolicy, String> pair = Util.loadYaml(yaml);
-               assertNotNull(pair);
-               assertNotNull(pair.a);
-               assertNotNull(pair.a.getControlLoop());
-               assertNotNull(pair.a.getControlLoop().getControlLoopName());
-               assertTrue(pair.a.getControlLoop().getControlLoopName().length() > 0);
-
-               //
-               // Build a container
-               //
-               final String closedLoopControlName = pair.a.getControlLoop().getControlLoopName();
-               final KieSession kieSession = buildContainer("src/main/resources/ControlLoop_Template_xacml_guard.drl", 
-                               closedLoopControlName, 
-                               "type=operational", 
-                               "myVDNSDemoPolicy", 
-                               "v1.0",
-                               "SO",
-                               "POLICY-CL-MGT",
-                               "APPC-CL",
-                               URLEncoder.encode(pair.b, "UTF-8")
-                               );
-               
-               log.debug("============ PRINTING YAML ============");
-               log.debug(URLEncoder.encode(pair.b, "UTF-8"));
-               log.debug("================ DONE =================");
-
-               //
-               // Insert our globals
-               //
-               final ControlLoopLogger logger = new ControlLoopLoggerStdOutImpl();
-               kieSession.setGlobal("Logger", logger);
-               final PolicyEngineJUnitImpl engine = new PolicyEngineJUnitImpl();
-               kieSession.setGlobal("Engine", engine);
-
-               //
-               // Initial fire of rules
-               //
-               kieSession.fireAllRules();
-               //
-               // Kick a thread that starts testing
-               //
-               new Thread(new Runnable() {
-
-                       @Override
-                       public void run() {
-
-                               log.debug("\n************ Starting vDNS Test *************\n");
-
-                               //
-                               // Generate an invalid DCAE Event with requestID=null
-                               //
-                               VirtualControlLoopEvent invalidEvent = new VirtualControlLoopEvent();
-                               invalidEvent.closedLoopControlName = closedLoopControlName;
-                               invalidEvent.requestID = null;
-                               invalidEvent.closedLoopEventClient = "tca.instance00001";
-                               invalidEvent.target_type = ControlLoopTargetType.VNF;
-                               invalidEvent.target = "generic-vnf.vnf-id";
-                               invalidEvent.from = "DCAE";
-                               invalidEvent.closedLoopAlarmStart = Instant.now();
-                               invalidEvent.AAI = new HashMap<String, String>();
-                               invalidEvent.AAI.put("vserver.vserver-name", "vserver-name-16102016-aai3255-data-11-1");
-                               invalidEvent.closedLoopEventStatus = ControlLoopEventStatus.ONSET;
-                               
-                               log.debug("-------- Sending Invalid ONSET --------");
-                               log.debug(Serialization.gsonPretty.toJson(invalidEvent));
-                               
-                               //
-                               // Insert invalid DCAE Event into memory
-                               //
-                               kieSession.insert(invalidEvent);        
-                               try {
-                                       Thread.sleep(500);
-                               } catch (InterruptedException e) {
-                               }
-                               //
-                               // Generate first DCAE ONSET Event
-                               //
-                               VirtualControlLoopEvent onsetEvent = new VirtualControlLoopEvent();
-                               onsetEvent.closedLoopControlName = closedLoopControlName;
-                               onsetEvent.requestID = UUID.randomUUID();
-                               onsetEvent.closedLoopEventClient = "tca.instance00001";
-                               onsetEvent.target_type = ControlLoopTargetType.VNF;
-                               onsetEvent.target = "VNF_NAME";
-                               onsetEvent.from = "DCAE";
-                               onsetEvent.closedLoopAlarmStart = Instant.now();
-                               onsetEvent.AAI = new HashMap<String, String>();
-                               onsetEvent.AAI.put("vserver.vserver-name", "vserver-name-16102016-aai3255-data-11-1");
-                               onsetEvent.AAI.put("vserver.is-closed-loop-disabled", "false");
-                               onsetEvent.closedLoopEventStatus = ControlLoopEventStatus.ONSET;
-                               
-                               log.debug("-------- Sending Valid ONSET --------");
-                               log.debug(Serialization.gsonPretty.toJson(onsetEvent));
-                               
-                               //
-                               // Insert first DCAE ONSET Event into memory
-                               //
-                               kieSession.insert(onsetEvent);
-                               //
-                               // We have test for subsequent ONSET Events in testvFirewall()
-                               // So no need to test it again here
-                               //
-                               try {
-                                       Thread.sleep(10000);
-                               } catch (InterruptedException e) {
-                               }
-                               //
-                               // Test is finished, so stop the kieSession
-                               //
-                               kieSession.halt();
-                       }
-               //
-               }).start();
-               //
-               // Start firing rules
-               //
-               kieSession.fireUntilHalt();
-               //
-               // Dump working memory
-               //
-               dumpFacts(kieSession);
-               
-               //
-               // See if there is anything left in memory, there SHOULD only be
-               // a params fact.
-               //
-               // assertEquals("There should only be 1 Fact left in memory.", 1, kieSession.getFactCount());
-               if (kieSession.getFactCount() != 1L) {
-                   log.error("FACT count mismatch: 1 expected but there are {}", kieSession.getFactCount());
-               }
-               for (FactHandle handle : kieSession.getFactHandles()) {
-                       Object fact = kieSession.getObject(handle);
-                       // assertEquals("Non-Param Fact left in working memory", "org.onap.policy.controlloop.Params", fact.getClass().getName());
-                       log.info("Working Memory FACT: {}", fact.getClass().getName());
-               }
-               
-       }
-               
-       public static void dumpFacts(KieSession kieSession) {
-               log.debug("Fact Count: " + kieSession.getFactCount());
-               for (FactHandle handle : kieSession.getFactHandles()) {
-                       log.debug("FACT: " + handle);
-               }
-       }
-
-       public static KieSession buildContainer(String droolsTemplate, 
-                       String closedLoopControlName, 
-                       String policyScope, 
-                       String policyName, 
-                       String policyVersion, 
-                       String actor, 
-                       String notificationTopic,
-                       String appcTopic,
-                       String yamlSpecification) throws IOException {
-               //
-       // Get our Drools Kie factory
-       //
-        KieServices ks = KieServices.Factory.get();
-        
-        KieModuleModel kModule = ks.newKieModuleModel();
-        
-        log.debug("KMODULE:" + System.lineSeparator() + kModule.toXML());
-        
-        //
-        // Generate our drools rule from our template
-        //
-        KieFileSystem kfs = ks.newKieFileSystem();
-        
-        kfs.writeKModuleXML(kModule.toXML());
-        {
-               Path rule = Paths.get(droolsTemplate);
-               String ruleTemplate = new String(Files.readAllBytes(rule));
-               String drlContents = generatePolicy(ruleTemplate,
-                                                               closedLoopControlName,
-                                                               policyScope,
-                                                                       policyName,
-                                                                       policyVersion,
-                                                                       actor,
-                                                                       notificationTopic,
-                                                                       appcTopic,
-                                                                       yamlSpecification
-                                                                       );
-               
-               kfs.write("src/main/resources/" + policyName + ".drl", ks.getResources().newByteArrayResource(drlContents.getBytes()));
-        }
-        //
-        // Compile the rule
-        //
-        KieBuilder builder = ks.newKieBuilder(kfs).buildAll();
-        Results results = builder.getResults();
-        if (results.hasMessages(Message.Level.ERROR)) {
-               for (Message msg : results.getMessages()) {
-                       System.err.println(msg.toString());
-               }
-               throw new RuntimeException("Drools Rule has Errors");
-        }
-       for (Message msg : results.getMessages()) {
-               log.debug(msg.toString());
-       }
-       //
-       // Create our kie Session and container
-       //
-        ReleaseId releaseId = ks.getRepository().getDefaultReleaseId();
-        log.debug("ReleaseId: " + releaseId);
-           KieContainer kContainer = ks.newKieContainer(releaseId);
-           
-           return kContainer.newKieSession();
-       }
-       public static String    generatePolicy(String ruleContents, 
-                       String closedLoopControlName, 
-                       String policyScope, 
-                       String policyName, 
-                       String policyVersion,
-                       String actor,
-                       String notificationTopic,
-                       String appcTopic,
-                       String controlLoopYaml) {
-
-               Pattern p = Pattern.compile("\\$\\{closedLoopControlName\\}");
-               Matcher m = p.matcher(ruleContents);
-               ruleContents = m.replaceAll(closedLoopControlName);
-
-               p = Pattern.compile("\\$\\{policyScope\\}");
-               m = p.matcher(ruleContents);
-               ruleContents = m.replaceAll(policyScope);
-
-               p = Pattern.compile("\\$\\{policyName\\}");
-               m = p.matcher(ruleContents);
-               ruleContents = m.replaceAll(policyName);
-
-               p = Pattern.compile("\\$\\{policyVersion\\}");
-               m = p.matcher(ruleContents);
-               ruleContents = m.replaceAll(policyVersion);
-               
-               p = Pattern.compile("\\$\\{actor\\}");
-               m = p.matcher(ruleContents);
-               ruleContents = m.replaceAll(actor);
-               
-//             p = Pattern.compile("\\$\\{aaiURL\\}");
-//             m = p.matcher(ruleContents);
-//             if (aaiURL == null) {
-//                     ruleContents = m.replaceAll("null");
-//             } else {
-//                     ruleContents = m.replaceAll(aaiURL);
-//             }
-//             
-//             p = Pattern.compile("\\$\\{aaiUsername\\}");
-//             m = p.matcher(ruleContents);
-//             if (aaiUsername == null) {
-//                     ruleContents = m.replaceAll("null");
-//             } else {
-//                     ruleContents = m.replaceAll(aaiUsername);
-//             }
-//
-//             p = Pattern.compile("\\$\\{aaiPassword\\}");
-//             m = p.matcher(ruleContents);
-//             if (aaiPassword == null) {
-//                     ruleContents = m.replaceAll("null");
-//             } else {
-//                     ruleContents = m.replaceAll(aaiPassword);
-//             }
-//
-//             p = Pattern.compile("\\$\\{msoURL\\}");
-//             m = p.matcher(ruleContents);
-//             if (msoURL == null) {
-//                     ruleContents = m.replaceAll("null");
-//             } else {
-//                     ruleContents = m.replaceAll(msoURL);
-//             }
-//
-//             p = Pattern.compile("\\$\\{msoUsername\\}");
-//             m = p.matcher(ruleContents);
-//             if (msoUsername == null) {
-//                     ruleContents = m.replaceAll("null");
-//             } else {
-//                     ruleContents = m.replaceAll(msoUsername);
-//             }
-//
-//             p = Pattern.compile("\\$\\{msoPassword\\}");
-//             m = p.matcher(ruleContents);
-//             if (msoPassword == null) {
-//                     ruleContents = m.replaceAll("null");
-//             } else {
-//                     ruleContents = m.replaceAll(msoPassword);
-//             }
-//
-//             p = Pattern.compile("\\$\\{aaiNamedQueryUUID\\}");
-//             m = p.matcher(ruleContents);
-//             if (aaiNamedQueryUUID == null) {
-//                     ruleContents = m.replaceAll("null");
-//             } else {
-//                     ruleContents = m.replaceAll(aaiNamedQueryUUID);
-//             }
-//
-//             p = Pattern.compile("\\$\\{aaiPatternMatch\\}");
-//             m = p.matcher(ruleContents);
-//             if (aaiPatternMatch == 1) {
-//                     ruleContents = m.replaceAll("1");
-//             } else {
-//                     ruleContents = m.replaceAll("0");
-//             }
-               
-               p = Pattern.compile("\\$\\{notificationTopic\\}");
-               m = p.matcher(ruleContents);
-               if (notificationTopic == null) {
-                       ruleContents = m.replaceAll("null");
-               } else {
-                       ruleContents = m.replaceAll(notificationTopic);
-               }
-               
-               p = Pattern.compile("\\$\\{appcTopic\\}");
-               m = p.matcher(ruleContents);
-               if (appcTopic == null) {
-                       ruleContents = m.replaceAll("null");
-               } else {
-                       ruleContents = m.replaceAll(appcTopic);
-               }
-               
-               p = Pattern.compile("\\$\\{controlLoopYaml\\}");
-               m = p.matcher(ruleContents);
-               ruleContents = m.replaceAll(controlLoopYaml);
-               
-               log.debug(ruleContents);
-
-               return ruleContents;
-       }
-
-}
 
 import org.onap.policy.controlloop.VirtualControlLoopEvent;
 import org.onap.policy.controlloop.VirtualControlLoopNotification;
 import org.onap.policy.controlloop.policy.ControlLoopPolicy;
-import org.onap.policy.controlloop.policy.TargetType;
+import org.onap.policy.drools.PolicyEngineListener;
 import org.onap.policy.drools.http.server.HttpServletServer;
 import org.onap.policy.drools.impl.PolicyEngineJUnitImpl;
-import org.onap.policy.guard.PolicyGuard;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class VCPEControlLoopTest {
+public class VCPEControlLoopTest implements PolicyEngineListener {
 
     private static final Logger logger = LoggerFactory.getLogger(VCPEControlLoopTest.class);
     
     private KieSession kieSession;
     private Util.Pair<ControlLoopPolicy, String> pair;
-    private PolicyEngineJUnitImpl engine;    
+    private PolicyEngineJUnitImpl engine; 
+    private UUID requestID;
     
     static {
         /* Set environment properties */
     
     @Test
     public void successTest() {
-        
         /*
          * Start the kie session
          */
         try {
             kieSession = startSession("src/main/resources/ControlLoop_Template_xacml_guard.drl", 
                         "src/test/resources/yaml/policy_ControlLoop_vCPE.yaml",
-                        "service=ServiceTest;resource=ResourceTest;type=operational", 
+                        "service=ServiceDemo;resource=Res1Demo;type=operational", 
                         "CL_vCPE", 
-                        "org.onap.closed_loop.ServiceTest:VNFS:1.0.0");
+                        "org.onap.closed_loop.ServiceDemo:VNFS:1.0.0");
         } catch (IOException e) {
             e.printStackTrace();
             logger.debug("Could not create kieSession");
         }
         
         /*
-         * Create a thread to continuously fire rules 
-         * until main thread calls halt
-         */      
-        new Thread( new Runnable() {
-            @Override
-            public void run() {
-                kieSession.fireUntilHalt();
-            }
-          } ).start();
-        
-        /*
-         * Create a unique requestId and a unique trigger source
+         * Allows the PolicyEngine to callback to this object to
+         * notify that there is an event ready to be pulled 
+         * from the queue
          */
-        UUID requestID = UUID.randomUUID();
-        String triggerSourceName = "foobartriggersource36";
+        engine.addListener(this);
         
         /*
-         * This will be the object returned from the PolicyEngine
+         * Create a unique requestId
          */
-        Object obj = null;
+        requestID = UUID.randomUUID();
         
         /* 
          * Simulate an onset event the policy engine will 
          * receive from DCAE to kick off processing through
-         * the rules.
-         */
-        try {
-            sendOnset(pair.a, requestID, triggerSourceName);
-        } catch (InterruptedException e) {
-            e.printStackTrace();
-            logger.debug("Unable to send onset event");
-            fail("Unable to send onset event");
-        }
-        
-        /*
-         * Pull the object that was sent out to DMAAP and make
-         * sure it is a ControlLoopNoticiation of type active
-         */
-        obj = engine.subscribe("UEB", "POLICY-CL-MGT");
-        assertNotNull(obj);
-        assertTrue(obj instanceof VirtualControlLoopNotification);
-        assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.ACTIVE));
-        
-        /*
-         * Give the control loop time to acquire a lock
-         */
-        try {
-            Thread.sleep(4000);
-        } catch (InterruptedException e) {
-            e.printStackTrace();
-            logger.debug("An interrupt Exception was thrown");
-            fail("An interrupt Exception was thrown");
-        }
-        
-        /*
-         * The fact should be ready to query guard now to see 
-         * if a ModifyConfig recipe is allowed
-         */
-        obj = engine.subscribe("UEB", "POLICY-CL-MGT");
-        assertNotNull(obj);
-        logger.debug("\n\n####################### GOING TO QUERY GUARD about Restart!!!!!!");
-        logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message);
-        
-        /*
-         * Make sure the object is an instance of a ControlLoopNotification
-         * and is of type operation
+         * the rules
          */
-        assertTrue(obj instanceof VirtualControlLoopNotification);
-        assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION));
-    
-        try {
-            Thread.sleep(4000);
-        } catch (InterruptedException e) {
-            e.printStackTrace();
-            logger.debug("An interrupt Exception was thrown");
-            fail("An interrupt Exception was thrown");
-        }
-        
-        /*
-         * The guard response should be received at this point
-         */
-        obj = engine.subscribe("UEB", "POLICY-CL-MGT");
-        assertNotNull(obj);
-        logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message);
-        
-        /*
-         * The object should be a ControlLoopNotification with type operation
-         */
-        assertTrue(obj instanceof VirtualControlLoopNotification);
-        assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION));
-        
-        /*
-         * See if Guard permits this action, if it does 
-         * not then the test should fail
-         */
-        if (((VirtualControlLoopNotification)obj).message.contains("PERMIT")) {
-            
-            /* 
-             * A notification should be sent out of the Policy
-             * Engine at this point, it will be of type operation
-             */
-            obj = engine.subscribe("UEB", "POLICY-CL-MGT");
-            assertNotNull(obj);
-            logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message);
-            
-            /* A notification should be sent out of the Policy
-             * Engine at this point, it will be of type operation
-             */
-            assertTrue(obj instanceof VirtualControlLoopNotification);
-            assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION));
-            
-            try {
-                Thread.sleep(1000);
-            } catch (InterruptedException e) {
-                e.printStackTrace();
-                logger.debug("An interrupt Exception was thrown");
-                fail("An interrupt Exception was thrown");
-            }
-            
-            /*
-             * Obtain the request sent from the Policy Engine
-             */
-            obj = engine.subscribe("UEB", "APPC-LCM-READ");
-            assertNotNull(obj);
-            
-            /*
-             * The request should be of type LCMRequestWrapper
-             * and the subrequestid should be 1
-             */
-            assertTrue(obj instanceof LCMRequestWrapper);
-            LCMRequestWrapper dmaapRequest = (LCMRequestWrapper) obj;
-            LCMRequest appcRequest = dmaapRequest.getBody();
-            assertTrue(appcRequest.getCommonHeader().getSubRequestId().equals("1"));
-            
-            logger.debug("\n============ APPC received the request!!! ===========\n");
-
-            /*
-             * Give some time for processing
-             */
-            try {
-                Thread.sleep(1000);
-            } catch (InterruptedException e) {
-                e.printStackTrace();
-                logger.debug("An interrupt Exception was thrown");
-                fail("An interrupt Exception was thrown");
-            }
-            
-            /*
-             * Simulate a success response from APPC and insert
-             * the response into the working memory
-             */
-            LCMResponseWrapper dmaapResponse = new LCMResponseWrapper();
-            LCMResponse appcResponse = new LCMResponse(appcRequest);
-            appcResponse.getStatus().setCode(400);
-            appcResponse.getStatus().setMessage("AppC success");
-            dmaapResponse.setBody(appcResponse);
-            kieSession.insert(dmaapResponse);
-            
-            /* 
-             * Give time for processing
-             */
-            try {
-                Thread.sleep(10000);
-            } catch (InterruptedException e) {
-                e.printStackTrace();
-                logger.debug("An interrupt Exception was thrown");
-                fail("An interrupt Exception was thrown");
-            }
-            
-            /*
-             * Make sure the next notification is delivered
-             */
-            obj = engine.subscribe("UEB", "POLICY-CL-MGT");
-            assertNotNull(obj);
-            logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message);
-            
-            /*
-             * The ControlLoopNotification should be
-             * an OPERATION_SUCCESS
-             */
-            assertTrue(obj instanceof VirtualControlLoopNotification);
-            assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION_SUCCESS));
-            
-            /* 
-             * Now simulate the abatement sent from DCAE
-             */
-            try {
-                sendAbatement(pair.a, requestID, triggerSourceName);
-            } catch (InterruptedException e1) {
-                e1.printStackTrace();
-                logger.debug("Abatement could not be sent");
-                fail("Abatement could not be sent");
-            }
-            
-            /*
-             * Give time to finish processing
-             */
-            try {
-                Thread.sleep(20000);
-            } catch (InterruptedException e) {
-                e.printStackTrace();
-                logger.debug("An interrupt Exception was thrown");
-                fail("An interrupt Exception was thrown");
-            }     
-            
-            /*
-             * This should be the final notification from the Policy Engine
-             */
-            obj = engine.subscribe("UEB", "POLICY-CL-MGT");
-            assertNotNull(obj);
-            logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message);
-            
-            /*
-             * The ControlLoopNotification should be of type FINAL_SUCCESS
-             */
-            assertTrue(obj instanceof VirtualControlLoopNotification);
-            assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.FINAL_SUCCESS));
-            
-            /*
-             * One final check to make sure the lock is released 
-             */
-            assertFalse(PolicyGuard.isLocked(TargetType.VNF, triggerSourceName, requestID));
-        }
-        else {
-            fail("Operation Denied by Guard");
-        }
+        sendEvent(pair.a, requestID, ControlLoopEventStatus.ONSET);
         
-        /*
-         * This will stop the thread that is firing the rules
-         */
-        kieSession.halt();
+        kieSession.fireUntilHalt();
         
         /*
          * The only fact in memory should be Params
          */
-        //assertEquals(1, kieSession.getFactCount());
-        if (kieSession.getFactCount() != 1L) {
-            logger.error("FACT count mismatch: 1 expected but there are {}", kieSession.getFactCount());
-        }
+        assertEquals(1, kieSession.getFactCount());
         
         /*
          * Print what's left in memory
         return kieSession;
     }
     
-    /**
-     * This method is used to simulate event messages from DCAE
-     * that start the control loop (onset message).
-     * 
-     * @param policy the controlLoopName comes from the policy 
-     * @param requestID the requestId for this event
-     * @param triggerSourceName 
-     * @throws InterruptedException
+    /*
+     * (non-Javadoc)
+     * @see org.onap.policy.drools.PolicyEngineListener#newEventNotification(java.lang.String)
      */
-    protected void sendOnset(ControlLoopPolicy policy, UUID requestID, String triggerSourceName) throws InterruptedException {
-        VirtualControlLoopEvent event = new VirtualControlLoopEvent();
-        event.closedLoopControlName = policy.getControlLoop().getControlLoopName();
-        event.requestID = requestID;
-        event.target = "generic-vnf.vnf-id";
-        event.closedLoopAlarmStart = Instant.now();
-        event.AAI = new HashMap<>();
-        event.AAI.put("generic-vnf.vnf-id", "testGenericVnfId");
-        event.closedLoopEventStatus = ControlLoopEventStatus.ONSET;
-        kieSession.insert(event);
-        Thread.sleep(2000);
+    public void newEventNotification(String topic) {
+        /*
+         * Pull the object that was sent out to DMAAP and make
+         * sure it is a ControlLoopNoticiation of type active
+         */
+        Object obj = engine.subscribe("UEB", topic);
+        assertNotNull(obj);
+        if (obj instanceof VirtualControlLoopNotification) {
+            VirtualControlLoopNotification notification = (VirtualControlLoopNotification) obj;
+            String policyName = notification.policyName;
+            if (policyName.endsWith("EVENT")) {
+                logger.debug("Rule Fired: " + notification.policyName);
+                assertTrue(ControlLoopNotificationType.ACTIVE.equals(notification.notification));
+            }
+            else if (policyName.endsWith("GUARD_NOT_YET_QUERIED")) {
+                logger.debug("Rule Fired: " + notification.policyName);
+                assertTrue(ControlLoopNotificationType.OPERATION.equals(notification.notification));
+                assertNotNull(notification.message);
+                assertTrue(notification.message.startsWith("Sending guard query"));
+            }
+            else if (policyName.endsWith("GUARD.RESPONSE")) {
+                logger.debug("Rule Fired: " + notification.policyName);
+                assertTrue(ControlLoopNotificationType.OPERATION.equals(notification.notification));
+                assertNotNull(notification.message);
+                assertTrue(notification.message.endsWith("PERMIT"));
+            }
+            else if (policyName.endsWith("GUARD_PERMITTED")) {
+                logger.debug("Rule Fired: " + notification.policyName);
+                assertTrue(ControlLoopNotificationType.OPERATION.equals(notification.notification));
+                assertNotNull(notification.message);
+                assertTrue(notification.message.startsWith("actor=APPC"));
+            }
+            else if (policyName.endsWith("OPERATION.TIMEOUT")) {
+                logger.debug("Rule Fired: " + notification.policyName);
+                kieSession.halt();
+                logger.debug("The operation timed out");
+                fail("Operation Timed Out");
+            }
+            else if (policyName.endsWith("APPC.LCM.RESPONSE")) {
+                logger.debug("Rule Fired: " + notification.policyName);
+                assertTrue(ControlLoopNotificationType.OPERATION_SUCCESS.equals(notification.notification));
+                assertNotNull(notification.message);
+                assertTrue(notification.message.startsWith("actor=APPC"));
+                sendEvent(pair.a, requestID, ControlLoopEventStatus.ABATED);
+            }
+            else if (policyName.endsWith("EVENT.MANAGER")) {
+                logger.debug("Rule Fired: " + notification.policyName);
+                assertTrue(ControlLoopNotificationType.FINAL_SUCCESS.equals(notification.notification));
+                kieSession.halt();
+            }
+            else if (policyName.endsWith("EVENT.MANAGER.TIMEOUT")) {
+                logger.debug("Rule Fired: " + notification.policyName);
+                kieSession.halt();
+                logger.debug("The control loop timed out");
+                fail("Control Loop Timed Out");
+            }
+        }
+        else if (obj instanceof LCMRequestWrapper) {
+            /*
+             * The request should be of type LCMRequestWrapper
+             * and the subrequestid should be 1
+             */
+            LCMRequestWrapper dmaapRequest = (LCMRequestWrapper) obj;
+            LCMRequest appcRequest = dmaapRequest.getBody();
+            assertTrue(appcRequest.getCommonHeader().getSubRequestId().equals("1"));
+            
+            logger.debug("\n============ APPC received the request!!! ===========\n");
+            
+            /*
+             * Simulate a success response from APPC and insert
+             * the response into the working memory
+             */
+            LCMResponseWrapper dmaapResponse = new LCMResponseWrapper();
+            LCMResponse appcResponse = new LCMResponse(appcRequest);
+            appcResponse.getStatus().setCode(400);
+            appcResponse.getStatus().setMessage("AppC success");
+            dmaapResponse.setBody(appcResponse);
+            kieSession.insert(dmaapResponse);
+        }        
     }
     
     /**
      * This method is used to simulate event messages from DCAE
-     * that end the control loop (abatement message).
+     * that start the control loop (onset message) or end the
+     * control loop (abatement message).
      * 
      * @param policy the controlLoopName comes from the policy 
      * @param requestID the requestId for this event
-     * @param triggerSourceName 
-     * @throws InterruptedException
+     * @param status could be onset or abated
      */
-    protected void sendAbatement(ControlLoopPolicy policy, UUID requestID, String triggerSourceName) throws InterruptedException {
+    protected void sendEvent(ControlLoopPolicy policy, UUID requestID, ControlLoopEventStatus status) {
         VirtualControlLoopEvent event = new VirtualControlLoopEvent();
         event.closedLoopControlName = policy.getControlLoop().getControlLoopName();
         event.requestID = requestID;
         event.target = "generic-vnf.vnf-id";
-        event.closedLoopAlarmStart = Instant.now().minusSeconds(5);
-        event.closedLoopAlarmEnd = Instant.now();
+        event.closedLoopAlarmStart = Instant.now();
         event.AAI = new HashMap<>();
-        event.AAI.put("generic-vnf.vnf-id", "testGenericVnfId");
-        event.closedLoopEventStatus = ControlLoopEventStatus.ABATED;
+        event.AAI.put("generic-vnf.vnf-id", "testGenericVnfID");
+        event.closedLoopEventStatus = status;
         kieSession.insert(event);
     }
     
 
 
 package org.onap.policy.template.demo;
 
-import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import org.kie.api.runtime.rule.FactHandle;
 import org.onap.policy.controlloop.ControlLoopEventStatus;
 import org.onap.policy.controlloop.ControlLoopNotificationType;
-import org.onap.policy.controlloop.ControlLoopTargetType;
 import org.onap.policy.controlloop.VirtualControlLoopEvent;
 import org.onap.policy.controlloop.VirtualControlLoopNotification;
 import org.onap.policy.controlloop.policy.ControlLoopPolicy;
-import org.onap.policy.controlloop.policy.TargetType;
+import org.onap.policy.drools.PolicyEngineListener;
 import org.onap.policy.drools.http.server.HttpServletServer;
 import org.onap.policy.drools.impl.PolicyEngineJUnitImpl;
-import org.onap.policy.guard.PolicyGuard;
+
+import org.onap.policy.so.SORequest;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class VDNSControlLoopTest {
+public class VDNSControlLoopTest implements PolicyEngineListener {
 
     private static final Logger logger = LoggerFactory.getLogger(VDNSControlLoopTest.class);
     
     private KieSession kieSession;
     private Util.Pair<ControlLoopPolicy, String> pair;
     private PolicyEngineJUnitImpl engine;     
+    private UUID requestID;
     
     static {
         /* Set environment properties */
         }
         
         /*
-         * Create a thread to continuously fire rules 
-         * until main thread calls halt
-         */      
-        new Thread( new Runnable() {
-            @Override
-            public void run() {
-                kieSession.fireUntilHalt();
-            }
-          } ).start();
-        
-        /*
-         * Create a unique requestId and a unique trigger source
+         * Allows the PolicyEngine to callback to this object to
+         * notify that there is an event ready to be pulled 
+         * from the queue
          */
-        UUID requestID = UUID.randomUUID();
-        String triggerSourceName = "foobartriggersource36";
+        engine.addListener(this);
         
         /*
-         * This will be the object returned from the PolicyEngine
+         * Create a unique requestId
          */
-        Object obj = null;
+        requestID = UUID.randomUUID();
         
         /* 
          * Simulate an onset event the policy engine will 
          * receive from DCAE to kick off processing through
          * the rules
          */
-        try {
-            sendOnset(pair.a, requestID, triggerSourceName);
-        } catch (InterruptedException e) {
-            e.printStackTrace();
-            logger.debug("Unable to send onset event");
-            fail("Unable to send onset event");
-        }
+        sendEvent(pair.a, requestID, ControlLoopEventStatus.ONSET);
         
-        /*
-         * Pull the object that was sent out and make
-         * sure it is a ControlLoopNoticiation of type active
-         */
-        obj = engine.subscribe("UEB", "POLICY-CL-MGT");
-        assertNotNull(obj);
-        assertTrue(obj instanceof VirtualControlLoopNotification);
-        assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.ACTIVE));
-        
-
-        /*
-         * Give the control loop time to acquire a lock
-         */
-        try {
-            Thread.sleep(4000);
-        } catch (InterruptedException e) {
-            e.printStackTrace();
-            logger.debug("An interrupt Exception was thrown");
-            fail("An interrupt Exception was thrown");
-        }
-
-      /*
-      * Give time to finish processing
-      */
-     try {
-         Thread.sleep(10000);
-     } catch (InterruptedException e) {
-         e.printStackTrace();
-         logger.debug("An interrupt Exception was thrown");
-         fail("An interrupt Exception was thrown");
-     }     
-
-           /*
-            * One final check to make sure the lock is released 
-            */
-           assertFalse(PolicyGuard.isLocked(TargetType.VNF, triggerSourceName, requestID));
-
-        /*
-         * This will stop the thread that is firing the rules
-         */
-        kieSession.halt();
+        kieSession.fireUntilHalt();
         
         /*
          * The only fact in memory should be Params
          */
-        // assertEquals(1, kieSession.getFactCount());
-        if (kieSession.getFactCount() != 1L) {
-          logger.error("FACT count mismatch: 1 expected but there are {}", kieSession.getFactCount());
-        }
+        assertEquals(1, kieSession.getFactCount());
         
         /*
          * Print what's left in memory
         
         return kieSession;
     }
-
-    /**
-     * This method is used to simulate event messages from DCAE
-     * that start the control loop (onset message).
-     * 
-     * @param policy the controlLoopName comes from the policy 
-     * @param requestID the requestId for this event
-     * @param triggerSourceName 
-     * @throws InterruptedException
+    
+    /*
+     * (non-Javadoc)
+     * @see org.onap.policy.drools.PolicyEngineListener#newEventNotification(java.lang.String)
      */
-    protected void sendOnset(ControlLoopPolicy policy, UUID requestID, String triggerSourceName) throws InterruptedException {
-        VirtualControlLoopEvent event = new VirtualControlLoopEvent();
-        event.closedLoopControlName = policy.getControlLoop().getControlLoopName();
-        event.requestID = requestID;
-        event.target = "VNF_NAME";
-               event.target_type = ControlLoopTargetType.VNF;
-        event.closedLoopAlarmStart = Instant.now();
-        event.AAI = new HashMap<>();
-        event.AAI.put("cloud-region.identity-url", "foo");
-        event.AAI.put("vserver.selflink", "bar");
-        event.AAI.put("vserver.is-closed-loop-disabled", "false");
-        event.AAI.put("vserver.vserver-name", "vserver-name-16102016-aai3255-data-11-1");
-        event.closedLoopEventStatus = ControlLoopEventStatus.ONSET;
-        kieSession.insert(event);
-        Thread.sleep(2000);
+    public void newEventNotification(String topic) {
+        /*
+         * Pull the object that was sent out to DMAAP and make
+         * sure it is a ControlLoopNoticiation of type active
+         */
+        Object obj = engine.subscribe("UEB", topic);
+        assertNotNull(obj);
+        if (obj instanceof VirtualControlLoopNotification) {
+            VirtualControlLoopNotification notification = (VirtualControlLoopNotification) obj;
+            String policyName = notification.policyName;
+            if (policyName.endsWith("EVENT")) {
+                logger.debug("Rule Fired: " + notification.policyName);
+                assertTrue(ControlLoopNotificationType.ACTIVE.equals(notification.notification));
+            }
+            else if (policyName.endsWith("GUARD_NOT_YET_QUERIED")) {
+                logger.debug("Rule Fired: " + notification.policyName);
+                assertTrue(ControlLoopNotificationType.OPERATION.equals(notification.notification));
+                assertNotNull(notification.message);
+                assertTrue(notification.message.startsWith("Sending guard query"));
+            }
+            else if (policyName.endsWith("GUARD.RESPONSE")) {
+                logger.debug("Rule Fired: " + notification.policyName);
+                assertTrue(ControlLoopNotificationType.OPERATION.equals(notification.notification));
+                assertNotNull(notification.message);
+                assertTrue(notification.message.endsWith("PERMIT"));
+            }
+            else if (policyName.endsWith("GUARD_PERMITTED")) {
+                logger.debug("Rule Fired: " + notification.policyName);
+                assertTrue(ControlLoopNotificationType.OPERATION.equals(notification.notification));
+                assertNotNull(notification.message);
+                assertTrue(notification.message.startsWith("actor=SO"));
+            }
+            else if (policyName.endsWith("OPERATION.TIMEOUT")) {
+                logger.debug("Rule Fired: " + notification.policyName);
+                kieSession.halt();
+                logger.debug("The operation timed out");
+                fail("Operation Timed Out");
+            }
+            else if (policyName.endsWith("SO.RESPONSE")) {
+                logger.debug("Rule Fired: " + notification.policyName);
+                assertTrue(ControlLoopNotificationType.OPERATION_SUCCESS.equals(notification.notification));
+                assertNotNull(notification.message);
+                assertTrue(notification.message.startsWith("actor=SO"));
+            }
+            else if (policyName.endsWith("EVENT.MANAGER")) {
+                logger.debug("Rule Fired: " + notification.policyName);
+                assertTrue(ControlLoopNotificationType.FINAL_SUCCESS.equals(notification.notification));
+                kieSession.halt();
+            }
+            else if (policyName.endsWith("EVENT.MANAGER.TIMEOUT")) {
+                logger.debug("Rule Fired: " + notification.policyName);
+                kieSession.halt();
+                logger.debug("The control loop timed out");
+                fail("Control Loop Timed Out");
+            }
+        }
+        else if (obj instanceof SORequest) {
+            logger.debug("\n============ SO received the request!!! ===========\n");
+        }        
     }
     
     /**
      * This method is used to simulate event messages from DCAE
-     * that end the control loop (abatement message).
+     * that start the control loop (onset message) or end the
+     * control loop (abatement message).
      * 
      * @param policy the controlLoopName comes from the policy 
      * @param requestID the requestId for this event
-     * @param triggerSourceName 
-     * @throws InterruptedException
+     * @param status could be onset or abated
      */
-    protected void sendAbatement(ControlLoopPolicy policy, UUID requestID, String triggerSourceName) throws InterruptedException {
+    protected void sendEvent(ControlLoopPolicy policy, UUID requestID, ControlLoopEventStatus status) {
         VirtualControlLoopEvent event = new VirtualControlLoopEvent();
         event.closedLoopControlName = policy.getControlLoop().getControlLoopName();
         event.requestID = requestID;
-        event.target = "generic-vnf.vnf-id";
-        event.closedLoopAlarmStart = Instant.now().minusSeconds(5);
-        event.closedLoopAlarmEnd = Instant.now();
+        event.target = "vserver.vserver-name";
+        event.closedLoopAlarmStart = Instant.now();
         event.AAI = new HashMap<>();
-        event.AAI.put("cloud-region.identity-url", "foo");
-        event.AAI.put("vserver.selflink", "bar");
+        event.AAI.put("vserver.vserver-name", "dfw1lb01lb01");
         event.AAI.put("vserver.is-closed-loop-disabled", "false");
-        event.AAI.put("generic-vnf.vnf-id", "testGenericVnfID");
-        event.closedLoopEventStatus = ControlLoopEventStatus.ABATED;
+        event.closedLoopEventStatus = status;
         kieSession.insert(event);
     }
     
 
 
 package org.onap.policy.template.demo;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import org.kie.api.runtime.KieSession;
 import org.kie.api.runtime.rule.FactHandle;
 import org.onap.policy.controlloop.ControlLoopEventStatus;
-import org.onap.policy.controlloop.ControlLoopLogger;
+import org.onap.policy.controlloop.ControlLoopNotificationType;
 import org.onap.policy.controlloop.ControlLoopTargetType;
 import org.onap.policy.controlloop.VirtualControlLoopEvent;
-import org.onap.policy.controlloop.impl.ControlLoopLoggerStdOutImpl;
+import org.onap.policy.controlloop.VirtualControlLoopNotification;
 import org.onap.policy.controlloop.policy.ControlLoopPolicy;
+import org.onap.policy.drools.PolicyEngineListener;
 import org.onap.policy.drools.http.server.HttpServletServer;
 import org.onap.policy.drools.impl.PolicyEngineJUnitImpl;
-import org.onap.policy.drools.system.PolicyEngine;
-import org.onap.policy.vfc.util.Serialization;
+import org.onap.policy.vfc.VFCRequest;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 
-public class VFCControlLoopTest {
+public class VFCControlLoopTest implements PolicyEngineListener {
 
-       private static final Logger log = LoggerFactory.getLogger(VFCControlLoopTest.class);
+       private static final Logger logger = LoggerFactory.getLogger(VFCControlLoopTest.class);
        private KieSession kieSession;
        private Util.Pair<ControlLoopPolicy, String> pair;
        private PolicyEngineJUnitImpl engine;
+       private UUID requestID;
 
        static {
            /* Set environment properties */
        }
 
        @Test
-       public void testVolte() throws IOException {
+       public void successTest() throws IOException {
 
-               final String yaml = "src/test/resources/yaml/policy_ControlLoop_VFC.yaml";
-
-               //
-               // Pull info from the yaml
-               //
-               final Util.Pair<ControlLoopPolicy, String> pair = Util.loadYaml(yaml);
-               assertNotNull(pair);
-               assertNotNull(pair.a);
-               assertNotNull(pair.a.getControlLoop());
-               assertNotNull(pair.a.getControlLoop().getControlLoopName());
-               assertTrue(pair.a.getControlLoop().getControlLoopName().length() > 0);
-               final String closedLoopControlName = pair.a.getControlLoop().getControlLoopName();
-
-                /*
+        /*
          * Start the kie session
          */
-               try {
-                       kieSession = startSession("src/main/resources/ControlLoop_Template_xacml_guard.drl",
-                                       "src/test/resources/yaml/policy_ControlLoop_VFC.yaml",
-                                       "service=ServiceTest;resource=ResourceTest;type=operational",
-                                       "CL_VFC",
-                                       "org.onap.closed_loop.ServiceTest:VNFS:1.0.0");
-               } catch (IOException e) {
-                       e.printStackTrace();
-                       log.debug("Could not create kieSession");
-                       fail("Could not create kieSession");
-               }
-
-
-               //
-               // Insert our globals
-               //
-               final ControlLoopLogger logger = new ControlLoopLoggerStdOutImpl();
-               kieSession.setGlobal("Logger", logger);
-               final PolicyEngineJUnitImpl engine = new PolicyEngineJUnitImpl();
-               kieSession.setGlobal("Engine", engine);
-
-               //
-               // Initial fire of rules
-               //
-               kieSession.fireAllRules();
-               //
-               // Kick a thread that starts testing
-               //
-               new Thread(new Runnable() {
-
-                       @Override
-                       public void run() {
-
-                               log.debug("\n************ Starting VoLTE Test *************\n");
-
-                               //
-                               // Generate an invalid DCAE Event with requestID=null
-                               //
-                               VirtualControlLoopEvent invalidEvent = new VirtualControlLoopEvent();
-                               invalidEvent.closedLoopControlName = closedLoopControlName;
-                               invalidEvent.requestID = null;
-                               invalidEvent.closedLoopEventClient = "tca.instance00009";
-                               invalidEvent.target_type = ControlLoopTargetType.VNF;
-                               invalidEvent.target = "generic-vnf.vnf-id";
-                               invalidEvent.from = "DCAE";
-                               invalidEvent.closedLoopAlarmStart = Instant.now();
-                               invalidEvent.AAI = new HashMap<String, String>();
-                               invalidEvent.AAI.put("vserver.vserver-name", "vserver-name-16102016-aai3255-data-11-1");
-                               invalidEvent.closedLoopEventStatus = ControlLoopEventStatus.ONSET;
-
-                               log.debug("-------- Sending Invalid ONSET --------");
-                               log.debug(Serialization.gsonPretty.toJson(invalidEvent));
-
-                               //
-                               // Insert invalid DCAE Event into memory
-                               //
-                               kieSession.insert(invalidEvent);
-                               try {
-                                       Thread.sleep(500);
-                               } catch (InterruptedException e) {
-                               }
-                               //
-                               // Generate first DCAE ONSET Event
-                               //
-                               VirtualControlLoopEvent onsetEvent = new VirtualControlLoopEvent();
-                               onsetEvent.closedLoopControlName = closedLoopControlName;
-                               onsetEvent.requestID = UUID.randomUUID();
-                               onsetEvent.closedLoopEventClient = "tca.instance00009";
-                               onsetEvent.target_type = ControlLoopTargetType.VM;
-                               onsetEvent.target = "VM_NAME";
-                               onsetEvent.from = "DCAE";
-                               onsetEvent.closedLoopAlarmStart = Instant.now();
-                               onsetEvent.AAI = new HashMap<String, String>();
-                               onsetEvent.AAI.put("vserver.vserver-name", "vserver-name-16102016-aai3255-data-11-1");
-                               onsetEvent.AAI.put("vserver.vserver-id", "vserver-id-16102016-aai3255-data-11-1");
-                               onsetEvent.AAI.put("generic-vnf.vnf-id", "vnf-id-16102016-aai3255-data-11-1");
-                               onsetEvent.AAI.put("service-instance.service-instance-id", "service-instance-id-16102016-aai3255-data-11-1");
-                               onsetEvent.AAI.put("vserver.is-closed-loop-disabled", "false");
-                               onsetEvent.closedLoopEventStatus = ControlLoopEventStatus.ONSET;
-
-                               log.debug("-------- Sending Valid ONSET --------");
-                               log.debug(Serialization.gsonPretty.toJson(onsetEvent));
-
-                               //
-                               // Insert first DCAE ONSET Event into memory
-                               //
-                               kieSession.insert(onsetEvent);
-                               //
-                               // We have test for subsequent ONSET Events in testvFirewall()
-                               // So no need to test it again here
-                               //
-                               try {
-                                       Thread.sleep(30000);
-                               } catch (InterruptedException e) {
-                               }
-                               //
-                               // Test is finished, so stop the kieSession
-                               //
-                               kieSession.halt();
-                       }
-               //
-               }).start();
-               //
-               // Start firing rules
-               //
-               kieSession.fireUntilHalt();
-               //
-               // Dump working memory
-               //
-               dumpFacts(kieSession);
-
-               //
-               // See if there is anything left in memory, there SHOULD only be
-               // a params fact.
-               //
-               //assertEquals("There should only be 1 Fact left in memory.", 1, kieSession.getFactCount());
-               if (kieSession.getFactCount() != 1L) {
-                   log.error("FACT count mismatch: 1 expected but there are {}", kieSession.getFactCount());
-               }
-               for (FactHandle handle : kieSession.getFactHandles()) {
-                       Object fact = kieSession.getObject(handle);
-                       // assertEquals("Non-Param Fact left in working memory", "org.onap.policy.controlloop.Params", fact.getClass().getName());
-                       log.info("Working Memory FACT: {}", fact.getClass().getName());
-               }
-
-       }
-
-       public static void dumpFacts(KieSession kieSession) {
-               log.debug("Fact Count: " + kieSession.getFactCount());
-               for (FactHandle handle : kieSession.getFactHandles()) {
-                       log.debug("FACT: " + handle);
-               }
+        try {
+            kieSession = startSession("src/main/resources/ControlLoop_Template_xacml_guard.drl", 
+                        "src/test/resources/yaml/policy_ControlLoop_VFC.yaml",
+                        "type=operational", 
+                        "CL_VoLTE", 
+                        "v2.0");
+        } catch (IOException e) {
+            e.printStackTrace();
+            logger.debug("Could not create kieSession");
+            fail("Could not create kieSession");
+        }
+        
+        /*
+         * Allows the PolicyEngine to callback to this object to
+         * notify that there is an event ready to be pulled 
+         * from the queue
+         */
+        engine.addListener(this);
+        
+        /*
+         * Create a unique requestId
+         */
+        requestID = UUID.randomUUID();
+        
+        /* 
+         * Simulate an onset event the policy engine will 
+         * receive from DCAE to kick off processing through
+         * the rules
+         */
+        sendEvent(pair.a, requestID, ControlLoopEventStatus.ONSET);
+        
+        kieSession.fireUntilHalt();
+        
+        /*
+         * The only fact in memory should be Params
+         */
+        assertEquals(1, kieSession.getFactCount());
+        
+        /*
+         * Print what's left in memory
+         */
+        dumpFacts(kieSession);
+        
+        /*
+         * Gracefully shut down the kie session
+         */
+        kieSession.dispose();
        }
 
        /**
          */
                engine = (PolicyEngineJUnitImpl) kieSession.getGlobal("Engine");
 
-               log.debug("============");
-               log.debug(URLEncoder.encode(pair.b, "UTF-8"));
-               log.debug("============");
+               logger.debug("============");
+               logger.debug(URLEncoder.encode(pair.b, "UTF-8"));
+               logger.debug("============");
 
                return kieSession;
        }
+       
+       /*
+     * (non-Javadoc)
+     * @see org.onap.policy.drools.PolicyEngineListener#newEventNotification(java.lang.String)
+     */
+       public void newEventNotification(String topic) {
+        /*
+         * Pull the object that was sent out to DMAAP and make
+         * sure it is a ControlLoopNoticiation of type active
+         */
+        Object obj = engine.subscribe("UEB", topic);
+        assertNotNull(obj);
+        if (obj instanceof VirtualControlLoopNotification) {
+            VirtualControlLoopNotification notification = (VirtualControlLoopNotification) obj;
+            String policyName = notification.policyName;
+            if (policyName.endsWith("EVENT")) {
+                logger.debug("Rule Fired: " + notification.policyName);
+                assertTrue(ControlLoopNotificationType.ACTIVE.equals(notification.notification));
+            }
+            else if (policyName.endsWith("GUARD_NOT_YET_QUERIED")) {
+                logger.debug("Rule Fired: " + notification.policyName);
+                assertTrue(ControlLoopNotificationType.OPERATION.equals(notification.notification));
+                assertNotNull(notification.message);
+                assertTrue(notification.message.startsWith("Sending guard query"));
+            }
+            else if (policyName.endsWith("GUARD.RESPONSE")) {
+                logger.debug("Rule Fired: " + notification.policyName);
+                assertTrue(ControlLoopNotificationType.OPERATION.equals(notification.notification));
+                assertNotNull(notification.message);
+                assertTrue(notification.message.endsWith("PERMIT"));
+            }
+            else if (policyName.endsWith("GUARD_PERMITTED")) {
+                logger.debug("Rule Fired: " + notification.policyName);
+                assertTrue(ControlLoopNotificationType.OPERATION.equals(notification.notification));
+                assertNotNull(notification.message);
+                assertTrue(notification.message.startsWith("actor=VFC"));
+            }
+            else if (policyName.endsWith("OPERATION.TIMEOUT")) {
+                logger.debug("Rule Fired: " + notification.policyName);
+                kieSession.halt();
+                logger.debug("The operation timed out");
+                fail("Operation Timed Out");
+            }
+            else if (policyName.endsWith("VFC.RESPONSE")) {
+                logger.debug("Rule Fired: " + notification.policyName);
+                assertTrue(ControlLoopNotificationType.OPERATION_SUCCESS.equals(notification.notification));
+                assertNotNull(notification.message);
+                assertTrue(notification.message.startsWith("actor=VFC"));
+            }
+            else if (policyName.endsWith("EVENT.MANAGER")) {
+                logger.debug("Rule Fired: " + notification.policyName);
+                assertTrue(ControlLoopNotificationType.FINAL_SUCCESS.equals(notification.notification));
+                kieSession.halt();
+            }
+            else if (policyName.endsWith("EVENT.MANAGER.TIMEOUT")) {
+                logger.debug("Rule Fired: " + notification.policyName);
+                kieSession.halt();
+                logger.debug("The control loop timed out");
+                fail("Control Loop Timed Out");
+            }
+        }
+        else if (obj instanceof VFCRequest) {
+            logger.debug("\n============ VFC received the request!!! ===========\n");
+        }        
+    }
+       
+       /**
+    * This method is used to simulate event messages from DCAE
+    * that start the control loop (onset message) or end the
+    * control loop (abatement message).
+    * 
+    * @param policy the controlLoopName comes from the policy 
+    * @param requestID the requestId for this event
+    * @param status could be onset or abated
+    */
+   protected void sendEvent(ControlLoopPolicy policy, UUID requestID, ControlLoopEventStatus status) {
+       VirtualControlLoopEvent event = new VirtualControlLoopEvent();
+       event.closedLoopControlName = policy.getControlLoop().getControlLoopName();
+       event.requestID = UUID.randomUUID();
+       event.closedLoopEventClient = "tca.instance00009";
+       event.target_type = ControlLoopTargetType.VM;
+       event.target = "VM_NAME";
+       event.from = "DCAE";
+       event.closedLoopAlarmStart = Instant.now();
+       event.AAI = new HashMap<String, String>();
+       event.AAI.put("vserver.vserver-name", "vserver-name-16102016-aai3255-data-11-1");
+       event.AAI.put("vserver.vserver-id", "vserver-id-16102016-aai3255-data-11-1");
+       event.AAI.put("generic-vnf.vnf-id", "vnf-id-16102016-aai3255-data-11-1");
+       event.AAI.put("service-instance.service-instance-id", "service-instance-id-16102016-aai3255-data-11-1");
+       event.AAI.put("vserver.is-closed-loop-disabled", "false");
+       event.closedLoopEventStatus = ControlLoopEventStatus.ONSET;
+       kieSession.insert(event);
+   }
+   
+   public static void dumpFacts(KieSession kieSession) {
+       logger.debug("Fact Count: " + kieSession.getFactCount());
+       for (FactHandle handle : kieSession.getFactHandles()) {
+           logger.debug("FACT: " + handle);
+       }
+   }
 
 }
 
 
 
 package org.onap.policy.template.demo;
 
-import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import org.onap.policy.controlloop.VirtualControlLoopEvent;
 import org.onap.policy.controlloop.VirtualControlLoopNotification;
 import org.onap.policy.controlloop.policy.ControlLoopPolicy;
-import org.onap.policy.controlloop.policy.TargetType;
+import org.onap.policy.drools.PolicyEngineListener;
 import org.onap.policy.drools.http.server.HttpServletServer;
 import org.onap.policy.drools.impl.PolicyEngineJUnitImpl;
-import org.onap.policy.guard.PolicyGuard;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class VFWControlLoopTest {
+public class VFWControlLoopTest implements PolicyEngineListener {
 
     private static final Logger logger = LoggerFactory.getLogger(VFWControlLoopTest.class);
     
     private KieSession kieSession;
     private Util.Pair<ControlLoopPolicy, String> pair;
     private PolicyEngineJUnitImpl engine;
+    private UUID requestID;
     
     static {
         /* Set environment properties */
         }
         
         /*
-         * Create a thread to continuously fire rules 
-         * until main thread calls halt
-         */      
-        new Thread( new Runnable() {
-            @Override
-            public void run() {
-                kieSession.fireUntilHalt();
-            }
-          } ).start();
-        
-        /*
-         * Create a unique requestId and a unique trigger source
+         * Allows the PolicyEngine to callback to this object to
+         * notify that there is an event ready to be pulled 
+         * from the queue
          */
-        UUID requestID = UUID.randomUUID();
-        String triggerSourceName = "foobartriggersource36";
+        engine.addListener(this);
         
         /*
-         * This will be the object returned from the PolicyEngine
+         * Create a unique requestId
          */
-        Object obj = null;
+        requestID = UUID.randomUUID();
         
         /* 
          * Simulate an onset event the policy engine will 
          * receive from DCAE to kick off processing through
          * the rules
          */
-        try {
-            sendOnset(pair.a, requestID, triggerSourceName);
-        } catch (InterruptedException e) {
-            e.printStackTrace();
-            logger.debug("Unable to send onset event");
-            fail("Unable to send onset event");
-        }
-        
-        /*
-         * Pull the object that was sent out to DMAAP and make
-         * sure it is a ControlLoopNoticiation of type active
-         */
-        obj = engine.subscribe("UEB", "POLICY-CL-MGT");
-        assertNotNull(obj);
-        assertTrue(obj instanceof VirtualControlLoopNotification);
-        assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.ACTIVE));
-        
-        /*
-         * Give the control loop time to acquire a lock
-         */
-        try {
-            Thread.sleep(4000);
-        } catch (InterruptedException e) {
-            e.printStackTrace();
-            logger.debug("An interrupt Exception was thrown");
-            fail("An interrupt Exception was thrown");
-        }
+        sendEvent(pair.a, requestID, ControlLoopEventStatus.ONSET);
         
-        /*
-         * The fact should be ready to query guard now to see 
-         * if a ModifyConfig recipe is allowed
-         */
-        obj = engine.subscribe("UEB", "POLICY-CL-MGT");
-        assertNotNull(obj);
-        logger.debug("\n\n####################### GOING TO QUERY GUARD about ModifyConfig!!!!!!");
-        logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message);
-        
-        /*
-         * Make sure the object is an instance of a ControlLoopNotification
-         * and is of type operation
-         */
-        assertTrue(obj instanceof VirtualControlLoopNotification);
-        assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION));
-    
-        try {
-            Thread.sleep(4000);
-        } catch (InterruptedException e) {
-            e.printStackTrace();
-            logger.debug("An interrupt Exception was thrown");
-            fail("An interrupt Exception was thrown");
-        }
-        
-        /*
-         * The guard response should be received at this point
-         */
-        obj = engine.subscribe("UEB", "POLICY-CL-MGT");
-        assertNotNull(obj);
-        logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message);
-        
-        /*
-         * The object should be a ControlLoopNotification with type operation
-         */
-        assertTrue(obj instanceof VirtualControlLoopNotification);
-        assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION));
-        
-        /*
-         * See if Guard permits this action, if it does 
-         * not then the test should fail
-         */
-        if (((VirtualControlLoopNotification)obj).message.contains("PERMIT")) {
-            
-            /*
-             * Obtain the ControlLoopNoticiation, it should be of type operation
-             */
-            obj = engine.subscribe("UEB", "POLICY-CL-MGT");
-            assertNotNull(obj);
-            logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message);
-            
-            /* 
-             * A notification should be sent out of the Policy
-             * Engine at this point, it will be of type operation
-             */
-            assertTrue(obj instanceof VirtualControlLoopNotification);
-            assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION));
-            
-            try {
-                Thread.sleep(1000);
-            } catch (InterruptedException e) {
-                e.printStackTrace();
-                logger.debug("An interrupt Exception was thrown");
-                fail("An interrupt Exception was thrown");
-            }
-            
-            /*
-             * Obtain the request sent from the Policy Engine
-             */
-            obj = engine.subscribe("UEB", "APPC-CL");
-            assertNotNull(obj);
-            
-            /*
-             * The request should be of type Request 
-             * and the subrequestid should be 1
-             */
-            assertTrue(obj instanceof Request);
-            assertTrue(((Request)obj).getCommonHeader().SubRequestID.equals("1"));
-            
-            logger.debug("\n============ APPC received the request!!! ===========\n");
-
-            /*
-             * Give some time for processing
-             */
-            try {
-                Thread.sleep(1000);
-            } catch (InterruptedException e) {
-                e.printStackTrace();
-                logger.debug("An interrupt Exception was thrown");
-                fail("An interrupt Exception was thrown");
-            }
-            
-            /*
-             * Simulate a success response from APPC and insert
-             * the response into the working memory
-             */
-            Response appcResponse = new Response((Request)obj);
-            appcResponse.getStatus().Code = ResponseCode.SUCCESS.getValue();
-            appcResponse.getStatus().Value = "SUCCESS";
-            kieSession.insert(appcResponse);
-            
-            /* 
-             * Give time for processing
-             */
-            try {
-                Thread.sleep(4000);
-            } catch (InterruptedException e) {
-                e.printStackTrace();
-                logger.debug("An interrupt Exception was thrown");
-                fail("An interrupt Exception was thrown");
-            }
-            
-            /*
-             * Make sure the next notification is delivered
-             */
-            obj = engine.subscribe("UEB", "POLICY-CL-MGT");
-            assertNotNull(obj);
-            logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message);
-            
-            /*
-             * The ControlLoopNotification should be
-             * an OPERATION_SUCCESS
-             */
-            assertTrue(obj instanceof VirtualControlLoopNotification);
-            assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION_SUCCESS));
-            
-            /* 
-             * Now simulate the abatement sent from DCAE
-             */
-            try {
-                sendAbatement(pair.a, requestID, triggerSourceName);
-            } catch (InterruptedException e1) {
-                e1.printStackTrace();
-                logger.debug("Abatement could not be sent");
-                fail("Abatement could not be sent");
-            }
-            
-            /*
-             * Give time to finish processing
-             */
-            try {
-                Thread.sleep(20000);
-            } catch (InterruptedException e) {
-                e.printStackTrace();
-                logger.debug("An interrupt Exception was thrown");
-                fail("An interrupt Exception was thrown");
-            }     
-            
-            /*
-             * This should be the final notification from the Policy Engine
-             */
-            obj = engine.subscribe("UEB", "POLICY-CL-MGT");
-            assertNotNull(obj);
-            logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message);
-            
-            /*
-             * The ControlLoopNotification should be of type FINAL_SUCCESS
-             */
-            assertTrue(obj instanceof VirtualControlLoopNotification);
-            assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.FINAL_SUCCESS));
-            
-            /*
-             * One final check to make sure the lock is released 
-             */
-            assertFalse(PolicyGuard.isLocked(TargetType.VNF, triggerSourceName, requestID));
-        }
-        else {
-            fail("Operation Denied by Guard");
-        }
-        
-        /*
-         * This will stop the thread that is firing the rules
-         */
-        kieSession.halt();
+        kieSession.fireUntilHalt();
         
         /*
          * The only fact in memory should be Params
          */
-        // assertEquals(1, kieSession.getFactCount());
-        if (kieSession.getFactCount() != 1L) {
-            logger.error("FACT count mismatch: 1 expected but there are {}", kieSession.getFactCount());
-        }
+        assertEquals(1, kieSession.getFactCount());
         
         /*
          * Print what's left in memory
         
         return kieSession;
     }
-
-    /**
-     * This method is used to simulate event messages from DCAE
-     * that start the control loop (onset message).
-     * 
-     * @param policy the controlLoopName comes from the policy 
-     * @param requestID the requestId for this event
-     * @param triggerSourceName 
-     * @throws InterruptedException
+    
+    /*
+     * @see org.onap.policy.drools.PolicyEngineListener#newEventNotification(java.lang.String)
      */
-    protected void sendOnset(ControlLoopPolicy policy, UUID requestID, String triggerSourceName) throws InterruptedException {
-        VirtualControlLoopEvent event = new VirtualControlLoopEvent();
-        event.closedLoopControlName = policy.getControlLoop().getControlLoopName();
-        event.requestID = requestID;
-        event.target = "generic-vnf.vnf-id";
-        event.closedLoopAlarmStart = Instant.now();
-        event.AAI = new HashMap<>();
-        event.AAI.put("generic-vnf.vnf-id", "testGenericVnfID");
-        event.closedLoopEventStatus = ControlLoopEventStatus.ONSET;
-        kieSession.insert(event);
-        Thread.sleep(2000);
+    public void newEventNotification(String topic) {
+        /*
+         * Pull the object that was sent out to DMAAP and make
+         * sure it is a ControlLoopNoticiation of type active
+         */
+        Object obj = engine.subscribe("UEB", topic);
+        assertNotNull(obj);
+        if (obj instanceof VirtualControlLoopNotification) {
+            VirtualControlLoopNotification notification = (VirtualControlLoopNotification) obj;
+            String policyName = notification.policyName;
+            if (policyName.endsWith("EVENT")) {
+                logger.debug("Rule Fired: " + notification.policyName);
+                assertTrue(ControlLoopNotificationType.ACTIVE.equals(notification.notification));
+            }
+            else if (policyName.endsWith("GUARD_NOT_YET_QUERIED")) {
+                logger.debug("Rule Fired: " + notification.policyName);
+                assertTrue(ControlLoopNotificationType.OPERATION.equals(notification.notification));
+                assertNotNull(notification.message);
+                assertTrue(notification.message.startsWith("Sending guard query"));
+            }
+            else if (policyName.endsWith("GUARD.RESPONSE")) {
+                logger.debug("Rule Fired: " + notification.policyName);
+                assertTrue(ControlLoopNotificationType.OPERATION.equals(notification.notification));
+                assertNotNull(notification.message);
+                assertTrue(notification.message.endsWith("PERMIT"));
+            }
+            else if (policyName.endsWith("GUARD_PERMITTED")) {
+                logger.debug("Rule Fired: " + notification.policyName);
+                assertTrue(ControlLoopNotificationType.OPERATION.equals(notification.notification));
+                assertNotNull(notification.message);
+                assertTrue(notification.message.startsWith("actor=APPC"));
+            }
+            else if (policyName.endsWith("OPERATION.TIMEOUT")) {
+                logger.debug("Rule Fired: " + notification.policyName);
+                kieSession.halt();
+                logger.debug("The operation timed out");
+                fail("Operation Timed Out");
+            }
+            else if (policyName.endsWith("APPC.RESPONSE")) {
+                logger.debug("Rule Fired: " + notification.policyName);
+                assertTrue(ControlLoopNotificationType.OPERATION_SUCCESS.equals(notification.notification));
+                assertNotNull(notification.message);
+                assertTrue(notification.message.startsWith("actor=APPC"));
+                sendEvent(pair.a, requestID, ControlLoopEventStatus.ABATED);
+            }
+            else if (policyName.endsWith("EVENT.MANAGER")) {
+                logger.debug("Rule Fired: " + notification.policyName);
+                assertTrue(ControlLoopNotificationType.FINAL_SUCCESS.equals(notification.notification));
+                kieSession.halt();
+            }
+            else if (policyName.endsWith("EVENT.MANAGER.TIMEOUT")) {
+                logger.debug("Rule Fired: " + notification.policyName);
+                kieSession.halt();
+                logger.debug("The control loop timed out");
+                fail("Control Loop Timed Out");
+            }
+        }
+        else if (obj instanceof Request) {
+            assertTrue(((Request)obj).getCommonHeader().SubRequestID.equals("1"));
+            
+            logger.debug("\n============ APPC received the request!!! ===========\n");
+            
+            /*
+             * Simulate a success response from APPC and insert
+             * the response into the working memory
+             */
+            Response appcResponse = new Response((Request)obj);
+            appcResponse.getStatus().Code = ResponseCode.SUCCESS.getValue();
+            appcResponse.getStatus().Value = "SUCCESS";
+            kieSession.insert(appcResponse);
+        }        
     }
     
     /**
      * This method is used to simulate event messages from DCAE
-     * that end the control loop (abatement message).
+     * that start the control loop (onset message) or end the
+     * control loop (abatement message).
      * 
      * @param policy the controlLoopName comes from the policy 
      * @param requestID the requestId for this event
-     * @param triggerSourceName 
-     * @throws InterruptedException
+     * @param status could be onset or abated
      */
-    protected void sendAbatement(ControlLoopPolicy policy, UUID requestID, String triggerSourceName) throws InterruptedException {
+    protected void sendEvent(ControlLoopPolicy policy, UUID requestID, ControlLoopEventStatus status) {
         VirtualControlLoopEvent event = new VirtualControlLoopEvent();
         event.closedLoopControlName = policy.getControlLoop().getControlLoopName();
         event.requestID = requestID;
         event.target = "generic-vnf.vnf-id";
-        event.closedLoopAlarmStart = Instant.now().minusSeconds(5);
-        event.closedLoopAlarmEnd = Instant.now();
+        event.closedLoopAlarmStart = Instant.now();
         event.AAI = new HashMap<>();
-        event.AAI.put("cloud-region.identity-url", "foo");
-        event.AAI.put("vserver.selflink", "bar");
-        event.AAI.put("vserver.is-closed-loop-disabled", "false");
         event.AAI.put("generic-vnf.vnf-id", "testGenericVnfID");
-        event.closedLoopEventStatus = ControlLoopEventStatus.ABATED;
+        event.closedLoopEventStatus = status;
         kieSession.insert(event);
     }
     
 
       serviceInvariantUUID: dc112d6e-7e73-4777-9c6f-1a7fb5fd1b6f
       serviceUUID: 2eea06c6-e1d3-4c3a-b9c4-478c506eeedf
   trigger_policy: unique-policy-id-1-scale-up
-  timeout: 1200
+  timeout: 20
  
 policies:
   - id: unique-policy-id-1-scale-up
     target:
       type: VNF
     retry: 0
-    timeout: 1200
+    timeout: 10
     success: final_success
     failure: final_failure
     failure_timeout: final_failure_timeout
 
   controlLoopName: ControlLoop-VOLTE-2179b738-fd36-4843-a71a-a8c24c70c55b
 
   trigger_policy: unique-policy-id-1-restart
-  timeout: 3600
+  timeout: 20
 
 policies:
   - id: unique-policy-id-1-restart
     target:
       type: VM
     retry: 3
-    timeout: 1200
+    timeout: 10
     success: final_success
     failure: final_failure
     failure_timeout: final_failure_timeout
 
   version: 2.0.0
   controlLoopName: ControlLoop-vCPE-48f0c2c3-a172-4192-9ae3-052274181b6e
   trigger_policy: unique-policy-id-1-restart
-  timeout: 3600
+  timeout: 20
   abatement: true
  
 policies:
     target:
       type: VM
     retry: 3
-    timeout: 1200
+    timeout: 10
     success: final_success
     failure: final_failure
     failure_timeout: final_failure_timeout
 
       serviceUUID: 0f40bba5-986e-4b3c-803f-ddd1b7b25f24
       serviceName: 57e66ea7-0ed6-45c7-970f
   trigger_policy: unique-policy-id-1-modifyConfig
-  timeout: 1200
+  timeout: 20
   abatement: true
  
 policies:
       resourceID: Eace933104d443b496b8.nodes.heat.vpg
       type: VNF
     retry: 0
-    timeout: 300
+    timeout: 10
     success: final_success
     failure: final_failure
     failure_timeout: final_failure_timeout