Skip to content

Conversation

@pvillard31
Copy link
Contributor

@pvillard31 pvillard31 commented Feb 3, 2026

Summary

NIFI-15541 - Flow version upgrade binds new process groups to incorrect parameter context

When upgrading a versioned flow that introduces a new child process group, the new process group is incorrectly bound to a parameter context matched by name rather than using the same parameter context as its parent.

Steps to reproduce:

  1. Create a versioned flow v1 with Process Group A attached to Parameter Context P
  2. Create v2 by adding a child Process Group B inside A, also attached to P
  3. Import v1 twice using "do not keep existing parameter context" - this creates A1 with P, and A2 with P (1)
  4. Upgrade A2 from v1 to v2

Current behavior:
The newly added Process Group B in A2 gets bound to P instead of P (1)

Expected behavior:
Process Group B should use P (1), the same parameter context as its parent A2

Root cause:
In StandardVersionedComponentSynchronizer.updateParameterContext(), when a new child process group is added during synchronization, it looks up parameter contexts by name globally rather than inheriting from the parent group.

Tracking

Please complete the following tracking steps prior to pull request creation.

Issue Tracking

Pull Request Tracking

  • Pull Request title starts with Apache NiFi Jira issue number, such as NIFI-00000
  • Pull Request commit message starts with Apache NiFi Jira issue number, as such NIFI-00000
  • Pull request contains commits signed with a registered key indicating Verified status

Pull Request Formatting

  • Pull Request based on current revision of the main branch
  • Pull Request refers to a feature branch with one commit containing changes

Verification

Please indicate the verification steps performed prior to pull request creation.

Build

  • Build completed using ./mvnw clean install -P contrib-check
    • JDK 21
    • JDK 25

Licensing

  • New dependencies are compatible with the Apache License 2.0 according to the License Policy
  • New dependencies are documented in applicable LICENSE and NOTICE files

Documentation

  • Documentation formatting appears as expected in rendered files

Copy link
Contributor

@exceptionfactory exceptionfactory left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for addressing this issue @pvillard31. The basic approach looks good, though it does depend on the Parameter Context naming convention, it seems like a reasonable best effort match. I noted a few recommendations.

* @return true if contextName is versionedName with a suffix like " (n)"
*/
private boolean isParameterContextNameWithSuffix(final String contextName, final String versionedName) {
if (!contextName.startsWith(versionedName + " (")) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like the logic in this method could be replaced with a regular expression pattern.

Comment on lines 2163 to 2167
if (parentParameterContext != null) {
selectedParameterContext = parentParameterContext;
// Ensure the parent's context has all the parameters from the versioned context
addMissingConfiguration(versionedParameterContext, selectedParameterContext, versionedParameterContexts, parameterProviderReferences, componentIdGenerator);
} else {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I recommend adjusting the logic so that the first block is if (parentParameterContext == null) { ... } else {

// Save as v1
final VersionControlInformationEntity vciV1 = util.startVersionControl(groupA, clientEntity, TEST_FLOWS_BUCKET, "FlowWithParameterContext");
final String flowId = vciV1.getVersionControlInformation().getFlowId();
logger.info("Saved v1: Process Group A with Processor X");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I recommend removing the log statements from the test method, the integration test logs for nifi-app.log generally capture changes, and otherwise these additional logs are not a common approach in the system tests.

final ParameterContextEntity paramContextP = util.createParameterContext(paramContextName, params);

// Step 2: Create v1 - Process Group A with just a Processor X using param1
final ProcessGroupEntity groupA = util.createProcessGroup("A", "root");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are a number of string names and relationship values that could be changed to static final member variables and reused for consistency in the test method.

Comment on lines 72 to 73
final Map<String, String> params = new HashMap<>();
params.put("param1", "value1");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be simplified with Map.of()

Comment on lines 61 to 66
public class ParameterContextPreservationIT extends NiFiSystemIT {
private static final Logger logger = LoggerFactory.getLogger(ParameterContextPreservationIT.class);
public static final String TEST_FLOWS_BUCKET = "test-flows";

@Test
public void testNewProcessGroupUsesCorrectParameterContextDuringUpgrade() throws NiFiClientException, IOException, InterruptedException {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public class ParameterContextPreservationIT extends NiFiSystemIT {
private static final Logger logger = LoggerFactory.getLogger(ParameterContextPreservationIT.class);
public static final String TEST_FLOWS_BUCKET = "test-flows";
@Test
public void testNewProcessGroupUsesCorrectParameterContextDuringUpgrade() throws NiFiClientException, IOException, InterruptedException {
class ParameterContextPreservationIT extends NiFiSystemIT {
private static final Logger logger = LoggerFactory.getLogger(ParameterContextPreservationIT.class);
public static final String TEST_FLOWS_BUCKET = "test-flows";
@Test
void testNewProcessGroupUsesCorrectParameterContextDuringUpgrade() throws NiFiClientException, IOException, InterruptedException {

@pvillard31
Copy link
Contributor Author

Thanks for the review @exceptionfactory - I pushed a commit to address your comments and also consolidate the code where this logic of parameter context naming (when using keepExisting=false) is defined.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants