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();