This is an automated email from the ASF dual-hosted git repository.
exceptionfactory 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 87c1fc16872 NIFI-16213 Fixed null handing in MapRecord for an array of
UUIDs (#11554)
87c1fc16872 is described below
commit 87c1fc16872d902dc702ab484247b9b78067d7ae
Author: Mike <[email protected]>
AuthorDate: Mon Aug 17 14:56:40 2026 -0400
NIFI-16213 Fixed null handing in MapRecord for an array of UUIDs (#11554)
Added a null check to MapRecord to prevent a NPE from causing breakage when
dealing with an array/list of UUIDs
Signed-off-by: David Handermann <[email protected]>
---
.../nifi/serialization/record/MapRecord.java | 2 +-
.../nifi-standard-processors/pom.xml | 2 ++
.../nifi/processors/standard/TestUpdateRecord.java | 41 ++++++++++++++++++++++
.../input/uuid-list-test-input.json | 20 +++++++++++
.../schema/uuid-list-test-child.avsc | 20 +++++++++++
.../schema/uuid-list-test-parent.avsc | 38 ++++++++++++++++++++
6 files changed, 122 insertions(+), 1 deletion(-)
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 35daa1f87e9..bd3b4d5e244 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
@@ -805,7 +805,7 @@ public class MapRecord implements Record {
final List<DataType> possibleTypes =
choiceDataType.getPossibleSubTypes();
final DataType chosenDataType =
DataTypeUtils.chooseDataType(value, choiceDataType);
- if (chosenDataType.getFieldType() != RecordFieldType.RECORD ||
!(value instanceof final Record childRecord)) {
+ if (chosenDataType == null || chosenDataType.getFieldType() !=
RecordFieldType.RECORD || !(value instanceof final Record childRecord)) {
return specField;
}
diff --git
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/pom.xml
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/pom.xml
index 923eae50471..d78dfb58a5f 100644
---
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/pom.xml
+++
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/pom.xml
@@ -810,6 +810,8 @@
<exclude>src/test/resources/TestUpdateRecord/schema/person-with-name-string-fields.avsc</exclude>
<exclude>src/test/resources/TestUpdateRecord/schema/person-with-name-string.avsc</exclude>
<exclude>src/test/resources/TestUpdateRecord/schema/person-with-stringified-name.avsc</exclude>
+
<exclude>src/test/resources/TestUpdateRecord/schema/uuid-list-test-parent.avsc</exclude>
+
<exclude>src/test/resources/TestUpdateRecord/schema/uuid-list-test-child.avsc</exclude>
<exclude>src/test/resources/TestValidateJson/schema-simple-example-missing-required.json</exclude>
<exclude>src/test/resources/TestValidateJson/schema-simple-example-unmatched-pattern.json</exclude>
<exclude>src/test/resources/TestValidateJson/schema-simple-example.json</exclude>
diff --git
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestUpdateRecord.java
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestUpdateRecord.java
index 4b59f538026..b45c1b6a899 100644
---
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestUpdateRecord.java
+++
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestUpdateRecord.java
@@ -33,6 +33,7 @@ import org.apache.nifi.util.TestRunner;
import org.apache.nifi.util.TestRunners;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import java.io.IOException;
@@ -53,6 +54,8 @@ public class TestUpdateRecord {
private static String personWithNameAndMother;
private static Path multiArraysJson;
private static String multiArraysJsonContent;
+ private static String uuidListSchema;
+ private static String uuidListSchemaChild;
private TestRunner runner;
private MockRecordParser readerService;
@@ -64,6 +67,12 @@ public class TestUpdateRecord {
nameFieldsOnly =
Files.readString(Paths.get("src/test/resources/TestUpdateRecord/schema/name-fields-only.avsc"));
personWithNameAndMother =
Files.readString(Paths.get("src/test/resources/TestUpdateRecord/schema/person-with-name-and-mother.avsc"));
multiArraysJson =
Paths.get("src/test/resources/TestUpdateRecord/input/multi-arrays.json");
+
+ // These schemas were generated with Claude Opus
+ uuidListSchema =
Files.readString(Paths.get("src/test/resources/TestUpdateRecord/schema/uuid-list-test-parent.avsc"));
+ uuidListSchemaChild =
Files.readString(Paths.get("src/test/resources/TestUpdateRecord/schema/uuid-list-test-child.avsc"));
+ //
+
multiArraysJsonContent = JsonUtil.getExpectedContent(multiArraysJson);
}
@@ -883,6 +892,38 @@ public class TestUpdateRecord {
runner.removeProperty("/peoples[0..-1][./name != 'Mary
Doe']/addresses[0,1..2]/city");
}
+ @Test
+ @DisplayName("Updating a field with a pattern like
arrayOf(/participants[*]/user_id) caused a NPE pre-patch")
+ public void testNiFi16213() throws Exception {
+ //This referenced sample input as generated with Claude Opus
+ final String inputJson =
Files.readString(Paths.get("src/test/resources/TestUpdateRecord/input/uuid-list-test-input.json"));
+
+ final JsonTreeReader jsonReader = new JsonTreeReader();
+ runner.addControllerService("reader", jsonReader);
+
+ final String inputSchemaText = uuidListSchema;
+ final String outputSchemaText = uuidListSchemaChild;
+
+ runner.setProperty(jsonReader,
SchemaAccessUtils.SCHEMA_ACCESS_STRATEGY,
SchemaAccessUtils.SCHEMA_TEXT_PROPERTY);
+ runner.setProperty(jsonReader, SchemaAccessUtils.SCHEMA_TEXT,
inputSchemaText);
+ runner.enableControllerService(jsonReader);
+
+ final JsonRecordSetWriter jsonWriter = new JsonRecordSetWriter();
+ runner.addControllerService("writer", jsonWriter);
+ runner.setProperty(jsonWriter,
SchemaAccessUtils.SCHEMA_ACCESS_STRATEGY,
SchemaAccessUtils.SCHEMA_TEXT_PROPERTY);
+ runner.setProperty(jsonWriter, SchemaAccessUtils.SCHEMA_TEXT,
outputSchemaText);
+ runner.setProperty(jsonWriter, "Pretty Print JSON", "true");
+ runner.setProperty(jsonWriter, "Schema Write Strategy",
"full-schema-attribute");
+ runner.setProperty(UpdateRecord.REPLACEMENT_VALUE_STRATEGY,
UpdateRecord.RECORD_PATH_VALUES);
+ runner.enableControllerService(jsonWriter);
+
+ runner.enqueue(inputJson);
+ runner.setProperty("/participants",
"arrayOf(/participants[*]/user_id)");
+ runner.run();
+
+ runner.assertAllFlowFilesTransferred(UpdateRecord.REL_SUCCESS);
+ }
+
private void assertCountMatches(String content, String match, int
expectedCount) {
final int actualCount = StringUtils.countMatches(content, match);
diff --git
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestUpdateRecord/input/uuid-list-test-input.json
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestUpdateRecord/input/uuid-list-test-input.json
new file mode 100644
index 00000000000..0262e6f9af8
--- /dev/null
+++
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestUpdateRecord/input/uuid-list-test-input.json
@@ -0,0 +1,20 @@
+{
+ "chat_name": "Atlas Cutover Squad",
+ "participants": [
+ {
+ "user_id": "223a47ed-0f2c-44c5-b2ac-2a37133bf101",
+ "authenticator": "google-oauth2",
+ "principal": "priya.patel"
+ },
+ {
+ "user_id": "b7e92e2b-de17-4e1e-9415-8bc8057d8cbc",
+ "authenticator": "saml",
+ "principal": "[email protected]"
+ },
+ {
+ "user_id": "b9debc33-fbb6-4fca-9a90-f361b7572fea",
+ "authenticator": "okta-saml",
+ "principal": "jordan.kim"
+ }
+ ]
+}
diff --git
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestUpdateRecord/schema/uuid-list-test-child.avsc
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestUpdateRecord/schema/uuid-list-test-child.avsc
new file mode 100644
index 00000000000..52c5d746936
--- /dev/null
+++
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestUpdateRecord/schema/uuid-list-test-child.avsc
@@ -0,0 +1,20 @@
+{
+ "type": "record",
+ "name": "Chat",
+ "namespace": "com.example.chat",
+ "fields": [
+ {
+ "name": "chat_name",
+ "type": ["null", "string"],
+ "default": null
+ },
+ {
+ "name": "participants",
+ "type": {
+ "type": "array",
+ "items": { "type": "string", "logicalType": "uuid" }
+ },
+ "default": []
+ }
+ ]
+}
diff --git
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestUpdateRecord/schema/uuid-list-test-parent.avsc
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestUpdateRecord/schema/uuid-list-test-parent.avsc
new file mode 100644
index 00000000000..32be0f80d16
--- /dev/null
+++
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestUpdateRecord/schema/uuid-list-test-parent.avsc
@@ -0,0 +1,38 @@
+{
+ "type": "record",
+ "name": "IngestedChatMessage",
+ "namespace": "com.example.chat",
+ "fields": [
+
+ {
+ "name": "chat_name",
+ "type": ["null", "string"],
+ "default": null
+ },
+ {
+ "name": "participants",
+ "type": {
+ "type": "array",
+ "items": {
+ "type": "record",
+ "name": "Participant",
+ "doc": "One chat member and when they joined.",
+ "fields": [
+ {
+ "name": "user_id",
+ "type": { "type": "string", "logicalType": "uuid" }
+ },
+ {
+ "name": "authenticator",
+ "type": "string"
+ },
+ {
+ "name": "principal",
+ "type": "string"
+ }
+ ]
+ }
+ }
+ }
+ ]
+}