This is an automated email from the ASF dual-hosted git repository.
markap14 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git
The following commit(s) were added to refs/heads/main by this push:
new 047ad87a3b6 NIFI-15329 - Fix RenameRecordField to properly handle
multiple records (#10629)
047ad87a3b6 is described below
commit 047ad87a3b6f4a58db6ec51a49159618d95505a9
Author: Pierre Villard <[email protected]>
AuthorDate: Thu Dec 11 15:35:06 2025 +0100
NIFI-15329 - Fix RenameRecordField to properly handle multiple records
(#10629)
---
.gitignore | 1 +
.../nifi/serialization/record/MapRecord.java | 39 ++++++++++++++++++++++
.../processors/standard/RenameRecordField.java | 5 +++
.../input/complex-person.json | 13 +++++++-
.../TestRenameRecordField/input/simple-person.json | 6 +++-
.../output/testNestedPath.json | 11 ++++++
.../testRecursivelyReferencingAllFields.json | 11 ++++++
.../testRecursivelyReferencingFieldName.json | 11 ++++++
.../output/testReferencingFieldName.json | 4 +++
.../output/testRenameArray.json | 11 ++++++
.../output/testRenameFieldStaticValue.json | 4 +++
.../output/testRenameFieldUsingAttribute.json | 4 +++
.../output/testRenameMultipleFields.json | 4 +++
13 files changed, 122 insertions(+), 2 deletions(-)
diff --git a/.gitignore b/.gitignore
index bc18e8dbb49..ff8a118e9a5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
target
+bin
.project
.settings
.classpath
diff --git
a/nifi-commons/nifi-record/src/main/java/org/apache/nifi/serialization/record/MapRecord.java
b/nifi-commons/nifi-record/src/main/java/org/apache/nifi/serialization/record/MapRecord.java
index 37d787cf56e..794854f7cf7 100644
---
a/nifi-commons/nifi-record/src/main/java/org/apache/nifi/serialization/record/MapRecord.java
+++
b/nifi-commons/nifi-record/src/main/java/org/apache/nifi/serialization/record/MapRecord.java
@@ -50,6 +50,7 @@ public class MapRecord implements Record {
private static final Logger logger =
LoggerFactory.getLogger(MapRecord.class);
private RecordSchema schema;
+ private boolean mutableSchema = false; // Track if schema is a private
copy that can be safely modified
private final Map<String, Object> values;
private Optional<SerializedForm> serializedForm;
private final boolean checkTypes;
@@ -525,6 +526,15 @@ public class MapRecord implements Record {
throw new IllegalArgumentException("Could not rename [" + field +
"] to [" + newName + "] because a field already exists with the name [" +
newName + "]");
}
+ // Create a defensive copy of the schema to avoid modifying a shared
schema instance.
+ // Multiple records often share the same schema object for efficiency.
If we modify
+ // the shared schema, subsequent records would fail to find the
original field name.
+ // Only copy if we haven't already made a private copy.
+ if (!mutableSchema) {
+ this.schema = new SimpleRecordSchema(new
ArrayList<>(schema.getFields()));
+ this.mutableSchema = true;
+ }
+
final String currentName = resolvedField.get().getFieldName();
final boolean renamed = schema.renameField(currentName, newName);
if (!renamed) {
@@ -545,7 +555,36 @@ public class MapRecord implements Record {
if (schemaField.getDataType().getFieldType() ==
RecordFieldType.CHOICE) {
schemaFields.add(schemaField);
} else if (fieldValue instanceof final Record childRecord) {
+ childRecord.regenerateSchema();
schemaFields.add(new RecordField(schemaField.getFieldName(),
RecordFieldType.RECORD.getRecordDataType(childRecord.getSchema()),
schemaField.isNullable()));
+ } else if (schemaField.getDataType().getFieldType() ==
RecordFieldType.ARRAY && fieldValue instanceof Object[]) {
+ // Handle arrays of records - regenerate schema based on
actual element schemas
+ final ArrayDataType arrayType = (ArrayDataType)
schemaField.getDataType();
+ final DataType elementType = arrayType.getElementType();
+ if (elementType.getFieldType() == RecordFieldType.RECORD) {
+ final Object[] array = (Object[]) fieldValue;
+ RecordSchema mergedElementSchema = null;
+ for (final Object element : array) {
+ if (element instanceof Record) {
+ final Record elementRecord = (Record) element;
+ elementRecord.regenerateSchema();
+ if (mergedElementSchema == null) {
+ mergedElementSchema =
elementRecord.getSchema();
+ } else {
+ mergedElementSchema =
DataTypeUtils.merge(mergedElementSchema, elementRecord.getSchema());
+ }
+ }
+ }
+ if (mergedElementSchema != null) {
+ final DataType newElementType =
RecordFieldType.RECORD.getRecordDataType(mergedElementSchema);
+ final DataType newArrayType =
RecordFieldType.ARRAY.getArrayDataType(newElementType);
+ schemaFields.add(new
RecordField(schemaField.getFieldName(), newArrayType,
schemaField.isNullable()));
+ } else {
+ schemaFields.add(schemaField);
+ }
+ } else {
+ schemaFields.add(schemaField);
+ }
} else {
schemaFields.add(schemaField);
}
diff --git
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/RenameRecordField.java
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/RenameRecordField.java
index 91d2c6a1686..baae7928ee1 100644
---
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/RenameRecordField.java
+++
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/RenameRecordField.java
@@ -206,6 +206,11 @@ public class RenameRecordField extends
AbstractRecordProcessor {
}
}
+ // After renaming fields (especially in nested records), we need to
update the
+ // top-level record's schema to reflect the schema changes in nested
records.
+ // This ensures the writer uses the correct schema with renamed fields.
+ record.regenerateSchema();
+
return record;
}
}
diff --git
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/input/complex-person.json
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/input/complex-person.json
index 5de7972913b..77b15c641ba 100644
---
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/input/complex-person.json
+++
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/input/complex-person.json
@@ -9,4 +9,15 @@
"state" : "MS",
"zip" : "90210"
} ]
-} ]
\ No newline at end of file
+}, {
+ "name" : "Jane Smith",
+ "age" : 25,
+ "application" : "Apache Kafka",
+ "addresses" : [ {
+ "name" : "Work",
+ "street" : "1234 Office Blvd",
+ "city" : "Tech Town",
+ "state" : "CA",
+ "zip" : "94105"
+ } ]
+} ]
diff --git
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/input/simple-person.json
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/input/simple-person.json
index 9254388546c..42ac9f743a4 100644
---
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/input/simple-person.json
+++
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/input/simple-person.json
@@ -2,4 +2,8 @@
"name" : "John Doe",
"age" : 30,
"application" : "Apache NiFi"
-} ]
\ No newline at end of file
+}, {
+ "name" : "Jane Smith",
+ "age" : 25,
+ "application" : "Apache Kafka"
+} ]
diff --git
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testNestedPath.json
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testNestedPath.json
index c1ef08b79d8..72153539355 100644
---
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testNestedPath.json
+++
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testNestedPath.json
@@ -9,4 +9,15 @@
"state" : "MS",
"zip" : "90210"
} ]
+}, {
+ "name" : "Jane Smith",
+ "age" : 25,
+ "application" : "Apache Kafka",
+ "addresses" : [ {
+ "name" : "Work",
+ "streetAddress" : "1234 Office Blvd",
+ "city" : "Tech Town",
+ "state" : "CA",
+ "zip" : "94105"
+ } ]
} ]
\ No newline at end of file
diff --git
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRecursivelyReferencingAllFields.json
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRecursivelyReferencingAllFields.json
index 72df009e4c0..26d7a394657 100644
---
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRecursivelyReferencingAllFields.json
+++
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRecursivelyReferencingAllFields.json
@@ -9,4 +9,15 @@
"STATE" : "MS",
"ZIP" : "90210"
} ]
+}, {
+ "NAME" : "Jane Smith",
+ "AGE" : 25,
+ "APPLICATION" : "Apache Kafka",
+ "ADDRESSES" : [ {
+ "NAME" : "Work",
+ "STREET" : "1234 Office Blvd",
+ "CITY" : "Tech Town",
+ "STATE" : "CA",
+ "ZIP" : "94105"
+ } ]
} ]
\ No newline at end of file
diff --git
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRecursivelyReferencingFieldName.json
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRecursivelyReferencingFieldName.json
index 40f3530c61a..273b7020663 100644
---
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRecursivelyReferencingFieldName.json
+++
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRecursivelyReferencingFieldName.json
@@ -9,4 +9,15 @@
"state" : "MS",
"zip" : "90210"
} ]
+}, {
+ "NAME" : "Jane Smith",
+ "age" : 25,
+ "application" : "Apache Kafka",
+ "addresses" : [ {
+ "NAME" : "Work",
+ "street" : "1234 Office Blvd",
+ "city" : "Tech Town",
+ "state" : "CA",
+ "zip" : "94105"
+ } ]
} ]
\ No newline at end of file
diff --git
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testReferencingFieldName.json
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testReferencingFieldName.json
index a72fc8b3604..ef041653654 100644
---
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testReferencingFieldName.json
+++
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testReferencingFieldName.json
@@ -2,4 +2,8 @@
"UPDATED_name" : "John Doe",
"UPDATED_age" : 30,
"UPDATED_application" : "Apache NiFi"
+}, {
+ "UPDATED_name" : "Jane Smith",
+ "UPDATED_age" : 25,
+ "UPDATED_application" : "Apache Kafka"
} ]
\ No newline at end of file
diff --git
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRenameArray.json
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRenameArray.json
index 3f11cf24d29..7174e6d7786 100644
---
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRenameArray.json
+++
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRenameArray.json
@@ -9,4 +9,15 @@
"state" : "MS",
"zip" : "90210"
} ]
+}, {
+ "name" : "Jane Smith",
+ "age" : 25,
+ "application" : "Apache Kafka",
+ "addrs" : [ {
+ "name" : "Work",
+ "street" : "1234 Office Blvd",
+ "city" : "Tech Town",
+ "state" : "CA",
+ "zip" : "94105"
+ } ]
} ]
\ No newline at end of file
diff --git
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRenameFieldStaticValue.json
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRenameFieldStaticValue.json
index 58aec362dab..a9875696066 100644
---
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRenameFieldStaticValue.json
+++
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRenameFieldStaticValue.json
@@ -2,4 +2,8 @@
"name" : "John Doe",
"age" : 30,
"favoriteApplication" : "Apache NiFi"
+}, {
+ "name" : "Jane Smith",
+ "age" : 25,
+ "favoriteApplication" : "Apache Kafka"
} ]
\ No newline at end of file
diff --git
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRenameFieldUsingAttribute.json
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRenameFieldUsingAttribute.json
index 35e9f95e2be..2c72daec7b5 100644
---
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRenameFieldUsingAttribute.json
+++
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRenameFieldUsingAttribute.json
@@ -2,4 +2,8 @@
"name" : "John Doe",
"age" : 30,
"favorite" : "Apache NiFi"
+}, {
+ "name" : "Jane Smith",
+ "age" : 25,
+ "favorite" : "Apache Kafka"
} ]
\ No newline at end of file
diff --git
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRenameMultipleFields.json
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRenameMultipleFields.json
index 6a1b8d5b88c..bc04f52328c 100644
---
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRenameMultipleFields.json
+++
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestRenameRecordField/output/testRenameMultipleFields.json
@@ -2,4 +2,8 @@
"full_name" : "John Doe",
"age" : 30,
"app" : "Apache NiFi"
+}, {
+ "full_name" : "Jane Smith",
+ "age" : 25,
+ "app" : "Apache Kafka"
} ]
\ No newline at end of file