From 7018e1e207a2ca79d3fb98b6bc94ad811a95b1cf Mon Sep 17 00:00:00 2001 From: sonika-shah <58761340+sonika-shah@users.noreply.github.com> Date: Sun, 5 Jul 2026 23:57:36 +0530 Subject: [PATCH 1/2] fix(column-bulk): make grid sort null-safe for null column names Guard the column-name comparator with Comparator.nullsLast so a null column name (e.g. a null map key) sorts last instead of throwing an NPE. Adds a test covering the null case. --- .../service/search/ColumnMetadataGrouper.java | 7 +++++-- .../search/ColumnMetadataGrouperTest.java | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/search/ColumnMetadataGrouper.java b/openmetadata-service/src/main/java/org/openmetadata/service/search/ColumnMetadataGrouper.java index 23ea61d2b669..f7ab13bc02f3 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/search/ColumnMetadataGrouper.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/search/ColumnMetadataGrouper.java @@ -106,9 +106,12 @@ public static List groupColumns( // guaranteed (current callers build it as a HashMap), so sort here for a stable alphabetical // order. Case-insensitive for natural listing, with a case-sensitive tie-breaker so names that // differ only in case (e.g. "Name"/"name") stay stable instead of relying on map order. + // nullsLast guards against a null column name (e.g. a null map key) rather than throwing. gridItems.sort( - Comparator.comparing(ColumnGridItem::getColumnName, String.CASE_INSENSITIVE_ORDER) - .thenComparing(ColumnGridItem::getColumnName)); + Comparator.comparing( + ColumnGridItem::getColumnName, Comparator.nullsLast(String.CASE_INSENSITIVE_ORDER)) + .thenComparing( + ColumnGridItem::getColumnName, Comparator.nullsLast(Comparator.naturalOrder()))); return gridItems; } diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/search/ColumnMetadataGrouperTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/search/ColumnMetadataGrouperTest.java index 25986c8ce3a0..44e7c9e92b63 100644 --- a/openmetadata-service/src/test/java/org/openmetadata/service/search/ColumnMetadataGrouperTest.java +++ b/openmetadata-service/src/test/java/org/openmetadata/service/search/ColumnMetadataGrouperTest.java @@ -19,6 +19,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; @@ -403,6 +404,21 @@ void testGroupColumns_caseOnlyCollisionsAreDeterministic() { assertEquals(List.of("Name", "name"), actual); } + @Test + void testGroupColumns_nullColumnNameSortsLastWithoutError() { + // A null column name (e.g. a null map key) must not throw; it sorts last (nullsLast). + Map> columnsByName = + new LinkedHashMap<>(); + columnsByName.put("beta", singleOccurrence("beta")); + columnsByName.put(null, singleOccurrence(null)); + columnsByName.put("alpha", singleOccurrence("alpha")); + + List result = ColumnMetadataGrouper.groupColumns(columnsByName); + + List actual = result.stream().map(ColumnGridItem::getColumnName).toList(); + assertEquals(Arrays.asList("alpha", "beta", null), actual); + } + private static List singleOccurrence(String columnName) { Column column = new Column(); column.setName(columnName); From 6b7a7783f58ab704bd93c57ae3b9518a08078913 Mon Sep 17 00:00:00 2001 From: sonika-shah <58761340+sonika-shah@users.noreply.github.com> Date: Mon, 6 Jul 2026 15:27:41 +0530 Subject: [PATCH 2/2] fix(column-bulk): skip null-named columns instead of emitting a null required field A null column name (columnName is required in the column-grid response) is now skipped when building rows, so a malformed bucket is dropped and the remaining valid columns are returned. This also avoids the sort NPE at the source; the comparator keeps nullsLast as a backstop. Test updated to assert the null-named row is dropped. --- .../service/search/ColumnMetadataGrouper.java | 5 +++++ .../service/search/ColumnMetadataGrouperTest.java | 8 ++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/search/ColumnMetadataGrouper.java b/openmetadata-service/src/main/java/org/openmetadata/service/search/ColumnMetadataGrouper.java index f7ab13bc02f3..213717b32935 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/search/ColumnMetadataGrouper.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/search/ColumnMetadataGrouper.java @@ -40,6 +40,11 @@ public static List groupColumns( for (Map.Entry> entry : columnsByName.entrySet()) { String columnName = entry.getKey(); + if (columnName == null) { + // A column with no name isn't a valid grid row (columnName is required in the response); + // skip the malformed bucket so we return the remaining valid columns. + continue; + } List occurrences = entry.getValue(); Map groups = new HashMap<>(); diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/search/ColumnMetadataGrouperTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/search/ColumnMetadataGrouperTest.java index 44e7c9e92b63..f495413a09ab 100644 --- a/openmetadata-service/src/test/java/org/openmetadata/service/search/ColumnMetadataGrouperTest.java +++ b/openmetadata-service/src/test/java/org/openmetadata/service/search/ColumnMetadataGrouperTest.java @@ -19,7 +19,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; @@ -405,8 +404,9 @@ void testGroupColumns_caseOnlyCollisionsAreDeterministic() { } @Test - void testGroupColumns_nullColumnNameSortsLastWithoutError() { - // A null column name (e.g. a null map key) must not throw; it sorts last (nullsLast). + void testGroupColumns_nullColumnNameIsSkipped() { + // A null column name (e.g. a null map key) is dropped, not returned with a null required field, + // and must not throw. The remaining valid columns still come back sorted. Map> columnsByName = new LinkedHashMap<>(); columnsByName.put("beta", singleOccurrence("beta")); @@ -416,7 +416,7 @@ void testGroupColumns_nullColumnNameSortsLastWithoutError() { List result = ColumnMetadataGrouper.groupColumns(columnsByName); List actual = result.stream().map(ColumnGridItem::getColumnName).toList(); - assertEquals(Arrays.asList("alpha", "beta", null), actual); + assertEquals(List.of("alpha", "beta"), actual); } private static List singleOccurrence(String columnName) {