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

kdoran 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 ff27361f9f8 NIFI-15621: Allow Configuration to Validate with 
ValidationContext (#10916)
ff27361f9f8 is described below

commit ff27361f9f886825b62fda2b25f3e4da028a0306
Author: Bob Paulin <[email protected]>
AuthorDate: Thu Feb 19 15:34:26 2026 -0600

    NIFI-15621: Allow Configuration to Validate with ValidationContext (#10916)
    
    * Currently this is only implemented for processors in schedule periods
    * Allows connector to pass Validation Context to be used instead of
    current parameter context.
---
 .../c2/command/AgentPropertyValidationContext.java |   5 +
 .../nifi/mock/connectors/tests/CronScheduleIT.java |  68 ++++
 .../mock/connectors/CronScheduleConnector.java     | 106 ++++++
 .../org.apache.nifi.components.connector.Connector |   3 +-
 .../resources/flows/Cron_Schedule_Connector.json   | 410 +++++++++++++++++++++
 .../nifi/script/impl/ValidationContextAdapter.java |   5 +
 .../nifi/controller/StandardProcessorNode.java     | 120 +++---
 .../parameter/StandardParameterProviderNode.java   |   2 +-
 .../service/StandardControllerServiceNode.java     |   2 +-
 .../nifi/processor/StandardValidationContext.java  |  10 +
 .../flow/StandardFlowRegistryClientNode.java       |   3 +-
 .../nifi/controller/AbstractComponentNode.java     |   5 +-
 .../nifi/controller/TestAbstractComponentNode.java |   2 +-
 .../ConnectorValidationContextBridge.java          |  10 +
 .../flowanalysis/StandardFlowAnalysisRuleNode.java |   3 +-
 .../reporting/StandardReportingTaskNode.java       |   3 +-
 .../apache/nifi/util/MockValidationContext.java    |   8 +
 .../reporting/StatelessReportingTaskNode.java      |   3 +-
 18 files changed, 697 insertions(+), 71 deletions(-)

diff --git 
a/minifi/minifi-nar-bundles/minifi-framework-bundle/minifi-framework/minifi-framework-core/src/main/java/org/apache/nifi/minifi/c2/command/AgentPropertyValidationContext.java
 
b/minifi/minifi-nar-bundles/minifi-framework-bundle/minifi-framework/minifi-framework-core/src/main/java/org/apache/nifi/minifi/c2/command/AgentPropertyValidationContext.java
index ed0434949cd..7998a92065a 100644
--- 
a/minifi/minifi-nar-bundles/minifi-framework-bundle/minifi-framework/minifi-framework-core/src/main/java/org/apache/nifi/minifi/c2/command/AgentPropertyValidationContext.java
+++ 
b/minifi/minifi-nar-bundles/minifi-framework-bundle/minifi-framework/minifi-framework-core/src/main/java/org/apache/nifi/minifi/c2/command/AgentPropertyValidationContext.java
@@ -109,4 +109,9 @@ public class AgentPropertyValidationContext implements 
ValidationContext {
     public PropertyValue getProperty(PropertyDescriptor descriptor) {
         throw new UnsupportedOperationException();
     }
+
+    @Override
+    public String evaluateParameters(final String value) {
+        throw new UnsupportedOperationException();
+    }
 }
diff --git 
a/nifi-connector-mock-bundle/nifi-connector-mock-test-bundle/nifi-connector-mock-integration-tests/src/test/java/org/apache/nifi/mock/connectors/tests/CronScheduleIT.java
 
b/nifi-connector-mock-bundle/nifi-connector-mock-test-bundle/nifi-connector-mock-integration-tests/src/test/java/org/apache/nifi/mock/connectors/tests/CronScheduleIT.java
new file mode 100644
index 00000000000..10dea97a432
--- /dev/null
+++ 
b/nifi-connector-mock-bundle/nifi-connector-mock-test-bundle/nifi-connector-mock-integration-tests/src/test/java/org/apache/nifi/mock/connectors/tests/CronScheduleIT.java
@@ -0,0 +1,68 @@
+/*
+ * 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.mock.connectors.tests;
+
+import org.apache.nifi.components.ConfigVerificationResult;
+import org.apache.nifi.mock.connector.StandardConnectorTestRunner;
+import org.apache.nifi.mock.connector.server.ConnectorConfigVerificationResult;
+import org.apache.nifi.mock.connector.server.ConnectorTestRunner;
+import org.junit.jupiter.api.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+
+/**
+ * Integration tests that verify CRON expression validation during 
configuration verification.
+ * The {@code CronScheduleConnector} maps the "Trigger Schedule" connector 
property to a
+ * CRON-driven GenerateFlowFile processor's scheduling period parameter, and 
verification
+ * delegates to the processor's validation which checks the CRON expression.
+ */
+public class CronScheduleIT {
+
+    private static final String CONNECTOR_CLASS = 
"org.apache.nifi.mock.connectors.CronScheduleConnector";
+
+    @Test
+    public void testValidCronExpression() throws IOException {
+        try (final ConnectorTestRunner runner = createRunner()) {
+            final ConnectorConfigVerificationResult result = 
runner.verifyConfiguration("Schedule",
+                    Map.of("Trigger Schedule", "0 0 * * * *"));
+            result.assertNoFailures();
+        }
+    }
+
+    @Test
+    public void testInvalidCronExpression() throws IOException {
+        try (final ConnectorTestRunner runner = createRunner()) {
+            final ConnectorConfigVerificationResult result = 
runner.verifyConfiguration("Schedule",
+                    Map.of("Trigger Schedule", "invalid-cron"));
+            final List<ConfigVerificationResult> failedResults = 
result.getFailedResults();
+            assertFalse(failedResults.isEmpty());
+        }
+    }
+
+    private ConnectorTestRunner createRunner() {
+        return new StandardConnectorTestRunner.Builder()
+                .connectorClassName(CONNECTOR_CLASS)
+                .narLibraryDirectory(new File("target/libDir"))
+                .build();
+    }
+}
diff --git 
a/nifi-connector-mock-bundle/nifi-connector-mock-test-bundle/nifi-connector-mock-test-connectors/src/main/java/org/apache/nifi/mock/connectors/CronScheduleConnector.java
 
b/nifi-connector-mock-bundle/nifi-connector-mock-test-bundle/nifi-connector-mock-test-connectors/src/main/java/org/apache/nifi/mock/connectors/CronScheduleConnector.java
new file mode 100644
index 00000000000..1e257c245c6
--- /dev/null
+++ 
b/nifi-connector-mock-bundle/nifi-connector-mock-test-bundle/nifi-connector-mock-test-connectors/src/main/java/org/apache/nifi/mock/connectors/CronScheduleConnector.java
@@ -0,0 +1,106 @@
+/*
+ * 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.mock.connectors;
+
+import org.apache.nifi.components.ConfigVerificationResult;
+import org.apache.nifi.components.connector.AbstractConnector;
+import org.apache.nifi.components.connector.ConfigurationStep;
+import org.apache.nifi.components.connector.ConnectorConfigurationContext;
+import org.apache.nifi.components.connector.ConnectorPropertyDescriptor;
+import org.apache.nifi.components.connector.ConnectorPropertyGroup;
+import org.apache.nifi.components.connector.FlowUpdateException;
+import org.apache.nifi.components.connector.components.FlowContext;
+import org.apache.nifi.components.connector.components.ProcessorFacade;
+import org.apache.nifi.components.connector.util.VersionedFlowUtils;
+import org.apache.nifi.flow.VersionedExternalFlow;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A test connector that validates CRON scheduling expressions via the 
"Trigger Schedule" parameter.
+ * The underlying flow ({@code Cron_Schedule_Connector.json}) contains a 
CRON-driven
+ * GenerateFlowFile processor whose scheduling period references the {@code 
#{Trigger Schedule}} parameter.
+ * Verification delegates to the processor's validate/verify cycle, which 
checks the CRON expression.
+ */
+public class CronScheduleConnector extends AbstractConnector {
+
+    static final String SCHEDULE_STEP_NAME = "Schedule";
+    static final String TRIGGER_SCHEDULE_PARAM = "Trigger Schedule";
+
+    static final ConnectorPropertyDescriptor TRIGGER_SCHEDULE = new 
ConnectorPropertyDescriptor.Builder()
+            .name(TRIGGER_SCHEDULE_PARAM)
+            .description("CRON expression for the GenerateFlowFile trigger 
schedule")
+            .required(true)
+            .build();
+
+    static final ConnectorPropertyGroup SCHEDULE_GROUP = new 
ConnectorPropertyGroup.Builder()
+            .name("Schedule Settings")
+            .addProperty(TRIGGER_SCHEDULE)
+            .build();
+
+    static final ConfigurationStep SCHEDULE_STEP = new 
ConfigurationStep.Builder()
+            .name(SCHEDULE_STEP_NAME)
+            .propertyGroups(List.of(SCHEDULE_GROUP))
+            .build();
+
+    @Override
+    public VersionedExternalFlow getInitialFlow() {
+        return 
VersionedFlowUtils.loadFlowFromResource("flows/Cron_Schedule_Connector.json");
+    }
+
+    @Override
+    public List<ConfigurationStep> getConfigurationSteps() {
+        return List.of(SCHEDULE_STEP);
+    }
+
+    @Override
+    protected void onStepConfigured(final String stepName, final FlowContext 
flowContext) throws FlowUpdateException {
+        if (SCHEDULE_STEP_NAME.equals(stepName)) {
+            final String triggerSchedule = 
flowContext.getConfigurationContext()
+                    .getProperty(SCHEDULE_STEP_NAME, 
TRIGGER_SCHEDULE_PARAM).getValue();
+            final VersionedExternalFlow flow = getInitialFlow();
+            VersionedFlowUtils.setParameterValue(flow, TRIGGER_SCHEDULE_PARAM, 
triggerSchedule);
+            getInitializationContext().updateFlow(flowContext, flow);
+        }
+    }
+
+    @Override
+    public void applyUpdate(final FlowContext workingContext, final 
FlowContext activeContext) throws FlowUpdateException {
+    }
+
+    @Override
+    public List<ConfigVerificationResult> verifyConfigurationStep(final String 
stepName, final Map<String, String> overrides, final FlowContext flowContext) {
+        if (SCHEDULE_STEP_NAME.equals(stepName)) {
+            final ConnectorConfigurationContext configContext = 
flowContext.getConfigurationContext().createWithOverrides(stepName, overrides);
+            final String triggerSchedule = 
configContext.getProperty(SCHEDULE_STEP_NAME, 
TRIGGER_SCHEDULE_PARAM).getValue();
+
+            final VersionedExternalFlow flow = getInitialFlow();
+            VersionedFlowUtils.setParameterValue(flow, TRIGGER_SCHEDULE_PARAM, 
triggerSchedule);
+
+            final ProcessorFacade generateFlowFile = 
flowContext.getRootGroup().getProcessors().stream()
+                    .filter(p -> 
p.getDefinition().getType().endsWith("GenerateFlowFile"))
+                    .findFirst()
+                    .orElseThrow();
+
+            return generateFlowFile.verify(flow, Map.of());
+        }
+
+        return List.of();
+    }
+}
diff --git 
a/nifi-connector-mock-bundle/nifi-connector-mock-test-bundle/nifi-connector-mock-test-connectors/src/main/resources/META-INF/services/org.apache.nifi.components.connector.Connector
 
b/nifi-connector-mock-bundle/nifi-connector-mock-test-bundle/nifi-connector-mock-test-connectors/src/main/resources/META-INF/services/org.apache.nifi.components.connector.Connector
index b05e5b86f95..379d9026452 100644
--- 
a/nifi-connector-mock-bundle/nifi-connector-mock-test-bundle/nifi-connector-mock-test-connectors/src/main/resources/META-INF/services/org.apache.nifi.components.connector.Connector
+++ 
b/nifi-connector-mock-bundle/nifi-connector-mock-test-bundle/nifi-connector-mock-test-connectors/src/main/resources/META-INF/services/org.apache.nifi.components.connector.Connector
@@ -15,4 +15,5 @@
 
 org.apache.nifi.mock.connectors.AllowableValuesConnector
 org.apache.nifi.mock.connectors.GenerateAndLog
-org.apache.nifi.mock.connectors.MissingBundleConnector
\ No newline at end of file
+org.apache.nifi.mock.connectors.MissingBundleConnector
+org.apache.nifi.mock.connectors.CronScheduleConnector
\ No newline at end of file
diff --git 
a/nifi-connector-mock-bundle/nifi-connector-mock-test-bundle/nifi-connector-mock-test-connectors/src/main/resources/flows/Cron_Schedule_Connector.json
 
b/nifi-connector-mock-bundle/nifi-connector-mock-test-bundle/nifi-connector-mock-test-connectors/src/main/resources/flows/Cron_Schedule_Connector.json
new file mode 100644
index 00000000000..d078d4d6fa8
--- /dev/null
+++ 
b/nifi-connector-mock-bundle/nifi-connector-mock-test-bundle/nifi-connector-mock-test-connectors/src/main/resources/flows/Cron_Schedule_Connector.json
@@ -0,0 +1,410 @@
+{
+    "flowContents": {
+        "identifier": "1800c04e-f9b9-3293-bfc7-b35f43e0706c",
+        "instanceIdentifier": "4f8ca484-019c-1000-955f-68c5defeb22b",
+        "name": "Cron_Schedule_Connector",
+        "comments": "",
+        "position": {
+            "x": -1254.0,
+            "y": -437.70139741897583
+        },
+        "processGroups": [],
+        "remoteProcessGroups": [],
+        "processors": [
+            {
+                "identifier": "4d4160b1-736c-3be4-bc3a-84fc6eb4ad2a",
+                "instanceIdentifier": "499f9781-71c5-367f-aa17-5441bff29de9",
+                "name": "UpdateAttribute",
+                "comments": "",
+                "position": {
+                    "x": -360.0,
+                    "y": 24.0
+                },
+                "type": 
"org.apache.nifi.processors.attributes.UpdateAttribute",
+                "bundle": {
+                    "group": "org.apache.nifi",
+                    "artifact": "nifi-update-attribute-nar",
+                    "version": "2026.1.20.21-SNAPSHOT"
+                },
+                "properties": {
+                    "Delete Attributes Expression": null,
+                    "Store State": "Do not store state",
+                    "Cache Value Lookup Cache Size": "100",
+                    "Stateful Variables Initial Value": null
+                },
+                "propertyDescriptors": {
+                    "Delete Attributes Expression": {
+                        "name": "Delete Attributes Expression",
+                        "displayName": "Delete Attributes Expression",
+                        "identifiesControllerService": false,
+                        "sensitive": false,
+                        "dynamic": false
+                    },
+                    "Store State": {
+                        "name": "Store State",
+                        "displayName": "Store State",
+                        "identifiesControllerService": false,
+                        "sensitive": false,
+                        "dynamic": false
+                    },
+                    "Cache Value Lookup Cache Size": {
+                        "name": "Cache Value Lookup Cache Size",
+                        "displayName": "Cache Value Lookup Cache Size",
+                        "identifiesControllerService": false,
+                        "sensitive": false,
+                        "dynamic": false
+                    },
+                    "Stateful Variables Initial Value": {
+                        "name": "Stateful Variables Initial Value",
+                        "displayName": "Stateful Variables Initial Value",
+                        "identifiesControllerService": false,
+                        "sensitive": false,
+                        "dynamic": false
+                    }
+                },
+                "style": {},
+                "schedulingPeriod": "0 sec",
+                "schedulingStrategy": "TIMER_DRIVEN",
+                "executionNode": "ALL",
+                "penaltyDuration": "30 sec",
+                "yieldDuration": "1 sec",
+                "bulletinLevel": "WARN",
+                "runDurationMillis": 25,
+                "concurrentlySchedulableTaskCount": 1,
+                "autoTerminatedRelationships": [
+                    "success"
+                ],
+                "scheduledState": "ENABLED",
+                "retryCount": 10,
+                "retriedRelationships": [],
+                "backoffMechanism": "PENALIZE_FLOWFILE",
+                "maxBackoffPeriod": "10 mins",
+                "componentType": "PROCESSOR",
+                "groupIdentifier": "1800c04e-f9b9-3293-bfc7-b35f43e0706c"
+            },
+            {
+                "identifier": "54ab8572-0e10-39a5-b553-931f9c253023",
+                "instanceIdentifier": "6d6b9cd3-6d31-330a-40f9-185959ad1c78",
+                "name": "GenerateFlowFile",
+                "comments": "",
+                "position": {
+                    "x": -360.0,
+                    "y": -371.5
+                },
+                "type": "org.apache.nifi.processors.standard.GenerateFlowFile",
+                "bundle": {
+                    "group": "org.apache.nifi",
+                    "artifact": "nifi-standard-nar",
+                    "version": "2026.1.20.21-SNAPSHOT"
+                },
+                "properties": {
+                    "File Size": "0B",
+                    "Batch Size": "1",
+                    "Unique FlowFiles": "false",
+                    "Mime Type": null,
+                    "Custom Text": null,
+                    "Character Set": "UTF-8",
+                    "Data Format": "Text",
+                    "key": "test.key"
+                },
+                "propertyDescriptors": {
+                    "File Size": {
+                        "name": "File Size",
+                        "displayName": "File Size",
+                        "identifiesControllerService": false,
+                        "sensitive": false,
+                        "dynamic": false
+                    },
+                    "Batch Size": {
+                        "name": "Batch Size",
+                        "displayName": "Batch Size",
+                        "identifiesControllerService": false,
+                        "sensitive": false,
+                        "dynamic": false
+                    },
+                    "Unique FlowFiles": {
+                        "name": "Unique FlowFiles",
+                        "displayName": "Unique FlowFiles",
+                        "identifiesControllerService": false,
+                        "sensitive": false,
+                        "dynamic": false
+                    },
+                    "Mime Type": {
+                        "name": "Mime Type",
+                        "displayName": "Mime Type",
+                        "identifiesControllerService": false,
+                        "sensitive": false,
+                        "dynamic": false
+                    },
+                    "Custom Text": {
+                        "name": "Custom Text",
+                        "displayName": "Custom Text",
+                        "identifiesControllerService": false,
+                        "sensitive": false,
+                        "dynamic": false
+                    },
+                    "Character Set": {
+                        "name": "Character Set",
+                        "displayName": "Character Set",
+                        "identifiesControllerService": false,
+                        "sensitive": false,
+                        "dynamic": false
+                    },
+                    "Data Format": {
+                        "name": "Data Format",
+                        "displayName": "Data Format",
+                        "identifiesControllerService": false,
+                        "sensitive": false,
+                        "dynamic": false
+                    },
+                    "key": {
+                        "name": "key",
+                        "displayName": "key",
+                        "identifiesControllerService": false,
+                        "sensitive": false,
+                        "dynamic": true
+                    }
+                },
+                "style": {},
+                "schedulingPeriod": "#{Trigger Schedule}",
+                "schedulingStrategy": "CRON_DRIVEN",
+                "executionNode": "ALL",
+                "penaltyDuration": "30 sec",
+                "yieldDuration": "1 sec",
+                "bulletinLevel": "WARN",
+                "runDurationMillis": 0,
+                "concurrentlySchedulableTaskCount": 1,
+                "autoTerminatedRelationships": [],
+                "scheduledState": "ENABLED",
+                "retryCount": 10,
+                "retriedRelationships": [],
+                "backoffMechanism": "PENALIZE_FLOWFILE",
+                "maxBackoffPeriod": "10 mins",
+                "componentType": "PROCESSOR",
+                "groupIdentifier": "1800c04e-f9b9-3293-bfc7-b35f43e0706c"
+            },
+            {
+                "identifier": "34c1ac1b-1f21-3fd6-a734-726d5b142b7a",
+                "instanceIdentifier": "4f8d0670-019c-1000-1ac6-c81ef75a70d0",
+                "name": "LookupAttribute",
+                "comments": "",
+                "position": {
+                    "x": -360.0,
+                    "y": -168.0
+                },
+                "type": "org.apache.nifi.processors.standard.LookupAttribute",
+                "bundle": {
+                    "group": "org.apache.nifi",
+                    "artifact": "nifi-standard-nar",
+                    "version": "2026.1.20.21-SNAPSHOT"
+                },
+                "properties": {
+                    "Lookup Service": "b013f870-aee8-3cc4-b022-ac385ded928d",
+                    "test.attribute": "${key}",
+                    "Include Empty Values": "true"
+                },
+                "propertyDescriptors": {
+                    "Lookup Service": {
+                        "name": "Lookup Service",
+                        "displayName": "Lookup Service",
+                        "identifiesControllerService": true,
+                        "sensitive": false,
+                        "dynamic": false
+                    },
+                    "test.attribute": {
+                        "name": "test.attribute",
+                        "displayName": "test.attribute",
+                        "identifiesControllerService": false,
+                        "sensitive": false,
+                        "dynamic": true
+                    },
+                    "Include Empty Values": {
+                        "name": "Include Empty Values",
+                        "displayName": "Include Empty Values",
+                        "identifiesControllerService": false,
+                        "sensitive": false,
+                        "dynamic": false
+                    }
+                },
+                "style": {},
+                "schedulingPeriod": "0 sec",
+                "schedulingStrategy": "TIMER_DRIVEN",
+                "executionNode": "ALL",
+                "penaltyDuration": "30 sec",
+                "yieldDuration": "1 sec",
+                "bulletinLevel": "WARN",
+                "runDurationMillis": 0,
+                "concurrentlySchedulableTaskCount": 1,
+                "autoTerminatedRelationships": [
+                    "failure"
+                ],
+                "scheduledState": "ENABLED",
+                "retryCount": 10,
+                "retriedRelationships": [],
+                "backoffMechanism": "PENALIZE_FLOWFILE",
+                "maxBackoffPeriod": "10 mins",
+                "componentType": "PROCESSOR",
+                "groupIdentifier": "1800c04e-f9b9-3293-bfc7-b35f43e0706c"
+            }
+        ],
+        "inputPorts": [],
+        "outputPorts": [],
+        "connections": [
+            {
+                "identifier": "893ad2c9-4a07-3447-b772-6b7149cfd6c1",
+                "instanceIdentifier": "5b9c96a4-7982-3746-2937-45511fb20c96",
+                "name": "",
+                "source": {
+                    "id": "54ab8572-0e10-39a5-b553-931f9c253023",
+                    "type": "PROCESSOR",
+                    "groupId": "1800c04e-f9b9-3293-bfc7-b35f43e0706c",
+                    "name": "GenerateFlowFile",
+                    "comments": "",
+                    "instanceIdentifier": 
"6d6b9cd3-6d31-330a-40f9-185959ad1c78"
+                },
+                "destination": {
+                    "id": "34c1ac1b-1f21-3fd6-a734-726d5b142b7a",
+                    "type": "PROCESSOR",
+                    "groupId": "1800c04e-f9b9-3293-bfc7-b35f43e0706c",
+                    "name": "LookupAttribute",
+                    "comments": "",
+                    "instanceIdentifier": 
"4f8d0670-019c-1000-1ac6-c81ef75a70d0"
+                },
+                "labelIndex": 0,
+                "zIndex": 1,
+                "selectedRelationships": [
+                    "success"
+                ],
+                "backPressureObjectThreshold": 10000,
+                "backPressureDataSizeThreshold": "1 GB",
+                "flowFileExpiration": "0 sec",
+                "prioritizers": [],
+                "bends": [],
+                "loadBalanceStrategy": "DO_NOT_LOAD_BALANCE",
+                "partitioningAttribute": "",
+                "loadBalanceCompression": "DO_NOT_COMPRESS",
+                "componentType": "CONNECTION",
+                "groupIdentifier": "1800c04e-f9b9-3293-bfc7-b35f43e0706c"
+            },
+            {
+                "identifier": "f63459de-cf1f-3773-8f93-405518e085e4",
+                "instanceIdentifier": "4f93c5e2-019c-1000-2bea-06d8d611d5f6",
+                "name": "",
+                "source": {
+                    "id": "34c1ac1b-1f21-3fd6-a734-726d5b142b7a",
+                    "type": "PROCESSOR",
+                    "groupId": "1800c04e-f9b9-3293-bfc7-b35f43e0706c",
+                    "name": "LookupAttribute",
+                    "comments": "",
+                    "instanceIdentifier": 
"4f8d0670-019c-1000-1ac6-c81ef75a70d0"
+                },
+                "destination": {
+                    "id": "4d4160b1-736c-3be4-bc3a-84fc6eb4ad2a",
+                    "type": "PROCESSOR",
+                    "groupId": "1800c04e-f9b9-3293-bfc7-b35f43e0706c",
+                    "name": "UpdateAttribute",
+                    "comments": "",
+                    "instanceIdentifier": 
"499f9781-71c5-367f-aa17-5441bff29de9"
+                },
+                "labelIndex": 0,
+                "zIndex": 2,
+                "selectedRelationships": [
+                    "matched",
+                    "unmatched"
+                ],
+                "backPressureObjectThreshold": 10000,
+                "backPressureDataSizeThreshold": "1 GB",
+                "flowFileExpiration": "0 sec",
+                "prioritizers": [],
+                "bends": [],
+                "loadBalanceStrategy": "DO_NOT_LOAD_BALANCE",
+                "partitioningAttribute": "",
+                "loadBalanceCompression": "DO_NOT_COMPRESS",
+                "componentType": "CONNECTION",
+                "groupIdentifier": "1800c04e-f9b9-3293-bfc7-b35f43e0706c"
+            }
+        ],
+        "labels": [],
+        "funnels": [],
+        "controllerServices": [
+            {
+                "identifier": "b013f870-aee8-3cc4-b022-ac385ded928d",
+                "instanceIdentifier": "4f8d53d4-019c-1000-d376-abfaa091dc37",
+                "name": "SimpleKeyValueLookupService",
+                "comments": "",
+                "type": "org.apache.nifi.lookup.SimpleKeyValueLookupService",
+                "bundle": {
+                    "group": "org.apache.nifi",
+                    "artifact": "nifi-lookup-services-nar",
+                    "version": "2026.1.20.21-SNAPSHOT"
+                },
+                "properties": {
+                    "test.key": "Test Value"
+                },
+                "propertyDescriptors": {
+                    "test.key": {
+                        "name": "test.key",
+                        "displayName": "test.key",
+                        "identifiesControllerService": false,
+                        "sensitive": false,
+                        "dynamic": true
+                    }
+                },
+                "controllerServiceApis": [
+                    {
+                        "type": "org.apache.nifi.lookup.StringLookupService",
+                        "bundle": {
+                            "group": "org.apache.nifi",
+                            "artifact": "nifi-standard-services-api-nar",
+                            "version": "2026.1.20.21-SNAPSHOT"
+                        }
+                    },
+                    {
+                        "type": "org.apache.nifi.lookup.LookupService",
+                        "bundle": {
+                            "group": "org.apache.nifi",
+                            "artifact": "nifi-standard-services-api-nar",
+                            "version": "2026.1.20.21-SNAPSHOT"
+                        }
+                    }
+                ],
+                "scheduledState": "DISABLED",
+                "bulletinLevel": "WARN",
+                "componentType": "CONTROLLER_SERVICE",
+                "groupIdentifier": "1800c04e-f9b9-3293-bfc7-b35f43e0706c"
+            }
+        ],
+        "parameterContextName": "Generate Parameters",
+        "defaultFlowFileExpiration": "0 sec",
+        "defaultBackPressureObjectThreshold": 10000,
+        "defaultBackPressureDataSizeThreshold": "1 GB",
+        "scheduledState": "ENABLED",
+        "executionEngine": "INHERITED",
+        "maxConcurrentTasks": 1,
+        "statelessFlowTimeout": "1 min",
+        "flowFileConcurrency": "UNBOUNDED",
+        "flowFileOutboundPolicy": "STREAM_WHEN_AVAILABLE",
+        "componentType": "PROCESS_GROUP"
+    },
+    "externalControllerServices": {},
+    "parameterContexts": {
+        "Generate Parameters": {
+            "name": "Generate Parameters",
+            "parameters": [
+                {
+                    "name": "Trigger Schedule",
+                    "description": "",
+                    "sensitive": false,
+                    "provided": false,
+                    "value": ""
+                }
+            ],
+            "inheritedParameterContexts": [],
+            "description": "",
+            "componentType": "PARAMETER_CONTEXT"
+        }
+    },
+    "flowEncodingVersion": "1.0",
+    "parameterProviders": {},
+    "latest": false
+}
\ No newline at end of file
diff --git 
a/nifi-extension-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/script/impl/ValidationContextAdapter.java
 
b/nifi-extension-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/script/impl/ValidationContextAdapter.java
index d78d0134782..8951412fc00 100644
--- 
a/nifi-extension-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/script/impl/ValidationContextAdapter.java
+++ 
b/nifi-extension-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/script/impl/ValidationContextAdapter.java
@@ -115,4 +115,9 @@ public abstract class ValidationContextAdapter implements 
ValidationContext {
     public boolean isDependencySatisfied(final PropertyDescriptor 
propertyDescriptor, final Function<String, PropertyDescriptor> 
propertyDescriptorLookup) {
         return 
innerValidationContext.isDependencySatisfied(propertyDescriptor, 
propertyDescriptorLookup);
     }
+
+    @Override
+    public String evaluateParameters(final String value) {
+        return innerValidationContext.evaluateParameters(value);
+    }
 }
diff --git 
a/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/StandardProcessorNode.java
 
b/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/StandardProcessorNode.java
index 69bef45ed71..f739bc11fc6 100644
--- 
a/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/StandardProcessorNode.java
+++ 
b/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/StandardProcessorNode.java
@@ -1140,89 +1140,87 @@ public class StandardProcessorNode extends 
ProcessorNode implements Connectable
     }
 
     @Override
-    public List<ValidationResult> validateConfig() {
+    public List<ValidationResult> validateConfig(final ValidationContext 
validationContext) {
 
         final List<ValidationResult> results = new ArrayList<>();
-        final ParameterContext parameterContext = getParameterContext();
-
-        if (parameterContext == null && !this.parameterReferences.isEmpty()) {
-            results.add(new ValidationResult.Builder()
-                    .subject(RUN_SCHEDULE)
-                    .input("Parameter Context")
-                    .valid(false)
-                    .explanation("Processor configuration references one or 
more Parameters but no Parameter Context is currently set on the Process 
Group.")
-                    .build());
-        } else {
-            for (final ParameterReference paramRef : parameterReferences) {
-                final Optional<Parameter> parameterRef = 
parameterContext.getParameter(paramRef.getParameterName());
-                if (!parameterRef.isPresent()) {
-                    results.add(new ValidationResult.Builder()
-                            .subject(RUN_SCHEDULE)
-                            .input(paramRef.getParameterName())
-                            .valid(false)
-                            .explanation("Processor configuration references 
Parameter '" + paramRef.getParameterName() +
-                                    "' but the currently selected Parameter 
Context does not have a Parameter with that name")
-                            .build());
-                } else {
-                    final ParameterDescriptor parameterDescriptor = 
parameterRef.get().getDescriptor();
-                    if (parameterDescriptor.isSensitive()) {
-                        results.add(new ValidationResult.Builder()
-                                .subject(RUN_SCHEDULE)
-                                .input(parameterDescriptor.getName())
-                                .valid(false)
-                                .explanation("Processor configuration cannot 
reference sensitive parameters")
-                                .build());
-                    }
-                }
-            }
 
-            final String schedulingPeriod = getSchedulingPeriod();
-            final String evaluatedSchedulingPeriod = 
evaluateParameters(schedulingPeriod);
+        for (final ParameterReference paramRef : parameterReferences) {
+            final String paramName = paramRef.getParameterName();
 
-            if (evaluatedSchedulingPeriod != null) {
-                switch (schedulingStrategy) {
-                    case CRON_DRIVEN: {
-                        try {
-                            CronExpression.parse(evaluatedSchedulingPeriod);
-                        } catch (final Exception e) {
+            if (!validationContext.isParameterDefined(paramName)) {
+                results.add(new ValidationResult.Builder()
+                        .subject(RUN_SCHEDULE)
+                        .input(paramName)
+                        .valid(false)
+                        .explanation("Processor configuration references 
Parameter '" + paramName +
+                                "' but the currently selected Parameter 
Context does not have a Parameter with that name")
+                        .build());
+            } else {
+                final ParameterContext parameterContext = 
getParameterContext();
+                if (parameterContext != null) {
+                    final Optional<Parameter> parameterFromContext = 
parameterContext.getParameter(paramName);
+                    if (parameterFromContext.isPresent()) {
+                        final ParameterDescriptor parameterDescriptor = 
parameterFromContext.get().getDescriptor();
+                        if (parameterDescriptor.isSensitive()) {
                             results.add(new ValidationResult.Builder()
                                     .subject(RUN_SCHEDULE)
-                                    .input(schedulingPeriod)
+                                    .input(parameterDescriptor.getName())
                                     .valid(false)
-                                    .explanation("Scheduling Period is not a 
valid cron expression")
+                                    .explanation("Processor configuration 
cannot reference sensitive parameters")
                                     .build());
                         }
                     }
-                    break;
-                    case TIMER_DRIVEN: {
-                        try {
-                            final long schedulingNanos = 
FormatUtils.getTimeDuration(Objects.requireNonNull(evaluatedSchedulingPeriod),
-                                    TimeUnit.NANOSECONDS);
-
-                            if (schedulingNanos < 0) {
-                                results.add(new ValidationResult.Builder()
-                                        .subject(RUN_SCHEDULE)
-                                        .input(schedulingPeriod)
-                                        .valid(false)
-                                        .explanation("Scheduling Period must 
be positive")
-                                        .build());
-                            }
+                }
+            }
+        }
 
-                            
this.schedulingNanos.set(Math.max(MINIMUM_SCHEDULING_NANOS, schedulingNanos));
+        final String schedulingPeriod = getSchedulingPeriod();
+        final String evaluatedSchedulingPeriod = 
validationContext.evaluateParameters(schedulingPeriod);
 
-                        } catch (final Exception e) {
+        if (evaluatedSchedulingPeriod != null) {
+            switch (schedulingStrategy) {
+                case CRON_DRIVEN: {
+                    try {
+                        CronExpression.parse(evaluatedSchedulingPeriod);
+                    } catch (final Exception e) {
+                        results.add(new ValidationResult.Builder()
+                                .subject(RUN_SCHEDULE)
+                                .input(schedulingPeriod)
+                                .valid(false)
+                                .explanation("Scheduling Period is not a valid 
cron expression")
+                                .build());
+                    }
+                }
+                break;
+                case TIMER_DRIVEN: {
+                    try {
+                        final long schedulingNanos = 
FormatUtils.getTimeDuration(Objects.requireNonNull(evaluatedSchedulingPeriod),
+                                TimeUnit.NANOSECONDS);
+
+                        if (schedulingNanos < 0) {
                             results.add(new ValidationResult.Builder()
                                     .subject(RUN_SCHEDULE)
                                     .input(schedulingPeriod)
                                     .valid(false)
-                                    .explanation("Scheduling Period is not a 
valid time duration")
+                                    .explanation("Scheduling Period must be 
positive")
                                     .build());
                         }
+
+                        
this.schedulingNanos.set(Math.max(MINIMUM_SCHEDULING_NANOS, schedulingNanos));
+
+                    } catch (final Exception e) {
+                        results.add(new ValidationResult.Builder()
+                                .subject(RUN_SCHEDULE)
+                                .input(schedulingPeriod)
+                                .valid(false)
+                                .explanation("Scheduling Period is not a valid 
time duration")
+                                .build());
                     }
-                    break;
                 }
+                break;
             }
         }
+
         return results;
     }
 
diff --git 
a/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/parameter/StandardParameterProviderNode.java
 
b/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/parameter/StandardParameterProviderNode.java
index 6b70934396f..256fa991a53 100644
--- 
a/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/parameter/StandardParameterProviderNode.java
+++ 
b/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/parameter/StandardParameterProviderNode.java
@@ -266,7 +266,7 @@ public class StandardParameterProviderNode extends 
AbstractComponentNode impleme
     }
 
     @Override
-    protected List<ValidationResult> validateConfig() {
+    protected List<ValidationResult> validateConfig(final ValidationContext 
validationContext) {
         return Collections.emptyList();
     }
 
diff --git 
a/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/service/StandardControllerServiceNode.java
 
b/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/service/StandardControllerServiceNode.java
index 1c06833451e..47ac9dedd6a 100644
--- 
a/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/service/StandardControllerServiceNode.java
+++ 
b/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/service/StandardControllerServiceNode.java
@@ -619,7 +619,7 @@ public class StandardControllerServiceNode extends 
AbstractComponentNode impleme
     }
 
     @Override
-    protected List<ValidationResult> validateConfig() {
+    protected List<ValidationResult> validateConfig(final ValidationContext 
validationContext) {
         return Collections.emptyList();
     }
 
diff --git 
a/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/processor/StandardValidationContext.java
 
b/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/processor/StandardValidationContext.java
index f82b8eb24ba..9ee15d3eff1 100644
--- 
a/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/processor/StandardValidationContext.java
+++ 
b/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/processor/StandardValidationContext.java
@@ -36,9 +36,12 @@ import 
org.apache.nifi.controller.service.ControllerServiceProvider;
 import org.apache.nifi.controller.service.ControllerServiceState;
 import org.apache.nifi.expression.ExpressionLanguageCompiler;
 import org.apache.nifi.groups.ProcessGroup;
+import org.apache.nifi.parameter.ExpressionLanguageAgnosticParameterParser;
 import org.apache.nifi.parameter.Parameter;
 import org.apache.nifi.parameter.ParameterLookup;
+import org.apache.nifi.parameter.ParameterParser;
 import org.apache.nifi.parameter.ParameterReference;
+import org.apache.nifi.parameter.ParameterTokenList;
 
 import java.util.Collection;
 import java.util.Collections;
@@ -242,6 +245,13 @@ public class StandardValidationContext implements 
ValidationContext {
         return validateConnections;
     }
 
+    @Override
+    public String evaluateParameters(final String value) {
+        final ParameterParser parameterParser = new 
ExpressionLanguageAgnosticParameterParser();
+        final ParameterTokenList parameterTokenList = 
parameterParser.parseTokens(value);
+        return parameterTokenList.substitute(parameterLookup);
+    }
+
     @Override
     public String toString() {
         return "StandardValidationContext[componentId=" + componentId + ", 
properties=" + properties + "]";
diff --git 
a/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/registry/flow/StandardFlowRegistryClientNode.java
 
b/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/registry/flow/StandardFlowRegistryClientNode.java
index 9eb895fcec1..e8e936df270 100644
--- 
a/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/registry/flow/StandardFlowRegistryClientNode.java
+++ 
b/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/registry/flow/StandardFlowRegistryClientNode.java
@@ -28,6 +28,7 @@ import org.apache.nifi.components.ConfigVerificationResult;
 import org.apache.nifi.components.ConfigVerificationResult.Outcome;
 import org.apache.nifi.components.ConfigurableComponent;
 import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.components.ValidationContext;
 import org.apache.nifi.components.ValidationResult;
 import org.apache.nifi.components.validation.ValidationStatus;
 import org.apache.nifi.components.validation.ValidationTrigger;
@@ -118,7 +119,7 @@ public final class StandardFlowRegistryClientNode extends 
AbstractComponentNode
     }
 
     @Override
-    protected List<ValidationResult> validateConfig() {
+    protected List<ValidationResult> validateConfig(final ValidationContext 
validationContext) {
         return Collections.emptyList();
     }
 
diff --git 
a/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/AbstractComponentNode.java
 
b/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/AbstractComponentNode.java
index 612547ab019..88a41522600 100644
--- 
a/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/AbstractComponentNode.java
+++ 
b/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/AbstractComponentNode.java
@@ -932,7 +932,7 @@ public abstract class AbstractComponentNode implements 
ComponentNode {
             }
 
             final List<ValidationResult> invalidParameterResults = 
validateParameterReferences(validationContext);
-            invalidParameterResults.addAll(validateConfig());
+            invalidParameterResults.addAll(validateConfig(validationContext));
 
             if (!invalidParameterResults.isEmpty()) {
                 // At this point, we are not able to properly resolve all 
property values, so we will not attempt to perform
@@ -993,11 +993,12 @@ public abstract class AbstractComponentNode implements 
ComponentNode {
      * Validates the current configuration, returning ValidationResults for any
      * invalid configuration parameter.
      *
+     * @param validationContext the ValidationContext to use for parameter 
lookup
      * @return Collection of validation result objects for any invalid findings
      *         only. If the collection is empty then the component is valid. 
Should guarantee
      *         non-null
      */
-    protected abstract List<ValidationResult> validateConfig();
+    protected abstract List<ValidationResult> validateConfig(ValidationContext 
validationContext);
 
     private List<ValidationResult> validateParameterReferences(final 
ValidationContext validationContext) {
         final List<ValidationResult> results = new ArrayList<>();
diff --git 
a/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/test/java/org/apache/nifi/controller/TestAbstractComponentNode.java
 
b/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/test/java/org/apache/nifi/controller/TestAbstractComponentNode.java
index ed27ec59375..08be7562705 100644
--- 
a/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/test/java/org/apache/nifi/controller/TestAbstractComponentNode.java
+++ 
b/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/test/java/org/apache/nifi/controller/TestAbstractComponentNode.java
@@ -536,7 +536,7 @@ public class TestAbstractComponentNode {
         }
 
         @Override
-        protected List<ValidationResult> validateConfig() {
+        protected List<ValidationResult> validateConfig(final 
ValidationContext validationContext) {
             return Collections.emptyList();
         }
 
diff --git 
a/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/components/connector/ConnectorValidationContextBridge.java
 
b/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/components/connector/ConnectorValidationContextBridge.java
index 27992b2f4f8..6f867925be7 100644
--- 
a/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/components/connector/ConnectorValidationContextBridge.java
+++ 
b/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/components/connector/ConnectorValidationContextBridge.java
@@ -25,8 +25,11 @@ import org.apache.nifi.controller.ControllerService;
 import org.apache.nifi.controller.ControllerServiceLookup;
 import org.apache.nifi.documentation.init.EmptyControllerServiceLookup;
 import org.apache.nifi.expression.ExpressionLanguageCompiler;
+import org.apache.nifi.parameter.ExpressionLanguageAgnosticParameterParser;
 import org.apache.nifi.parameter.Parameter;
 import org.apache.nifi.parameter.ParameterLookup;
+import org.apache.nifi.parameter.ParameterParser;
+import org.apache.nifi.parameter.ParameterTokenList;
 
 import java.util.Collection;
 import java.util.Collections;
@@ -133,4 +136,11 @@ public class ConnectorValidationContextBridge implements 
ValidationContext {
     public Map<String, String> getAllProperties() {
         return Collections.unmodifiableMap(rawValues);
     }
+
+    @Override
+    public String evaluateParameters(final String value) {
+        final ParameterParser parameterParser = new 
ExpressionLanguageAgnosticParameterParser();
+        final ParameterTokenList parameterTokenList = 
parameterParser.parseTokens(value);
+        return parameterTokenList.substitute(parameterLookup);
+    }
 }
diff --git 
a/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/flowanalysis/StandardFlowAnalysisRuleNode.java
 
b/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/flowanalysis/StandardFlowAnalysisRuleNode.java
index 110ba3fa061..7c2d9a4d213 100644
--- 
a/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/flowanalysis/StandardFlowAnalysisRuleNode.java
+++ 
b/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/flowanalysis/StandardFlowAnalysisRuleNode.java
@@ -22,6 +22,7 @@ import org.apache.nifi.authorization.Resource;
 import org.apache.nifi.authorization.resource.Authorizable;
 import org.apache.nifi.authorization.resource.ResourceFactory;
 import org.apache.nifi.authorization.resource.ResourceType;
+import org.apache.nifi.components.ValidationContext;
 import org.apache.nifi.components.ValidationResult;
 import org.apache.nifi.components.validation.ValidationTrigger;
 import org.apache.nifi.controller.FlowAnalysisRuleNode;
@@ -98,7 +99,7 @@ public class StandardFlowAnalysisRuleNode extends 
AbstractFlowAnalysisRuleNode i
     }
 
     @Override
-    protected List<ValidationResult> validateConfig() {
+    protected List<ValidationResult> validateConfig(final ValidationContext 
validationContext) {
         return Collections.emptyList();
     }
 
diff --git 
a/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/reporting/StandardReportingTaskNode.java
 
b/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/reporting/StandardReportingTaskNode.java
index dfaf6347309..055a1d246eb 100644
--- 
a/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/reporting/StandardReportingTaskNode.java
+++ 
b/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/reporting/StandardReportingTaskNode.java
@@ -22,6 +22,7 @@ import org.apache.nifi.authorization.Resource;
 import org.apache.nifi.authorization.resource.Authorizable;
 import org.apache.nifi.authorization.resource.ResourceFactory;
 import org.apache.nifi.authorization.resource.ResourceType;
+import org.apache.nifi.components.ValidationContext;
 import org.apache.nifi.components.ValidationResult;
 import org.apache.nifi.components.validation.ValidationTrigger;
 import org.apache.nifi.controller.FlowController;
@@ -91,7 +92,7 @@ public class StandardReportingTaskNode extends 
AbstractReportingTaskNode impleme
     }
 
     @Override
-    protected List<ValidationResult> validateConfig() {
+    protected List<ValidationResult> validateConfig(final ValidationContext 
validationContext) {
         return Collections.emptyList();
     }
 
diff --git 
a/nifi-mock/src/main/java/org/apache/nifi/util/MockValidationContext.java 
b/nifi-mock/src/main/java/org/apache/nifi/util/MockValidationContext.java
index 91541c9b500..df6b8a61d48 100644
--- a/nifi-mock/src/main/java/org/apache/nifi/util/MockValidationContext.java
+++ b/nifi-mock/src/main/java/org/apache/nifi/util/MockValidationContext.java
@@ -31,6 +31,7 @@ import 
org.apache.nifi.parameter.ExpressionLanguageAwareParameterParser;
 import org.apache.nifi.parameter.ParameterLookup;
 import org.apache.nifi.parameter.ParameterParser;
 import org.apache.nifi.parameter.ParameterReference;
+import org.apache.nifi.parameter.ParameterTokenList;
 
 import java.util.Collection;
 import java.util.Collections;
@@ -220,6 +221,13 @@ public class MockValidationContext extends 
MockControllerServiceLookup implement
         return contextParameters.containsKey(parameterName) && 
contextParameters.get(parameterName) != null;
     }
 
+    @Override
+    public String evaluateParameters(final String value) {
+        final ParameterParser parameterParser = new 
ExpressionLanguageAgnosticParameterParser();
+        final ParameterTokenList parameterTokenList = 
parameterParser.parseTokens(value);
+        return parameterTokenList.substitute(parameterLookup);
+    }
+
     private String getEffectiveValue(final PropertyDescriptor descriptor) {
         final String configuredValue = context.getProperties().get(descriptor);
         return getEffectiveValue(descriptor, configuredValue);
diff --git 
a/nifi-stateless/nifi-stateless-bundle/nifi-stateless-engine/src/main/java/org/apache/nifi/controller/reporting/StatelessReportingTaskNode.java
 
b/nifi-stateless/nifi-stateless-bundle/nifi-stateless-engine/src/main/java/org/apache/nifi/controller/reporting/StatelessReportingTaskNode.java
index 2528c76d606..e72d6972778 100644
--- 
a/nifi-stateless/nifi-stateless-bundle/nifi-stateless-engine/src/main/java/org/apache/nifi/controller/reporting/StatelessReportingTaskNode.java
+++ 
b/nifi-stateless/nifi-stateless-bundle/nifi-stateless-engine/src/main/java/org/apache/nifi/controller/reporting/StatelessReportingTaskNode.java
@@ -19,6 +19,7 @@ package org.apache.nifi.controller.reporting;
 
 import org.apache.nifi.authorization.Resource;
 import org.apache.nifi.authorization.resource.Authorizable;
+import org.apache.nifi.components.ValidationContext;
 import org.apache.nifi.components.ValidationResult;
 import org.apache.nifi.components.validation.ValidationTrigger;
 import org.apache.nifi.controller.LoggableComponent;
@@ -50,7 +51,7 @@ public class StatelessReportingTaskNode extends 
AbstractReportingTaskNode implem
     }
 
     @Override
-    protected List<ValidationResult> validateConfig() {
+    protected List<ValidationResult> validateConfig(final ValidationContext 
validationContext) {
         return Collections.emptyList();
     }
 

Reply via email to