This is an automated email from the ASF dual-hosted git repository.
jmclean pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git
The following commit(s) were added to refs/heads/main by this push:
new 8e01ca5485 [#10605] fix(server): avoid secondary NPE in
dropPartitionStatistics (#10618)
8e01ca5485 is described below
commit 8e01ca548592b7257b25913b355ffd21d5f78cdd
Author: Khushang Thakkar <[email protected]>
AuthorDate: Wed Apr 1 06:46:07 2026 +0530
[#10605] fix(server): avoid secondary NPE in dropPartitionStatistics
(#10618)
#10605
## What changes were proposed in this pull request?
Fix `dropPartitionStatistics` so the REST exception handler does not
throw a secondary
`NullPointerException` when the request body is invalid and `drops` is
null.
Previously, the catch block in `StatisticOperations` called
`request.getDrops().stream()`
while building the partition name string for the error response. If
`request` or
`request.getDrops()` was null, that masked the original validation
failure and could turn
a client-side bad request into an internal server error.
This PR:
- adds a null-safe helper for extracting drop partition names
- uses that helper in the `dropPartitionStatistics` catch block
- adds a regression test for `{"drops": null}`
## How was this patch tested?
```bash
./gradlew :server:test --tests
org.apache.gravitino.server.web.rest.TestStatisticOperations
---
.../server/web/rest/StatisticOperations.java | 19 +++++++++-----
.../server/web/rest/TestStatisticOperations.java | 29 ++++++++++++++++++++++
2 files changed, 42 insertions(+), 6 deletions(-)
diff --git
a/server/src/main/java/org/apache/gravitino/server/web/rest/StatisticOperations.java
b/server/src/main/java/org/apache/gravitino/server/web/rest/StatisticOperations.java
index 0c87a9f03f..1f4999dfcf 100644
---
a/server/src/main/java/org/apache/gravitino/server/web/rest/StatisticOperations.java
+++
b/server/src/main/java/org/apache/gravitino/server/web/rest/StatisticOperations.java
@@ -455,12 +455,7 @@ public class StatisticOperations {
fullName,
metalake,
e);
- String partitions =
- StringUtils.joinWith(
- ",",
- request.getDrops().stream()
- .map(PartitionStatisticsDropDTO::partitionName)
- .collect(Collectors.toList()));
+ String partitions = getDropPartitionNames(request);
return ExceptionHandlers.handlePartitionStatsException(
OperationType.DROP, partitions, fullName, e);
}
@@ -515,4 +510,16 @@ public class StatisticOperations {
.map(PartitionStatisticsUpdateDTO::partitionName)
.collect(Collectors.toList()));
}
+
+ private static String getDropPartitionNames(PartitionStatisticsDropRequest
request) {
+ if (request == null || request.getDrops() == null) {
+ return "";
+ }
+
+ return StringUtils.joinWith(
+ ",",
+ request.getDrops().stream()
+ .map(PartitionStatisticsDropDTO::partitionName)
+ .collect(Collectors.toList()));
+ }
}
diff --git
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestStatisticOperations.java
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestStatisticOperations.java
index 547d79ad74..dc3055a550 100644
---
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestStatisticOperations.java
+++
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestStatisticOperations.java
@@ -863,6 +863,35 @@ public class TestStatisticOperations extends JerseyTest {
UnmodifiableStatisticException.class.getSimpleName(),
errorResp3.getType());
}
+ @Test
+ public void testDropPartitionStatisticsWithNullDrops() {
+ when(tableDispatcher.tableExists(any())).thenReturn(true);
+ MetadataObject tableObject =
+ MetadataObjects.parse(
+ String.format("%s.%s.%s", catalog, schema, table),
MetadataObject.Type.TABLE);
+
+ Response response =
+ target(
+ "/metalakes/"
+ + metalake
+ + "/objects/"
+ + tableObject.type()
+ + "/"
+ + tableObject.fullName()
+ + "/statistics/partitions")
+ .request(MediaType.APPLICATION_JSON_TYPE)
+ .accept("application/vnd.gravitino.v1+json")
+ .post(entity("{\"drops\":null}", MediaType.APPLICATION_JSON_TYPE));
+
+ Assertions.assertEquals(Response.Status.BAD_REQUEST.getStatusCode(),
response.getStatus());
+ Assertions.assertEquals(MediaType.APPLICATION_JSON_TYPE,
response.getMediaType());
+
+ ErrorResponse errorResponse = response.readEntity(ErrorResponse.class);
+ Assertions.assertEquals(ErrorConstants.ILLEGAL_ARGUMENTS_CODE,
errorResponse.getCode());
+ Assertions.assertEquals(
+ IllegalArgumentException.class.getSimpleName(),
errorResponse.getType());
+ }
+
@Test
public void testGetBoundType() {
Assertions.assertEquals(