This is an automated email from the ASF dual-hosted git repository.

bbende pushed a commit to branch NIFI-15258
in repository https://gitbox.apache.org/repos/asf/nifi.git


The following commit(s) were added to refs/heads/NIFI-15258 by this push:
     new ed1f478f25 NIFI-15490: If any processors or controller services are 
missing, make Connector invalid (#10799)
ed1f478f25 is described below

commit ed1f478f253523be7143719d74c6fa9f3abd9698
Author: Mark Payne <[email protected]>
AuthorDate: Thu Jan 22 09:30:45 2026 -0500

    NIFI-15490: If any processors or controller services are missing, make 
Connector invalid (#10799)
---
 .../connector/StandardConnectorNode.java           | 43 ++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git 
a/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/components/connector/StandardConnectorNode.java
 
b/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/components/connector/StandardConnectorNode.java
index 25fb6fef1d..4e2213eb0a 100644
--- 
a/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/components/connector/StandardConnectorNode.java
+++ 
b/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/components/connector/StandardConnectorNode.java
@@ -39,6 +39,7 @@ import org.apache.nifi.controller.ProcessorNode;
 import org.apache.nifi.controller.flow.FlowManager;
 import org.apache.nifi.controller.queue.DropFlowFileStatus;
 import org.apache.nifi.controller.queue.QueueSize;
+import org.apache.nifi.controller.service.ControllerServiceNode;
 import org.apache.nifi.engine.FlowEngine;
 import org.apache.nifi.flow.Bundle;
 import org.apache.nifi.flow.ScheduledState;
@@ -1177,6 +1178,7 @@ public class StandardConnectorNode implements 
ConnectorNode {
             final ConnectorValidationContext validationContext = 
createValidationContext(activeFlowContext);
 
             final List<ValidationResult> allResults = new ArrayList<>();
+            validateManagedFlowComponents(allResults);
             validatePropertyReferences(allResults);
 
             if (allResults.isEmpty()) {
@@ -1216,6 +1218,47 @@ public class StandardConnectorNode implements 
ConnectorNode {
     }
 
 
+    private void validateManagedFlowComponents(final List<ValidationResult> 
results) {
+        final ProcessGroup managedProcessGroup = 
activeFlowContext.getManagedProcessGroup();
+
+        // Check for any missing / ghosted Processors
+        final Set<String> missingProcessors = new HashSet<>();
+        for (final ProcessorNode processor : 
managedProcessGroup.findAllProcessors()) {
+            if (processor.isExtensionMissing()) {
+                
missingProcessors.add(getSimpleClassName(processor.getCanonicalClassName()) + " 
from NAR " + processor.getBundleCoordinate());
+            }
+        }
+
+        if (!missingProcessors.isEmpty()) {
+            results.add(new ValidationResult.Builder()
+                .subject("Missing Processors")
+                .valid(false)
+                .explanation("The following processors are missing: " + 
missingProcessors)
+                .build());
+        }
+
+        // Check for any missing / ghosted Controller Services
+        final Set<String> missingControllerServices = new HashSet<>();
+        for (final ControllerServiceNode controllerService : 
managedProcessGroup.findAllControllerServices()) {
+            if (controllerService.isExtensionMissing()) {
+                
missingControllerServices.add(getSimpleClassName(controllerService.getCanonicalClassName())
 + " from NAR " + controllerService.getBundleCoordinate());
+            }
+        }
+
+        if (!missingControllerServices.isEmpty()) {
+            results.add(new ValidationResult.Builder()
+                .subject("Missing Controller Services")
+                .valid(false)
+                .explanation("The following controller services are missing: " 
+ missingControllerServices)
+                .build());
+        }
+    }
+
+    private static String getSimpleClassName(final String canonicalClassName) {
+        final int lastDot = canonicalClassName.lastIndexOf('.');
+        return lastDot < 0 ? canonicalClassName : 
canonicalClassName.substring(lastDot + 1);
+    }
+
     private void validatePropertyReferences(final List<ValidationResult> 
allResults) {
         final List<ConfigurationStep> configurationSteps = 
getConnector().getConfigurationSteps();
         final ConnectorConfiguration connectorConfiguration = 
activeFlowContext.getConfigurationContext().toConnectorConfiguration();

Reply via email to