Repository: nifi
Updated Branches:
  refs/heads/master ea41b41ed -> 604656fe8


http://git-wip-us.apache.org/repos/asf/nifi/blob/604656fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/serialization/StandardFlowSerializerTest.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/serialization/StandardFlowSerializerTest.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/serialization/StandardFlowSerializerTest.java
index 8044ede..34bae40 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/serialization/StandardFlowSerializerTest.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/serialization/StandardFlowSerializerTest.java
@@ -36,6 +36,7 @@ import org.apache.nifi.util.NiFiProperties;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mockito;
+import org.w3c.dom.Document;
 
 import java.io.ByteArrayOutputStream;
 import java.io.File;
@@ -101,7 +102,8 @@ public class StandardFlowSerializerTest {
 
         // serialize the controller
         final ByteArrayOutputStream os = new ByteArrayOutputStream();
-        serializer.serialize(controller, os, 
ScheduledStateLookup.IDENTITY_LOOKUP);
+        final Document doc = serializer.transform(controller, 
ScheduledStateLookup.IDENTITY_LOOKUP);
+        serializer.serialize(doc, os);
 
         // verify the results contain the serialized string
         final String serializedFlow = 
os.toString(StandardCharsets.UTF_8.name());

http://git-wip-us.apache.org/repos/asf/nifi/blob/604656fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/StandardControllerServiceProviderIT.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/StandardControllerServiceProviderIT.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/StandardControllerServiceProviderIT.java
index 015ae67..d2784ca 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/StandardControllerServiceProviderIT.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/StandardControllerServiceProviderIT.java
@@ -40,6 +40,7 @@ import org.apache.nifi.nar.ExtensionManager;
 import org.apache.nifi.nar.SystemBundle;
 import org.apache.nifi.registry.VariableRegistry;
 import org.apache.nifi.util.NiFiProperties;
+import org.apache.nifi.util.SynchronousValidationTrigger;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.mockito.Mockito;
@@ -101,7 +102,8 @@ public class StandardControllerServiceProviderIT {
         final ProcessGroup procGroup = new MockProcessGroup(controller);
         
Mockito.when(controller.getGroup(Mockito.anyString())).thenReturn(procGroup);
 
-        final StandardControllerServiceProvider provider = new 
StandardControllerServiceProvider(controller, scheduler, null, 
stateManagerProvider, variableRegistry, niFiProperties);
+        final StandardControllerServiceProvider provider = new 
StandardControllerServiceProvider(controller, scheduler, null,
+            stateManagerProvider, variableRegistry, niFiProperties, new 
SynchronousValidationTrigger());
 
         // build a graph of controller services with dependencies as such:
         //

http://git-wip-us.apache.org/repos/asf/nifi/blob/604656fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/StandardControllerServiceProviderTest.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/StandardControllerServiceProviderTest.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/StandardControllerServiceProviderTest.java
index 55263f8..f7ee72f 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/StandardControllerServiceProviderTest.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/StandardControllerServiceProviderTest.java
@@ -27,6 +27,7 @@ import org.apache.nifi.registry.VariableRegistry;
 import org.apache.nifi.registry.variable.FileBasedVariableRegistry;
 import org.apache.nifi.reporting.InitializationException;
 import org.apache.nifi.util.NiFiProperties;
+import org.apache.nifi.util.SynchronousValidationTrigger;
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
@@ -80,7 +81,7 @@ public class StandardControllerServiceProviderTest {
             @Override
             public void onComponentRemoved(String componentId) {
             }
-        }, variableRegistry, nifiProperties);
+        }, variableRegistry, nifiProperties, new 
SynchronousValidationTrigger());
         ControllerServiceNode node = provider.createControllerService(clazz, 
id, systemBundle.getBundleDetails().getCoordinate(), null, true);
         proxied = node.getProxiedControllerService();
         implementation = node.getControllerServiceImplementation();

http://git-wip-us.apache.org/repos/asf/nifi/blob/604656fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/TestStandardControllerServiceProvider.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/TestStandardControllerServiceProvider.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/TestStandardControllerServiceProvider.java
index bfd1340..b37dbb2 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/TestStandardControllerServiceProvider.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/TestStandardControllerServiceProvider.java
@@ -29,6 +29,7 @@ import java.util.Map;
 import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.TimeUnit;
 
 import org.apache.nifi.bundle.Bundle;
 import org.apache.nifi.components.state.StateManager;
@@ -58,6 +59,7 @@ import 
org.apache.nifi.registry.variable.StandardComponentVariableRegistry;
 import org.apache.nifi.util.MockProcessContext;
 import org.apache.nifi.util.MockProcessorInitializationContext;
 import org.apache.nifi.util.NiFiProperties;
+import org.apache.nifi.util.SynchronousValidationTrigger;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.BeforeClass;
@@ -147,15 +149,17 @@ public class TestStandardControllerServiceProvider {
 
         final StandardProcessScheduler scheduler = createScheduler();
         final StandardControllerServiceProvider provider =
-                new StandardControllerServiceProvider(controller, scheduler, 
null, stateManagerProvider, variableRegistry, niFiProperties);
+            new StandardControllerServiceProvider(controller, scheduler, null, 
stateManagerProvider, variableRegistry, niFiProperties, new 
SynchronousValidationTrigger());
 
         final ControllerServiceNode serviceNode = 
provider.createControllerService(ServiceB.class.getName(), "B",
                 systemBundle.getBundleDetails().getCoordinate(), null,false);
+        serviceNode.performValidation();
+        serviceNode.getValidationStatus(5, TimeUnit.SECONDS);
         provider.enableControllerService(serviceNode);
         provider.disableControllerService(serviceNode);
     }
 
-    @Test(timeout = 10000)
+    @Test(timeout = 1000000)
     public void testEnableDisableWithReference() {
         final ProcessGroup group = new MockProcessGroup(controller);
         final FlowController controller = Mockito.mock(FlowController.class);
@@ -163,7 +167,7 @@ public class TestStandardControllerServiceProvider {
 
         final StandardProcessScheduler scheduler = createScheduler();
         final StandardControllerServiceProvider provider =
-                new StandardControllerServiceProvider(controller, scheduler, 
null, stateManagerProvider, variableRegistry, niFiProperties);
+            new StandardControllerServiceProvider(controller, scheduler, null, 
stateManagerProvider, variableRegistry, niFiProperties, new 
SynchronousValidationTrigger());
 
         final ControllerServiceNode serviceNodeB = 
provider.createControllerService(ServiceB.class.getName(), "B",
                 systemBundle.getBundleDetails().getCoordinate(), null, false);
@@ -180,7 +184,12 @@ public class TestStandardControllerServiceProvider {
         } catch (final IllegalStateException expected) {
         }
 
+        serviceNodeB.performValidation();
+        serviceNodeB.getValidationStatus(5, TimeUnit.SECONDS);
         provider.enableControllerService(serviceNodeB);
+
+        serviceNodeA.performValidation();
+        serviceNodeA.getValidationStatus(5, TimeUnit.SECONDS);
         provider.enableControllerService(serviceNodeA);
 
         try {
@@ -212,7 +221,7 @@ public class TestStandardControllerServiceProvider {
         
Mockito.when(controller.getGroup(Mockito.anyString())).thenReturn(procGroup);
 
         final StandardControllerServiceProvider provider =
-                new StandardControllerServiceProvider(controller, null, null, 
stateManagerProvider, variableRegistry, niFiProperties);
+            new StandardControllerServiceProvider(controller, null, null, 
stateManagerProvider, variableRegistry, niFiProperties, new 
SynchronousValidationTrigger());
         final ControllerServiceNode serviceNode1 = 
provider.createControllerService(ServiceA.class.getName(), "1",
                 systemBundle.getBundleDetails().getCoordinate(), null, false);
         final ControllerServiceNode serviceNode2 = 
provider.createControllerService(ServiceB.class.getName(), "2",
@@ -370,7 +379,7 @@ public class TestStandardControllerServiceProvider {
         final LoggableComponent<Processor> dummyProcessor = new 
LoggableComponent<>(processor, systemBundle.getBundleDetails().getCoordinate(), 
null);
         final ProcessorNode procNode = new 
StandardProcessorNode(dummyProcessor, mockInitContext.getIdentifier(),
                 new StandardValidationContextFactory(serviceProvider, null), 
scheduler, serviceProvider, niFiProperties,
-                new 
StandardComponentVariableRegistry(VariableRegistry.EMPTY_REGISTRY), 
reloadComponent);
+            new 
StandardComponentVariableRegistry(VariableRegistry.EMPTY_REGISTRY), 
reloadComponent, new SynchronousValidationTrigger());
 
         final ProcessGroup group = new 
StandardProcessGroup(UUID.randomUUID().toString(), serviceProvider, scheduler, 
null, null, Mockito.mock(FlowController.class),
             new MutableVariableRegistry(variableRegistry));
@@ -388,7 +397,7 @@ public class TestStandardControllerServiceProvider {
 
         final StandardProcessScheduler scheduler = createScheduler();
         final StandardControllerServiceProvider provider =
-                new StandardControllerServiceProvider(controller, null, null, 
stateManagerProvider, variableRegistry, niFiProperties);
+            new StandardControllerServiceProvider(controller, null, null, 
stateManagerProvider, variableRegistry, niFiProperties, new 
SynchronousValidationTrigger());
         final ControllerServiceNode serviceNode = 
provider.createControllerService(ServiceA.class.getName(), "1",
                 systemBundle.getBundleDetails().getCoordinate(), null, false);
 
@@ -409,7 +418,7 @@ public class TestStandardControllerServiceProvider {
         StandardProcessScheduler scheduler = createScheduler();
         FlowController controller = Mockito.mock(FlowController.class);
         StandardControllerServiceProvider provider =
-                new StandardControllerServiceProvider(controller, scheduler, 
null, stateManagerProvider, variableRegistry, niFiProperties);
+            new StandardControllerServiceProvider(controller, scheduler, null, 
stateManagerProvider, variableRegistry, niFiProperties, new 
SynchronousValidationTrigger());
         ProcessGroup procGroup = new MockProcessGroup(controller);
         
Mockito.when(controller.getGroup(Mockito.anyString())).thenReturn(procGroup);
 
@@ -440,7 +449,9 @@ public class TestStandardControllerServiceProvider {
         setProperty(E, ServiceA.OTHER_SERVICE.getName(), "A");
         setProperty(E, ServiceA.OTHER_SERVICE_2.getName(), "F");
 
-        provider.enableControllerServices(Arrays.asList(A, B, C, D, E, F));
+        final List<ControllerServiceNode> serviceNodes = Arrays.asList(A, B, 
C, D, E, F);
+        
serviceNodes.stream().forEach(ControllerServiceNode::performValidation);
+        provider.enableControllerServices(serviceNodes);
 
         assertTrue(A.isActive());
         assertTrue(B.isActive());
@@ -460,7 +471,7 @@ public class TestStandardControllerServiceProvider {
         StandardProcessScheduler scheduler = createScheduler();
         FlowController controller = Mockito.mock(FlowController.class);
         StandardControllerServiceProvider provider = new 
StandardControllerServiceProvider(controller, scheduler, null,
-                stateManagerProvider, variableRegistry, niFiProperties);
+            stateManagerProvider, variableRegistry, niFiProperties, new 
SynchronousValidationTrigger());
         ProcessGroup procGroup = new MockProcessGroup(controller);
         
Mockito.when(controller.getGroup(Mockito.anyString())).thenReturn(procGroup);
 
@@ -488,7 +499,10 @@ public class TestStandardControllerServiceProvider {
         setProperty(F, ServiceA.OTHER_SERVICE.getName(), "D");
         setProperty(D, ServiceA.OTHER_SERVICE.getName(), "C");
 
-        provider.enableControllerServices(Arrays.asList(C, F, A, B, D));
+        final List<ControllerServiceNode> services = Arrays.asList(C, F, A, B, 
D);
+        services.stream().forEach(ControllerServiceNode::performValidation);
+
+        provider.enableControllerServices(services);
 
         assertTrue(A.isActive());
         assertTrue(B.isActive());
@@ -502,7 +516,7 @@ public class TestStandardControllerServiceProvider {
         StandardProcessScheduler scheduler = createScheduler();
         FlowController controller = Mockito.mock(FlowController.class);
         StandardControllerServiceProvider provider =
-                new StandardControllerServiceProvider(controller, scheduler, 
null, stateManagerProvider, variableRegistry, niFiProperties);
+            new StandardControllerServiceProvider(controller, scheduler, null, 
stateManagerProvider, variableRegistry, niFiProperties, new 
SynchronousValidationTrigger());
         ProcessGroup procGroup = new MockProcessGroup(controller);
         
Mockito.when(controller.getGroup(Mockito.anyString())).thenReturn(procGroup);
 
@@ -537,8 +551,10 @@ public class TestStandardControllerServiceProvider {
         setProperty(serviceNode7, ServiceC.REQ_SERVICE_1.getName(), "2");
         setProperty(serviceNode7, ServiceC.REQ_SERVICE_2.getName(), "3");
 
-        provider.enableControllerServices(Arrays.asList(
-                serviceNode1, serviceNode2, serviceNode3, serviceNode4, 
serviceNode5, serviceNode7));
+        final List<ControllerServiceNode> allBut6 = 
Arrays.asList(serviceNode1, serviceNode2, serviceNode3, serviceNode4, 
serviceNode5, serviceNode7);
+        allBut6.stream().forEach(ControllerServiceNode::performValidation);
+
+        provider.enableControllerServices(allBut6);
         assertFalse(serviceNode1.isActive());
         assertFalse(serviceNode2.isActive());
         assertFalse(serviceNode3.isActive());
@@ -546,7 +562,9 @@ public class TestStandardControllerServiceProvider {
         assertFalse(serviceNode5.isActive());
         assertFalse(serviceNode6.isActive());
 
+        serviceNode6.performValidation();
         provider.enableControllerService(serviceNode6);
+
         provider.enableControllerServices(Arrays.asList(
                 serviceNode1, serviceNode2, serviceNode3, serviceNode4, 
serviceNode5));
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/604656fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/mock/MockProcessGroup.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/mock/MockProcessGroup.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/mock/MockProcessGroup.java
index 08a71bc..374d02b 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/mock/MockProcessGroup.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/mock/MockProcessGroup.java
@@ -25,7 +25,7 @@ import org.apache.nifi.connectable.Funnel;
 import org.apache.nifi.connectable.Port;
 import org.apache.nifi.connectable.Position;
 import org.apache.nifi.connectable.Positionable;
-import org.apache.nifi.controller.ConfiguredComponent;
+import org.apache.nifi.controller.ComponentNode;
 import org.apache.nifi.controller.FlowController;
 import org.apache.nifi.controller.ProcessorNode;
 import org.apache.nifi.controller.Snippet;
@@ -627,7 +627,7 @@ public class MockProcessGroup implements ProcessGroup {
     }
 
     @Override
-    public Set<ConfiguredComponent> getComponentsAffectedByVariable(String 
variableName) {
+    public Set<ComponentNode> getComponentsAffectedByVariable(String 
variableName) {
         return Collections.emptySet();
     }
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/604656fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/util/SynchronousValidationTrigger.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/util/SynchronousValidationTrigger.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/util/SynchronousValidationTrigger.java
new file mode 100644
index 0000000..0309fc0
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/util/SynchronousValidationTrigger.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.nifi.util;
+
+import org.apache.nifi.components.validation.ValidationTrigger;
+import org.apache.nifi.controller.ComponentNode;
+
+public class SynchronousValidationTrigger implements ValidationTrigger {
+
+    @Override
+    public void triggerAsync(ComponentNode component) {
+        trigger(component);
+    }
+
+    @Override
+    public void trigger(ComponentNode component) {
+        component.performValidation();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/604656fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/resources/logback-test.xml
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/resources/logback-test.xml
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/resources/logback-test.xml
index fd00fef..560363c 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/resources/logback-test.xml
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/resources/logback-test.xml
@@ -30,9 +30,9 @@
     
     
     <logger name="org.apache.nifi" level="INFO"/>
+    <logger name="org.apache.nifi.controller.service" level="DEBUG"/>
     <logger name="org.apache.nifi.encrypt" level="DEBUG"/>
     <logger name="org.apache.nifi.controller.service.mock" level="ERROR"/>
-    <logger 
name="org.apache.nifi.controller.service.StandardControllerServiceProvider" 
level="WARN" />
 
     <logger name="StandardProcessSession.claims" level="INFO" />
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/604656fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-utils/src/main/java/org/apache/nifi/nar/ExtensionManager.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-utils/src/main/java/org/apache/nifi/nar/ExtensionManager.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-utils/src/main/java/org/apache/nifi/nar/ExtensionManager.java
index 3501351..f4a59f8 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-utils/src/main/java/org/apache/nifi/nar/ExtensionManager.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-utils/src/main/java/org/apache/nifi/nar/ExtensionManager.java
@@ -381,7 +381,7 @@ public class ExtensionManager {
 
         if (logger.isTraceEnabled()) {
             for (URL url : instanceClassLoader.getURLs()) {
-                logger.trace("URL resource {} for {}...", new 
Object[]{url.toExternalForm(), instanceIdentifier});
+                logger.trace("URL resource {} for {}...", new Object[] 
{url.toExternalForm(), instanceIdentifier});
             }
         }
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/604656fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ControllerServiceAuditor.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ControllerServiceAuditor.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ControllerServiceAuditor.java
index efb11a0..4856065 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ControllerServiceAuditor.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ControllerServiceAuditor.java
@@ -27,7 +27,7 @@ import org.apache.nifi.authorization.user.NiFiUser;
 import org.apache.nifi.authorization.user.NiFiUserUtils;
 import org.apache.nifi.bundle.BundleCoordinate;
 import org.apache.nifi.components.PropertyDescriptor;
-import org.apache.nifi.controller.ConfiguredComponent;
+import org.apache.nifi.controller.ComponentNode;
 import org.apache.nifi.controller.ProcessorNode;
 import org.apache.nifi.controller.ReportingTaskNode;
 import org.apache.nifi.controller.ScheduledState;
@@ -259,9 +259,9 @@ public class ControllerServiceAuditor extends NiFiAuditor {
      * @param referencingComponents components
      */
     private void getUpdateActionsForReferencingComponents(
-            final NiFiUser user, final Collection<Action> actions, final 
Collection<String> visitedServices, final Set<ConfiguredComponent> 
referencingComponents) {
+            final NiFiUser user, final Collection<Action> actions, final 
Collection<String> visitedServices, final Set<ComponentNode> 
referencingComponents) {
         // consider each component updates
-        for (final ConfiguredComponent component : referencingComponents) {
+        for (final ComponentNode component : referencingComponents) {
             if (component instanceof ProcessorNode) {
                 final ProcessorNode processor = ((ProcessorNode) component);
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/604656fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/StandardAuthorizableLookup.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/StandardAuthorizableLookup.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/StandardAuthorizableLookup.java
index d70d5fa..0468f23 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/StandardAuthorizableLookup.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/StandardAuthorizableLookup.java
@@ -34,7 +34,7 @@ import org.apache.nifi.components.RequiredPermission;
 import org.apache.nifi.connectable.Connectable;
 import org.apache.nifi.connectable.Connection;
 import org.apache.nifi.connectable.Port;
-import org.apache.nifi.controller.ConfiguredComponent;
+import org.apache.nifi.controller.ComponentNode;
 import org.apache.nifi.controller.ProcessorNode;
 import org.apache.nifi.controller.ReportingTaskNode;
 import org.apache.nifi.controller.Snippet;
@@ -324,9 +324,9 @@ class StandardAuthorizableLookup implements 
AuthorizableLookup {
         return FLOW_AUTHORIZABLE;
     }
 
-    private ConfiguredComponent 
findControllerServiceReferencingComponent(final ControllerServiceReference 
referencingComponents, final String id) {
-        ConfiguredComponent reference = null;
-        for (final ConfiguredComponent component : 
referencingComponents.getReferencingComponents()) {
+    private ComponentNode findControllerServiceReferencingComponent(final 
ControllerServiceReference referencingComponents, final String id) {
+        ComponentNode reference = null;
+        for (final ComponentNode component : 
referencingComponents.getReferencingComponents()) {
             if (component.getIdentifier().equals(id)) {
                 reference = component;
                 break;
@@ -348,7 +348,7 @@ class StandardAuthorizableLookup implements 
AuthorizableLookup {
     public Authorizable getControllerServiceReferencingComponent(String 
controllerServiceId, String id) {
         final ControllerServiceNode controllerService = 
controllerServiceDAO.getControllerService(controllerServiceId);
         final ControllerServiceReference referencingComponents = 
controllerService.getReferences();
-        final ConfiguredComponent reference = 
findControllerServiceReferencingComponent(referencingComponents, id);
+        final ComponentNode reference = 
findControllerServiceReferencingComponent(referencingComponents, id);
 
         if (reference == null) {
             throw new ResourceNotFoundException("Unable to find referencing 
component with id " + id);
@@ -483,9 +483,10 @@ class StandardAuthorizableLookup implements 
AuthorizableLookup {
         // if this is a policy or a provenance event resource, there should be 
another resource type
         if (ResourceType.Policy.equals(resourceType) || 
ResourceType.Data.equals(resourceType) || 
ResourceType.DataTransfer.equals(resourceType)) {
             final ResourceType primaryResourceType = resourceType;
+            resourceType = null;
 
             // get the resource type
-            resource = StringUtils.substringAfter(resource, 
resourceType.getValue());
+            resource = StringUtils.substringAfter(resource, 
primaryResourceType.getValue());
 
             for (ResourceType type : ResourceType.values()) {
                 if (resource.equals(type.getValue()) || 
resource.startsWith(type.getValue() + "/")) {
@@ -494,7 +495,7 @@ class StandardAuthorizableLookup implements 
AuthorizableLookup {
             }
 
             if (resourceType == null) {
-                throw new ResourceNotFoundException("Unrecognized resource: " 
+ resource);
+                throw new ResourceNotFoundException("Unrecognized base 
resource: " + resource);
             }
 
             // must either be a policy, event, or data transfer

http://git-wip-us.apache.org/repos/asf/nifi/blob/604656fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
index 241c83d..0a008ea 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
@@ -64,7 +64,7 @@ import org.apache.nifi.connectable.Connectable;
 import org.apache.nifi.connectable.Connection;
 import org.apache.nifi.connectable.Funnel;
 import org.apache.nifi.connectable.Port;
-import org.apache.nifi.controller.ConfiguredComponent;
+import org.apache.nifi.controller.ComponentNode;
 import org.apache.nifi.controller.Counter;
 import org.apache.nifi.controller.FlowController;
 import org.apache.nifi.controller.ProcessorNode;
@@ -868,9 +868,9 @@ public class StandardNiFiServiceFacade implements 
NiFiServiceFacade {
 
         final Set<String> updatedVariableNames = getUpdatedVariables(group, 
variableMap);
         for (final String variableName : updatedVariableNames) {
-            final Set<ConfiguredComponent> affectedComponents = 
group.getComponentsAffectedByVariable(variableName);
+            final Set<ComponentNode> affectedComponents = 
group.getComponentsAffectedByVariable(variableName);
 
-            for (final ConfiguredComponent component : affectedComponents) {
+            for (final ComponentNode component : affectedComponents) {
                 if (component instanceof ProcessorNode) {
                     final ProcessorNode procNode = (ProcessorNode) component;
                     if (procNode.isRunning()) {
@@ -906,7 +906,7 @@ public class StandardNiFiServiceFacade implements 
NiFiServiceFacade {
 
         final Set<String> updatedVariableNames = getUpdatedVariables(group, 
variableMap);
         for (final String variableName : updatedVariableNames) {
-            final Set<ConfiguredComponent> affectedComponents = 
group.getComponentsAffectedByVariable(variableName);
+            final Set<ComponentNode> affectedComponents = 
group.getComponentsAffectedByVariable(variableName);
             
affectedComponentEntities.addAll(dtoFactory.createAffectedComponentEntities(affectedComponents,
 revisionManager));
         }
 
@@ -1738,6 +1738,8 @@ public class StandardNiFiServiceFacade implements 
NiFiServiceFacade {
         if (flow.getProcessors() != null) {
             for (final ProcessorDTO processorDTO : flow.getProcessors()) {
                 final ProcessorNode processorNode = 
processorDAO.getProcessor(processorDTO.getId());
+                
processorDTO.setValidationStatus(processorNode.getValidationStatus().name());
+
                 final Collection<ValidationResult> validationErrors = 
processorNode.getValidationErrors();
                 if (validationErrors != null && !validationErrors.isEmpty()) {
                     final List<String> errors = new ArrayList<>();
@@ -2199,10 +2201,10 @@ public class StandardNiFiServiceFacade implements 
NiFiServiceFacade {
         return 
entityFactory.createControllerServiceEntity(snapshot.getComponent(), 
dtoFactory.createRevisionDTO(snapshot.getLastModification()), permissions, 
bulletinEntities);
     }
 
-    private Set<ConfiguredComponent> findAllReferencingComponents(final 
ControllerServiceReference reference) {
-        final Set<ConfiguredComponent> referencingComponents = new 
HashSet<>(reference.getReferencingComponents());
+    private Set<ComponentNode> findAllReferencingComponents(final 
ControllerServiceReference reference) {
+        final Set<ComponentNode> referencingComponents = new 
HashSet<>(reference.getReferencingComponents());
 
-        for (final ConfiguredComponent referencingComponent : 
reference.getReferencingComponents()) {
+        for (final ComponentNode referencingComponent : 
reference.getReferencingComponents()) {
             if (referencingComponent instanceof ControllerServiceNode) {
                 
referencingComponents.addAll(findAllReferencingComponents(((ControllerServiceNode)
 referencingComponent).getReferences()));
             }
@@ -2222,19 +2224,19 @@ public class StandardNiFiServiceFacade implements 
NiFiServiceFacade {
                 new 
UpdateRevisionTask<ControllerServiceReferencingComponentsEntity>() {
                     @Override
                     public 
RevisionUpdate<ControllerServiceReferencingComponentsEntity> update() {
-                        final Set<ConfiguredComponent> updated = 
controllerServiceDAO.updateControllerServiceReferencingComponents(controllerServiceId,
 scheduledState, controllerServiceState);
+                        final Set<ComponentNode> updated = 
controllerServiceDAO.updateControllerServiceReferencingComponents(controllerServiceId,
 scheduledState, controllerServiceState);
                         final ControllerServiceReference updatedReference = 
controllerServiceDAO.getControllerService(controllerServiceId).getReferences();
 
                         // get the revisions of the updated components
                         final Map<String, Revision> updatedRevisions = new 
HashMap<>();
-                        for (final ConfiguredComponent component : updated) {
+                        for (final ComponentNode component : updated) {
                             final Revision currentRevision = 
revisionManager.getRevision(component.getIdentifier());
                             final Revision requestRevision = 
referenceRevisions.get(component.getIdentifier());
                             updatedRevisions.put(component.getIdentifier(), 
currentRevision.incrementRevision(requestRevision.getClientId()));
                         }
 
                         // ensure the revision for all referencing components 
is included regardless of whether they were updated in this request
-                        for (final ConfiguredComponent component : 
findAllReferencingComponents(updatedReference)) {
+                        for (final ComponentNode component : 
findAllReferencingComponents(updatedReference)) {
                             
updatedRevisions.putIfAbsent(component.getIdentifier(), 
revisionManager.getRevision(component.getIdentifier()));
                         }
 
@@ -2253,7 +2255,7 @@ public class StandardNiFiServiceFacade implements 
NiFiServiceFacade {
      * @param visited        ControllerServices we've already visited
      */
     private void findControllerServiceReferencingComponentIdentifiers(final 
ControllerServiceReference reference, final Set<ControllerServiceNode> visited) 
{
-        for (final ConfiguredComponent component : 
reference.getReferencingComponents()) {
+        for (final ComponentNode component : 
reference.getReferencingComponents()) {
 
             // if this is a ControllerService consider it's referencing 
components
             if (component instanceof ControllerServiceNode) {
@@ -2278,7 +2280,7 @@ public class StandardNiFiServiceFacade implements 
NiFiServiceFacade {
         findControllerServiceReferencingComponentIdentifiers(reference, 
visited);
 
         final Map<String, Revision> referencingRevisions = new HashMap<>();
-        for (final ConfiguredComponent component : 
reference.getReferencingComponents()) {
+        for (final ComponentNode component : 
reference.getReferencingComponents()) {
             referencingRevisions.put(component.getIdentifier(), 
revisionManager.getRevision(component.getIdentifier()));
         }
 
@@ -2311,10 +2313,10 @@ public class StandardNiFiServiceFacade implements 
NiFiServiceFacade {
             final ControllerServiceReference reference, final Map<String, 
Revision> revisions, final Set<ControllerServiceNode> visited) {
 
         final String modifier = NiFiUserUtils.getNiFiUserIdentity();
-        final Set<ConfiguredComponent> referencingComponents = 
reference.getReferencingComponents();
+        final Set<ComponentNode> referencingComponents = 
reference.getReferencingComponents();
 
         final Set<ControllerServiceReferencingComponentEntity> 
componentEntities = new HashSet<>();
-        for (final ConfiguredComponent refComponent : referencingComponents) {
+        for (final ComponentNode refComponent : referencingComponents) {
             PermissionsDTO permissions = null;
             if (refComponent instanceof Authorizable) {
                 permissions = dtoFactory.createPermissionsDto(refComponent);
@@ -2338,7 +2340,7 @@ public class StandardNiFiServiceFacade implements 
NiFiServiceFacade {
                 if (!dto.getReferenceCycle()) {
                     final ControllerServiceReference refReferences = 
node.getReferences();
                     final Map<String, Revision> referencingRevisions = new 
HashMap<>(revisions);
-                    for (final ConfiguredComponent component : 
refReferences.getReferencingComponents()) {
+                    for (final ComponentNode component : 
refReferences.getReferencingComponents()) {
                         
referencingRevisions.putIfAbsent(component.getIdentifier(), 
revisionManager.getRevision(component.getIdentifier()));
                     }
                     final ControllerServiceReferencingComponentsEntity 
references = createControllerServiceReferencingComponentsEntity(refReferences, 
referencingRevisions, visited);
@@ -3531,38 +3533,13 @@ public class StandardNiFiServiceFacade implements 
NiFiServiceFacade {
 
     @Override
     public ProcessGroupFlowEntity getProcessGroupFlow(final String groupId) {
-        // get all identifiers for every child component
-        final Set<String> identifiers = new HashSet<>();
         final ProcessGroup processGroup = 
processGroupDAO.getProcessGroup(groupId);
-        processGroup.getProcessors().stream()
-            .map(proc -> proc.getIdentifier())
-            .forEach(id -> identifiers.add(id));
-        processGroup.getConnections().stream()
-            .map(conn -> conn.getIdentifier())
-            .forEach(id -> identifiers.add(id));
-        processGroup.getInputPorts().stream()
-            .map(port -> port.getIdentifier())
-            .forEach(id -> identifiers.add(id));
-        processGroup.getOutputPorts().stream()
-            .map(port -> port.getIdentifier())
-            .forEach(id -> identifiers.add(id));
-        processGroup.getProcessGroups().stream()
-            .map(group -> group.getIdentifier())
-            .forEach(id -> identifiers.add(id));
-        processGroup.getRemoteProcessGroups().stream()
-            .map(remoteGroup -> remoteGroup.getIdentifier())
-            .forEach(id -> identifiers.add(id));
-        processGroup.getRemoteProcessGroups().stream()
-            .flatMap(remoteGroup -> remoteGroup.getInputPorts().stream())
-            .map(remoteInputPort -> remoteInputPort.getIdentifier())
-            .forEach(id -> identifiers.add(id));
-        processGroup.getRemoteProcessGroups().stream()
-            .flatMap(remoteGroup -> remoteGroup.getOutputPorts().stream())
-            .map(remoteOutputPort -> remoteOutputPort.getIdentifier())
-            .forEach(id -> identifiers.add(id));
-
-        // read lock on every component being accessed in the dto conversion
-        final ProcessGroupStatus groupStatus = 
controllerFacade.getProcessGroupStatus(groupId);
+
+        // Get the Process Group Status but we only need a status depth of one 
because for any child process group,
+        // we ignore the status of each individual components. I.e., if 
Process Group A has child Group B, and child Group B
+        // has a Processor, we don't care about the individual stats of that 
Processor because the ProcessGroupFlowEntity
+        // doesn't include that anyway. So we can avoid including the 
information in the status that is returned.
+        final ProcessGroupStatus groupStatus = 
controllerFacade.getProcessGroupStatus(groupId, 1);
         final PermissionsDTO permissions = 
dtoFactory.createPermissionsDto(processGroup);
         return 
entityFactory.createProcessGroupFlowEntity(dtoFactory.createProcessGroupFlowDto(processGroup,
 groupStatus, revisionManager, this::getProcessGroupBulletins), permissions);
     }

http://git-wip-us.apache.org/repos/asf/nifi/blob/604656fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowResource.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowResource.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowResource.java
index 0382e8a..eaa48d2 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowResource.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowResource.java
@@ -36,6 +36,7 @@ import org.apache.nifi.cluster.manager.NodeResponse;
 import org.apache.nifi.cluster.protocol.NodeIdentifier;
 import org.apache.nifi.connectable.Port;
 import org.apache.nifi.controller.ProcessorNode;
+import org.apache.nifi.components.validation.ValidationStatus;
 import org.apache.nifi.controller.ScheduledState;
 import org.apache.nifi.controller.service.ControllerServiceNode;
 import org.apache.nifi.controller.service.ControllerServiceState;
@@ -745,12 +746,12 @@ public class FlowResource extends ApplicationResource {
                 + "not equal the process group id of the requested resource 
(%s).", requestEntity.getId(), id));
         }
 
-        final ControllerServiceState state;
+        final ControllerServiceState desiredState;
         if (requestEntity.getState() == null) {
             throw new IllegalArgumentException("The controller service state 
must be specified.");
         } else {
             try {
-                state = 
ControllerServiceState.valueOf(requestEntity.getState());
+                desiredState = 
ControllerServiceState.valueOf(requestEntity.getState());
             } catch (final IllegalArgumentException iae) {
                 throw new IllegalArgumentException(String.format("The 
controller service state must be one of [%s].",
                     
StringUtils.join(EnumSet.of(ControllerServiceState.ENABLED, 
ControllerServiceState.DISABLED), ", ")));
@@ -758,7 +759,7 @@ public class FlowResource extends ApplicationResource {
         }
 
         // ensure its a supported scheduled state
-        if (ControllerServiceState.DISABLING.equals(state) || 
ControllerServiceState.ENABLING.equals(state)) {
+        if (ControllerServiceState.DISABLING.equals(desiredState) || 
ControllerServiceState.ENABLING.equals(desiredState)) {
             throw new IllegalArgumentException(String.format("The scheduled 
must be one of [%s].",
                 StringUtils.join(EnumSet.of(ControllerServiceState.ENABLED, 
ControllerServiceState.DISABLED), ", ")));
         }
@@ -770,10 +771,10 @@ public class FlowResource extends ApplicationResource {
                 final Set<String> componentIds = new HashSet<>();
 
                 final Predicate<ControllerServiceNode> filter;
-                if (ControllerServiceState.ENABLED.equals(state)) {
-                    filter = service -> !service.isActive() && 
service.isValid();
+                if (ControllerServiceState.ENABLED.equals(desiredState)) {
+                    filter = service -> !service.isActive() && 
service.getValidationStatus() == ValidationStatus.VALID;
                 } else {
-                    filter = service -> service.isActive();
+                    filter = ControllerServiceNode::isActive;
                 }
 
                 group.findAllControllerServices().stream()
@@ -819,7 +820,7 @@ public class FlowResource extends ApplicationResource {
                         authorizable.authorize(authorizer, 
RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
                     });
                 },
-                () -> serviceFacade.verifyActivateControllerServices(id, 
state, requestComponentRevisions.keySet()),
+            () -> serviceFacade.verifyActivateControllerServices(id, 
desiredState, requestComponentRevisions.keySet()),
                 (revisions, scheduleComponentsEntity) -> {
                 final ControllerServiceState serviceState = 
ControllerServiceState.valueOf(scheduleComponentsEntity.getState());
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/604656fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessGroupResource.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessGroupResource.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessGroupResource.java
index 835aa7e..e16d69a 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessGroupResource.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessGroupResource.java
@@ -3232,7 +3232,7 @@ public class ProcessGroupResource extends 
ApplicationResource {
                 instantiateTemplateRequestEntity -> {
                     // create the template and generate the json
                     final FlowEntity entity = 
serviceFacade.createTemplateInstance(groupId, 
instantiateTemplateRequestEntity.getOriginX(), 
instantiateTemplateRequestEntity.getOriginY(),
-                            
instantiateTemplateRequestEntity.getEncodingVersion(), 
instantiateTemplateRequestEntity.getSnippet(), 
getIdGenerationSeed().orElse(null));
+                        instantiateTemplateRequestEntity.getEncodingVersion(), 
instantiateTemplateRequestEntity.getSnippet(), 
getIdGenerationSeed().orElse(null));
 
                     final FlowDTO flowSnippet = entity.getFlow();
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/604656fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/SnippetResource.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/SnippetResource.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/SnippetResource.java
index 6833428..15c75d1 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/SnippetResource.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/SnippetResource.java
@@ -16,12 +16,19 @@
  */
 package org.apache.nifi.web.api;
 
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import io.swagger.annotations.ApiParam;
-import io.swagger.annotations.ApiResponse;
-import io.swagger.annotations.ApiResponses;
-import io.swagger.annotations.Authorization;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.HttpMethod;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
 import org.apache.nifi.authorization.AccessDeniedException;
 import org.apache.nifi.authorization.AuthorizableLookup;
 import org.apache.nifi.authorization.Authorizer;
@@ -35,23 +42,18 @@ import org.apache.nifi.web.api.dto.SnippetDTO;
 import org.apache.nifi.web.api.entity.ComponentEntity;
 import org.apache.nifi.web.api.entity.SnippetEntity;
 
-import javax.servlet.http.HttpServletRequest;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.HttpMethod;
-import javax.ws.rs.POST;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
 import java.net.URI;
 import java.util.Set;
 import java.util.function.Consumer;
 import java.util.stream.Collectors;
 
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+import io.swagger.annotations.Authorization;
+
 /**
  * RESTful endpoint for querying dataflow snippets.
  */
@@ -61,7 +63,6 @@ import java.util.stream.Collectors;
         description = "Endpoint for accessing dataflow snippets."
 )
 public class SnippetResource extends ApplicationResource {
-
     private NiFiServiceFacade serviceFacade;
     private Authorizer authorizer;
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/604656fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
index 26bf442..e3be8d7 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
@@ -64,6 +64,7 @@ import org.apache.nifi.components.PropertyDescriptor;
 import org.apache.nifi.components.ValidationResult;
 import org.apache.nifi.components.state.Scope;
 import org.apache.nifi.components.state.StateMap;
+import org.apache.nifi.components.validation.ValidationStatus;
 import org.apache.nifi.connectable.Connectable;
 import org.apache.nifi.connectable.ConnectableType;
 import org.apache.nifi.connectable.Connection;
@@ -71,7 +72,7 @@ import org.apache.nifi.connectable.Funnel;
 import org.apache.nifi.connectable.Port;
 import org.apache.nifi.connectable.Position;
 import org.apache.nifi.controller.ActiveThreadInfo;
-import org.apache.nifi.controller.ConfiguredComponent;
+import org.apache.nifi.controller.ComponentNode;
 import org.apache.nifi.controller.ControllerService;
 import org.apache.nifi.controller.Counter;
 import org.apache.nifi.controller.FlowController;
@@ -1380,6 +1381,9 @@ public final class DtoFactory {
             dto.getProperties().put(descriptor.getName(), propertyValue);
         }
 
+        final ValidationStatus validationStatus = 
reportingTaskNode.getValidationStatus(1, TimeUnit.MILLISECONDS);
+        dto.setValidationStatus(validationStatus.name());
+
         // add the validation errors
         final Collection<ValidationResult> validationErrors = 
reportingTaskNode.getValidationErrors();
         if (validationErrors != null && !validationErrors.isEmpty()) {
@@ -1458,6 +1462,8 @@ public final class DtoFactory {
             dto.getProperties().put(descriptor.getName(), propertyValue);
         }
 
+        dto.setValidationStatus(controllerServiceNode.getValidationStatus(1, 
TimeUnit.MILLISECONDS).name());
+
         // add the validation errors
         final Collection<ValidationResult> validationErrors = 
controllerServiceNode.getValidationErrors();
         if (validationErrors != null && !validationErrors.isEmpty()) {
@@ -1472,7 +1478,7 @@ public final class DtoFactory {
         return dto;
     }
 
-    public ControllerServiceReferencingComponentDTO 
createControllerServiceReferencingComponentDTO(final ConfiguredComponent 
component) {
+    public ControllerServiceReferencingComponentDTO 
createControllerServiceReferencingComponentDTO(final ComponentNode component) {
         final ControllerServiceReferencingComponentDTO dto = new 
ControllerServiceReferencingComponentDTO();
         dto.setId(component.getIdentifier());
         dto.setName(component.getName());
@@ -1913,7 +1919,7 @@ public final class DtoFactory {
     }
 
 
-    public AffectedComponentDTO createAffectedComponentDto(final 
ConfiguredComponent component) {
+    public AffectedComponentDTO createAffectedComponentDto(final ComponentNode 
component) {
         final AffectedComponentDTO dto = new AffectedComponentDTO();
         dto.setId(component.getIdentifier());
         dto.setName(component.getName());
@@ -2491,7 +2497,7 @@ public final class DtoFactory {
         return deprecationNotice == null ? null : deprecationNotice.reason();
     }
 
-    public Set<AffectedComponentEntity> createAffectedComponentEntities(final 
Set<ConfiguredComponent> affectedComponents, final RevisionManager 
revisionManager) {
+    public Set<AffectedComponentEntity> createAffectedComponentEntities(final 
Set<ComponentNode> affectedComponents, final RevisionManager revisionManager) {
         return affectedComponents.stream()
                 .map(component -> {
                     final AffectedComponentDTO affectedComponent = 
createAffectedComponentDto(component);
@@ -2816,6 +2822,9 @@ public final class DtoFactory {
         dto.setSupportsBatching(node.isSessionBatchingSupported());
         dto.setConfig(createProcessorConfigDto(node));
 
+        final ValidationStatus validationStatus = node.getValidationStatus(1, 
TimeUnit.MILLISECONDS);
+        dto.setValidationStatus(validationStatus.name());
+
         final Collection<ValidationResult> validationErrors = 
node.getValidationErrors();
         if (validationErrors != null && !validationErrors.isEmpty()) {
             final List<String> errors = new ArrayList<>();
@@ -3682,6 +3691,7 @@ public final class DtoFactory {
         
copy.setMultipleVersionsAvailable(original.getMultipleVersionsAvailable());
         copy.setPersistsState(original.getPersistsState());
         copy.setValidationErrors(copy(original.getValidationErrors()));
+        copy.setValidationStatus(original.getValidationStatus());
         copy.setVersionedComponentId(original.getVersionedComponentId());
         return copy;
     }
@@ -3760,6 +3770,7 @@ public final class DtoFactory {
         copy.setExtensionMissing(original.getExtensionMissing());
         
copy.setMultipleVersionsAvailable(original.getMultipleVersionsAvailable());
         copy.setValidationErrors(copy(original.getValidationErrors()));
+        copy.setValidationStatus(original.getValidationStatus());
         copy.setVersionedComponentId(original.getVersionedComponentId());
 
         return copy;

http://git-wip-us.apache.org/repos/asf/nifi/blob/604656fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
index 9663d3b..1d9be9c 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
@@ -603,7 +603,18 @@ public class ControllerFacade implements Authorizable {
      * @return the status for the specified process group
      */
     public ProcessGroupStatus getProcessGroupStatus(final String groupId) {
-        final ProcessGroupStatus processGroupStatus = 
flowController.getGroupStatus(groupId, NiFiUserUtils.getNiFiUser());
+        return getProcessGroupStatus(groupId, Integer.MAX_VALUE);
+    }
+
+    /**
+     * Gets the status for the specified process group.
+     *
+     * @param groupId group id
+     * @param recursiveStatusDepth the number of levels deep that we want to 
go before deciding to stop including component statuses
+     * @return the status for the specified process group
+     */
+    public ProcessGroupStatus getProcessGroupStatus(final String groupId, 
final int recursiveStatusDepth) {
+        final ProcessGroupStatus processGroupStatus = 
flowController.getGroupStatus(groupId, NiFiUserUtils.getNiFiUser(), 
recursiveStatusDepth);
         if (processGroupStatus == null) {
             throw new ResourceNotFoundException(String.format("Unable to 
locate group with id '%s'.", groupId));
         }
@@ -628,7 +639,7 @@ public class ControllerFacade implements Authorizable {
 
         // calculate the process group status
         final String groupId = processor.getProcessGroup().getIdentifier();
-        final ProcessGroupStatus processGroupStatus = 
flowController.getGroupStatus(groupId, NiFiUserUtils.getNiFiUser());
+        final ProcessGroupStatus processGroupStatus = 
flowController.getGroupStatus(groupId, NiFiUserUtils.getNiFiUser(), 1);
         if (processGroupStatus == null) {
             throw new ResourceNotFoundException(String.format("Unable to 
locate group with id '%s'.", groupId));
         }
@@ -658,7 +669,7 @@ public class ControllerFacade implements Authorizable {
 
         // calculate the process group status
         final String groupId = connection.getProcessGroup().getIdentifier();
-        final ProcessGroupStatus processGroupStatus = 
flowController.getGroupStatus(groupId, NiFiUserUtils.getNiFiUser());
+        final ProcessGroupStatus processGroupStatus = 
flowController.getGroupStatus(groupId, NiFiUserUtils.getNiFiUser(), 1);
         if (processGroupStatus == null) {
             throw new ResourceNotFoundException(String.format("Unable to 
locate group with id '%s'.", groupId));
         }
@@ -687,7 +698,7 @@ public class ControllerFacade implements Authorizable {
         }
 
         final String groupId = port.getProcessGroup().getIdentifier();
-        final ProcessGroupStatus processGroupStatus = 
flowController.getGroupStatus(groupId, NiFiUserUtils.getNiFiUser());
+        final ProcessGroupStatus processGroupStatus = 
flowController.getGroupStatus(groupId, NiFiUserUtils.getNiFiUser(), 1);
         if (processGroupStatus == null) {
             throw new ResourceNotFoundException(String.format("Unable to 
locate group with id '%s'.", groupId));
         }
@@ -716,7 +727,7 @@ public class ControllerFacade implements Authorizable {
         }
 
         final String groupId = port.getProcessGroup().getIdentifier();
-        final ProcessGroupStatus processGroupStatus = 
flowController.getGroupStatus(groupId, NiFiUserUtils.getNiFiUser());
+        final ProcessGroupStatus processGroupStatus = 
flowController.getGroupStatus(groupId, NiFiUserUtils.getNiFiUser(), 1);
         if (processGroupStatus == null) {
             throw new ResourceNotFoundException(String.format("Unable to 
locate group with id '%s'.", groupId));
         }
@@ -745,7 +756,7 @@ public class ControllerFacade implements Authorizable {
         }
 
         final String groupId = 
remoteProcessGroup.getProcessGroup().getIdentifier();
-        final ProcessGroupStatus groupStatus = 
flowController.getGroupStatus(groupId, NiFiUserUtils.getNiFiUser());
+        final ProcessGroupStatus groupStatus = 
flowController.getGroupStatus(groupId, NiFiUserUtils.getNiFiUser(), 1);
         if (groupStatus == null) {
             throw new ResourceNotFoundException(String.format("Unable to 
locate group with id '%s'.", groupId));
         }

http://git-wip-us.apache.org/repos/asf/nifi/blob/604656fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerSearchService.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerSearchService.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerSearchService.java
index 0194b8c..ae84db0 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerSearchService.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerSearchService.java
@@ -23,6 +23,7 @@ import org.apache.nifi.authorization.RequestAction;
 import org.apache.nifi.authorization.user.NiFiUser;
 import org.apache.nifi.authorization.user.NiFiUserUtils;
 import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.components.validation.ValidationStatus;
 import org.apache.nifi.connectable.Connectable;
 import org.apache.nifi.connectable.Connection;
 import org.apache.nifi.connectable.Funnel;
@@ -240,8 +241,10 @@ public class ControllerSearchService {
                 matches.add("Run status: Disabled");
             }
         } else {
-            if (StringUtils.containsIgnoreCase("invalid", searchStr) && 
!procNode.isValid()) {
+            if (StringUtils.containsIgnoreCase("invalid", searchStr) && 
procNode.getValidationStatus() == ValidationStatus.INVALID) {
                 matches.add("Run status: Invalid");
+            } else if (StringUtils.containsIgnoreCase("validating", searchStr) 
&& procNode.getValidationStatus() == ValidationStatus.VALIDATING) {
+                matches.add("Run status: Validating");
             } else if 
(ScheduledState.RUNNING.equals(procNode.getScheduledState()) && 
StringUtils.containsIgnoreCase("running", searchStr)) {
                 matches.add("Run status: Running");
             } else if 
(ScheduledState.STOPPED.equals(procNode.getScheduledState()) && 
StringUtils.containsIgnoreCase("stopped", searchStr)) {

http://git-wip-us.apache.org/repos/asf/nifi/blob/604656fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/ControllerServiceDAO.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/ControllerServiceDAO.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/ControllerServiceDAO.java
index 0409e95..2a2ba6b 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/ControllerServiceDAO.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/ControllerServiceDAO.java
@@ -18,7 +18,7 @@ package org.apache.nifi.web.dao;
 
 import org.apache.nifi.components.state.Scope;
 import org.apache.nifi.components.state.StateMap;
-import org.apache.nifi.controller.ConfiguredComponent;
+import org.apache.nifi.controller.ComponentNode;
 import org.apache.nifi.controller.ScheduledState;
 import org.apache.nifi.controller.service.ControllerServiceNode;
 import org.apache.nifi.controller.service.ControllerServiceState;
@@ -81,7 +81,7 @@ public interface ControllerServiceDAO {
      * @param controllerServiceState the value of state
      * @return the set of all components that were modified as a result of 
this action
      */
-    Set<ConfiguredComponent> 
updateControllerServiceReferencingComponents(String controllerServiceId, 
ScheduledState scheduledState, ControllerServiceState controllerServiceState);
+    Set<ComponentNode> updateControllerServiceReferencingComponents(String 
controllerServiceId, ScheduledState scheduledState, ControllerServiceState 
controllerServiceState);
 
     /**
      * Determines whether this controller service can be updated.

http://git-wip-us.apache.org/repos/asf/nifi/blob/604656fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardControllerServiceDAO.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardControllerServiceDAO.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardControllerServiceDAO.java
index 5622097..0c889f5 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardControllerServiceDAO.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardControllerServiceDAO.java
@@ -22,7 +22,7 @@ import org.apache.nifi.bundle.BundleCoordinate;
 import org.apache.nifi.components.ConfigurableComponent;
 import org.apache.nifi.components.state.Scope;
 import org.apache.nifi.components.state.StateMap;
-import org.apache.nifi.controller.ConfiguredComponent;
+import org.apache.nifi.controller.ComponentNode;
 import org.apache.nifi.controller.FlowController;
 import org.apache.nifi.controller.ScheduledState;
 import 
org.apache.nifi.controller.exception.ControllerServiceInstantiationException;
@@ -180,7 +180,7 @@ public class StandardControllerServiceDAO extends 
ComponentDAO implements Contro
             // and notify the Process Group that a component has been 
modified. This way, we know to re-calculate
             // whether or not the Process Group has local modifications.
             
controllerService.getReferences().getReferencingComponents().stream()
-                .map(ConfiguredComponent::getProcessGroupIdentifier)
+                .map(ComponentNode::getProcessGroupIdentifier)
                 .filter(id -> !id.equals(group.getIdentifier()))
                 .forEach(groupId -> {
                     final ProcessGroup descendant = 
group.findProcessGroup(groupId);
@@ -213,7 +213,7 @@ public class StandardControllerServiceDAO extends 
ComponentDAO implements Contro
     }
 
     @Override
-    public Set<ConfiguredComponent> 
updateControllerServiceReferencingComponents(
+    public Set<ComponentNode> updateControllerServiceReferencingComponents(
             final String controllerServiceId, final ScheduledState 
scheduledState, final ControllerServiceState controllerServiceState) {
         // get the controller service
         final ControllerServiceNode controllerService = 
locateControllerService(controllerServiceId);

http://git-wip-us.apache.org/repos/asf/nifi/blob/604656fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardProcessorDAO.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardProcessorDAO.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardProcessorDAO.java
index 5838f37..e9a665a 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardProcessorDAO.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardProcessorDAO.java
@@ -313,7 +313,7 @@ public class StandardProcessorDAO extends ComponentDAO 
implements ProcessorDAO {
         if (includeDescendants) {
             return 
group.findAllProcessors().stream().collect(Collectors.toSet());
         } else {
-            return group.getProcessors();
+            return new HashSet<>(group.getProcessors());
         }
     }
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/604656fe/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/DebugFlow.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/DebugFlow.java
 
b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/DebugFlow.java
index 93047b7..86e5080 100644
--- 
a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/DebugFlow.java
+++ 
b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/DebugFlow.java
@@ -20,6 +20,7 @@ import java.io.IOException;
 import java.io.OutputStream;
 import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
@@ -36,6 +37,7 @@ import org.apache.nifi.components.PropertyDescriptor;
 import org.apache.nifi.components.ValidationContext;
 import org.apache.nifi.components.ValidationResult;
 import org.apache.nifi.components.Validator;
+import org.apache.nifi.expression.ExpressionLanguageScope;
 import org.apache.nifi.flowfile.FlowFile;
 import org.apache.nifi.flowfile.attributes.CoreAttributes;
 import org.apache.nifi.logging.ComponentLog;
@@ -213,11 +215,19 @@ public class DebugFlow extends AbstractProcessor {
         .defaultValue("0 sec")
         .addValidator(StandardValidators.TIME_PERIOD_VALIDATOR)
         .build();
+    static final PropertyDescriptor CUSTOM_VALIDATE_SLEEP_TIME = new 
PropertyDescriptor.Builder()
+        .name("CustomValidate Pause Time")
+        .displayName("CustomValidate Pause Time")
+        .description("Specifies how long the processor should sleep in the 
customValidate() method")
+        .addValidator(StandardValidators.TIME_PERIOD_VALIDATOR)
+        .defaultValue("0 sec")
+        .required(true)
+        .build();
     static final PropertyDescriptor IGNORE_INTERRUPTS = new 
PropertyDescriptor.Builder()
         .name("Ignore Interrupts When Paused")
         .description("If the Processor's thread(s) are sleeping (due to one of 
the \"Pause Time\" properties above), and the thread is interrupted, "
             + "this indicates whether the Processor should ignore the 
interrupt and continue sleeping or if it should allow itself to be 
interrupted.")
-        .expressionLanguageSupported(false)
+        .expressionLanguageSupported(ExpressionLanguageScope.NONE)
         .allowableValues("true", "false")
         .defaultValue("false")
         .required(true)
@@ -289,6 +299,7 @@ public class DebugFlow extends AbstractProcessor {
                 propList.add(ON_STOPPED_SLEEP_TIME);
                 propList.add(ON_STOPPED_FAIL);
                 propList.add(ON_TRIGGER_SLEEP_TIME);
+                propList.add(CUSTOM_VALIDATE_SLEEP_TIME);
                 propList.add(IGNORE_INTERRUPTS);
 
                 propertyDescriptors.compareAndSet(null, 
Collections.unmodifiableList(propList));
@@ -334,6 +345,23 @@ public class DebugFlow extends AbstractProcessor {
         fail(context.getProperty(ON_STOPPED_FAIL).asBoolean(), 
OnStopped.class);
     }
 
+    @Override
+    protected Collection<ValidationResult> customValidate(ValidationContext 
validationContext) {
+        try {
+            
sleep(validationContext.getProperty(CUSTOM_VALIDATE_SLEEP_TIME).asTimePeriod(TimeUnit.MILLISECONDS),
+                validationContext.getProperty(IGNORE_INTERRUPTS).asBoolean());
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+
+            return Collections.singleton(new ValidationResult.Builder()
+                .valid(false)
+                .subject("Validation")
+                .explanation("Processor Interrupted while performing 
validation").build());
+        }
+
+        return super.customValidate(validationContext);
+    }
+
     private void sleep(final long millis, final boolean ignoreInterrupts) 
throws InterruptedException {
         if (millis > 0L) {
             final long endSleep = System.currentTimeMillis() + millis;

http://git-wip-us.apache.org/repos/asf/nifi/blob/604656fe/nifi-nar-bundles/nifi-standard-services/nifi-ssl-context-bundle/nifi-ssl-context-service/src/test/java/org/apache/nifi/ssl/SSLContextServiceTest.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-standard-services/nifi-ssl-context-bundle/nifi-ssl-context-service/src/test/java/org/apache/nifi/ssl/SSLContextServiceTest.java
 
b/nifi-nar-bundles/nifi-standard-services/nifi-ssl-context-bundle/nifi-ssl-context-service/src/test/java/org/apache/nifi/ssl/SSLContextServiceTest.java
index 4c00bdc..fd0df1f 100644
--- 
a/nifi-nar-bundles/nifi-standard-services/nifi-ssl-context-bundle/nifi-ssl-context-service/src/test/java/org/apache/nifi/ssl/SSLContextServiceTest.java
+++ 
b/nifi-nar-bundles/nifi-standard-services/nifi-ssl-context-bundle/nifi-ssl-context-service/src/test/java/org/apache/nifi/ssl/SSLContextServiceTest.java
@@ -62,7 +62,7 @@ public class SSLContextServiceTest {
     public void testBad1() throws InitializationException {
         final TestRunner runner = 
TestRunners.newTestRunner(TestProcessor.class);
         final SSLContextService service = new StandardSSLContextService();
-        final Map<String, String> properties = new HashMap<String, String>();
+        final Map<String, String> properties = new HashMap<>();
         runner.addControllerService("test-bad1", service, properties);
         runner.assertNotValid(service);
     }
@@ -71,7 +71,7 @@ public class SSLContextServiceTest {
     public void testBad2() throws InitializationException {
         final TestRunner runner = 
TestRunners.newTestRunner(TestProcessor.class);
         final SSLContextService service = new StandardSSLContextService();
-        final Map<String, String> properties = new HashMap<String, String>();
+        final Map<String, String> properties = new HashMap<>();
         properties.put(StandardSSLContextService.KEYSTORE.getName(), 
"src/test/resources/localhost-ks.jks");
         properties.put(StandardSSLContextService.KEYSTORE_PASSWORD.getName(), 
"localtest");
         runner.addControllerService("test-bad2", service, properties);
@@ -82,7 +82,7 @@ public class SSLContextServiceTest {
     public void testBad3() throws InitializationException {
         final TestRunner runner = 
TestRunners.newTestRunner(TestProcessor.class);
         final SSLContextService service = new StandardSSLContextService();
-        final Map<String, String> properties = new HashMap<String, String>();
+        final Map<String, String> properties = new HashMap<>();
         properties.put(StandardSSLContextService.KEYSTORE.getName(), 
"src/test/resources/localhost-ks.jks");
         properties.put(StandardSSLContextService.KEYSTORE_PASSWORD.getName(), 
"localtest");
         properties.put(StandardSSLContextService.KEYSTORE_TYPE.getName(), 
"JKS");
@@ -95,7 +95,7 @@ public class SSLContextServiceTest {
     public void testBad4() throws InitializationException {
         final TestRunner runner = 
TestRunners.newTestRunner(TestProcessor.class);
         final SSLContextService service = new StandardSSLContextService();
-        final Map<String, String> properties = new HashMap<String, String>();
+        final Map<String, String> properties = new HashMap<>();
         properties.put(StandardSSLContextService.KEYSTORE.getName(), 
"src/test/resources/localhost-ks.jks");
         properties.put(StandardSSLContextService.KEYSTORE_PASSWORD.getName(), 
"wrongpassword");
         properties.put(StandardSSLContextService.KEYSTORE_TYPE.getName(), 
"PKCS12");
@@ -111,7 +111,7 @@ public class SSLContextServiceTest {
     public void testBad5() throws InitializationException {
         final TestRunner runner = 
TestRunners.newTestRunner(TestProcessor.class);
         final SSLContextService service = new StandardSSLContextService();
-        final Map<String, String> properties = new HashMap<String, String>();
+        final Map<String, String> properties = new HashMap<>();
         properties.put(StandardSSLContextService.KEYSTORE.getName(), 
"src/test/resources/DOES-NOT-EXIST.jks");
         properties.put(StandardSSLContextService.KEYSTORE_PASSWORD.getName(), 
"localtest");
         properties.put(StandardSSLContextService.KEYSTORE_TYPE.getName(), 
"PKCS12");
@@ -224,7 +224,7 @@ public class SSLContextServiceTest {
         // Assert
 
         // Have to exhaust the cached result by checking n-1 more times
-        for (int i = 2; i < sslContextService.getValidationCacheExpiration(); 
i++) {
+        for (int i = 2; i <= sslContextService.getValidationCacheExpiration(); 
i++) {
             validationResults = 
sslContextService.customValidate(validationContext);
             assertTrue("validation results is not empty", 
validationResults.isEmpty());
             logger.info("(" + i + ") 
StandardSSLContextService#customValidate() returned true even though the 
keystore file is no longer available");
@@ -240,7 +240,7 @@ public class SSLContextServiceTest {
         try {
             TestRunner runner = TestRunners.newTestRunner(TestProcessor.class);
             SSLContextService service = new StandardSSLContextService();
-            HashMap<String, String> properties = new HashMap<String, String>();
+            HashMap<String, String> properties = new HashMap<>();
             properties.put(StandardSSLContextService.TRUSTSTORE.getName(), 
"src/test/resources/localhost-ts.jks");
             
properties.put(StandardSSLContextService.TRUSTSTORE_PASSWORD.getName(), 
"localtest");
             
properties.put(StandardSSLContextService.TRUSTSTORE_TYPE.getName(), "JKS");
@@ -261,7 +261,7 @@ public class SSLContextServiceTest {
         try {
             TestRunner runner = TestRunners.newTestRunner(TestProcessor.class);
             SSLContextService service = new StandardSSLContextService();
-            HashMap<String, String> properties = new HashMap<String, String>();
+            HashMap<String, String> properties = new HashMap<>();
             properties.put(StandardSSLContextService.KEYSTORE.getName(), 
"src/test/resources/localhost-ks.jks");
             
properties.put(StandardSSLContextService.KEYSTORE_PASSWORD.getName(), 
"localtest");
             properties.put(StandardSSLContextService.KEYSTORE_TYPE.getName(), 
"JKS");
@@ -285,7 +285,7 @@ public class SSLContextServiceTest {
         try {
             final TestRunner runner = 
TestRunners.newTestRunner(TestProcessor.class);
             final SSLContextService service = new StandardSSLContextService();
-            final Map<String, String> properties = new HashMap<String, 
String>();
+            final Map<String, String> properties = new HashMap<>();
             properties.put(StandardSSLContextService.KEYSTORE.getName(), 
"src/test/resources/diffpass-ks.jks");
             
properties.put(StandardSSLContextService.KEYSTORE_PASSWORD.getName(), 
"storepassword");
             properties.put(StandardSSLContextService.KEY_PASSWORD.getName(), 
"keypassword");
@@ -310,7 +310,7 @@ public class SSLContextServiceTest {
         try {
             final TestRunner runner = 
TestRunners.newTestRunner(TestProcessor.class);
             final SSLContextService service = new StandardSSLContextService();
-            final Map<String, String> properties = new HashMap<String, 
String>();
+            final Map<String, String> properties = new HashMap<>();
             properties.put(StandardSSLContextService.KEYSTORE.getName(), 
"src/test/resources/diffpass-ks.jks");
             
properties.put(StandardSSLContextService.KEYSTORE_PASSWORD.getName(), 
"storepassword");
             properties.put(StandardSSLContextService.KEYSTORE_TYPE.getName(), 
"JKS");

Reply via email to