This is an automated email from the ASF dual-hosted git repository.
markap14 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 e2c09c2e2f NIFI-15611: Fetchable Values should pull from current
FlowContext (#10906)
e2c09c2e2f is described below
commit e2c09c2e2f1e4d6738fbf69501448dc390dc66f6
Author: Bob Paulin <[email protected]>
AuthorDate: Tue Feb 17 14:24:01 2026 -0600
NIFI-15611: Fetchable Values should pull from current FlowContext (#10906)
---
.../mock/connectors/tests/AllowableValuesIT.java | 87 +++++++++++++++++
.../mock/connectors/AllowableValuesConnector.java | 106 +++++++++++++++++++++
.../org.apache.nifi.components.connector.Connector | 1 +
.../connector/StandardConnectorNode.java | 2 +-
4 files changed, 195 insertions(+), 1 deletion(-)
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/AllowableValuesIT.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/AllowableValuesIT.java
new file mode 100644
index 0000000000..a350730b72
--- /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/AllowableValuesIT.java
@@ -0,0 +1,87 @@
+/*
+ * 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.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Integration tests that verify fetchable allowable values are properly
validated
+ * during configuration verification. These tests exercise the fix for
NIFI-15258,
+ * where {@code StandardConnectorNode.fetchAllowableValues} incorrectly used
the
+ * active flow context instead of the working flow context passed as a
parameter.
+ *
+ * <p>The {@code AllowableValuesConnector} returns allowable values only when
the
+ * flow context type is WORKING. If the framework incorrectly passes the ACTIVE
+ * context, the connector returns an empty list, causing all values to be
accepted.</p>
+ */
+public class AllowableValuesIT {
+
+ private static final String CONNECTOR_CLASS =
"org.apache.nifi.mock.connectors.AllowableValuesConnector";
+
+ @Test
+ public void testVerifyConfigurationRejectsInvalidAllowableValue() throws
IOException {
+ try (final ConnectorTestRunner runner = createRunner()) {
+ final ConnectorConfigVerificationResult result =
runner.verifyConfiguration("Selection", Map.of("Color", "purple"));
+
+ final List<ConfigVerificationResult> failedResults =
result.getFailedResults();
+ assertFalse(failedResults.isEmpty(), "Expected at least one failed
result for invalid allowable value 'purple'");
+ assertEquals(1, failedResults.size());
+
+ final String explanation =
failedResults.getFirst().getExplanation();
+ assertTrue(explanation.contains("allowable values"), "Expected
explanation to mention allowable values but was: " + explanation);
+ }
+ }
+
+ @Test
+ public void testVerifyConfigurationAcceptsValidAllowableValue() throws
IOException {
+ try (final ConnectorTestRunner runner = createRunner()) {
+ final ConnectorConfigVerificationResult result =
runner.verifyConfiguration("Selection", Map.of("Color", "red"));
+ result.assertNoFailures();
+ }
+ }
+
+ @Test
+ public void testVerifyConfigurationAcceptsAllValidAllowableValues() throws
IOException {
+ try (final ConnectorTestRunner runner = createRunner()) {
+ for (final String validColor : List.of("red", "green", "blue")) {
+ final ConnectorConfigVerificationResult result =
runner.verifyConfiguration("Selection", Map.of("Color", validColor));
+ result.assertNoFailures();
+ }
+ }
+ }
+
+ 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/AllowableValuesConnector.java
b/nifi-connector-mock-bundle/nifi-connector-mock-test-bundle/nifi-connector-mock-test-connectors/src/main/java/org/apache/nifi/mock/connectors/AllowableValuesConnector.java
new file mode 100644
index 0000000000..a263482eda
--- /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/AllowableValuesConnector.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.AllowableValue;
+import org.apache.nifi.components.ConfigVerificationResult;
+import org.apache.nifi.components.DescribedValue;
+import org.apache.nifi.components.connector.AbstractConnector;
+import org.apache.nifi.components.connector.ConfigurationStep;
+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.FlowContextType;
+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 with a configuration step that has fetchable allowable
values.
+ * The {@link #fetchAllowableValues} method returns allowable values only when
invoked
+ * with a WORKING {@link FlowContextType}. If invoked with an ACTIVE context,
it returns
+ * an empty list. This design verifies that the framework passes the correct
(working)
+ * context during configuration verification, reproducing the scenario fixed
in NIFI-15258.
+ */
+public class AllowableValuesConnector extends AbstractConnector {
+
+ static final ConnectorPropertyDescriptor COLOR = new
ConnectorPropertyDescriptor.Builder()
+ .name("Color")
+ .description("The color to select")
+ .allowableValuesFetchable(true)
+ .required(true)
+ .build();
+
+ static final ConnectorPropertyGroup SELECTION_GROUP = new
ConnectorPropertyGroup.Builder()
+ .name("Color Selection")
+ .addProperty(COLOR)
+ .build();
+
+ static final ConfigurationStep SELECTION_STEP = new
ConfigurationStep.Builder()
+ .name("Selection")
+ .propertyGroups(List.of(SELECTION_GROUP))
+ .build();
+
+ private static final List<ConfigurationStep> CONFIGURATION_STEPS =
List.of(SELECTION_STEP);
+
+ @Override
+ public VersionedExternalFlow getInitialFlow() {
+ return
VersionedFlowUtils.loadFlowFromResource("flows/Generate_and_Update.json");
+ }
+
+ @Override
+ public List<ConfigurationStep> getConfigurationSteps() {
+ return CONFIGURATION_STEPS;
+ }
+
+ @Override
+ protected void onStepConfigured(final String stepName, final FlowContext
flowContext) {
+ }
+
+ @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
workingContext) {
+ return List.of();
+ }
+
+ @Override
+ public List<DescribedValue> fetchAllowableValues(final String stepName,
final String propertyName, final FlowContext flowContext) {
+ if ("Selection".equals(stepName) && "Color".equals(propertyName)) {
+ if (flowContext.getType() == FlowContextType.WORKING) {
+ return List.of(
+ new AllowableValue("red", "Red"),
+ new AllowableValue("green", "Green"),
+ new AllowableValue("blue", "Blue")
+ );
+ }
+
+ // Return empty when the context is ACTIVE, simulating the pre-fix
behavior
+ // where using the wrong context caused allowable values to be
empty and
+ // any value to be incorrectly accepted.
+ return List.of();
+ }
+
+ return super.fetchAllowableValues(stepName, propertyName, flowContext);
+ }
+}
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 341890a36f..b05e5b86f9 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
@@ -13,5 +13,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+org.apache.nifi.mock.connectors.AllowableValuesConnector
org.apache.nifi.mock.connectors.GenerateAndLog
org.apache.nifi.mock.connectors.MissingBundleConnector
\ No newline at end of file
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 038ce10c36..438ea78c64 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
@@ -1546,7 +1546,7 @@ public class StandardConnectorNode implements
ConnectorNode {
private List<DescribedValue> fetchAllowableValues(final String stepName,
final String propertyName, final FlowContext context) {
final List<DescribedValue> allowableValues;
try (NarCloseable ignored =
NarCloseable.withComponentNarLoader(extensionManager,
getConnector().getClass(), getIdentifier())) {
- allowableValues = getConnector().fetchAllowableValues(stepName,
propertyName, activeFlowContext);
+ allowableValues = getConnector().fetchAllowableValues(stepName,
propertyName, context);
}
if (allowableValues == null || allowableValues.isEmpty()) {