This is an automated email from the ASF dual-hosted git repository.

jerryshao 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 f08dc93cad [#10172] fix(server): preserve REST errors for null request 
bodies (#12590)
f08dc93cad is described below

commit f08dc93cad344fa37c52cc3a7d897dd101bfef17
Author: Nguyễn Xuân Lộc <[email protected]>
AuthorDate: Mon Aug 31 10:40:37 2026 +0700

    [#10172] fix(server): preserve REST errors for null request bodies (#12590)
    
    ### What changes were proposed in this pull request?
    
    - Precompute null-safe request identifiers before entering the affected
    REST `try/catch` blocks.
    - Use those precomputed values in exception handlers instead of
    dereferencing `request` from catch paths.
    - Cover create/register/grant/revoke/statistics/job-template handlers
    listed in #10172 while keeping the existing `ExceptionHandlers` mappings
    and endpoint contracts unchanged.
    - Add a regression test for a null group request body to verify that the
    original error is marshalled instead of being replaced by a secondary
    `NullPointerException`.
    
    ### Why are the changes needed?
    
    Several REST catch paths call methods such as `request.getName()`,
    `request.getRoleNames()`, or `request.getJobTemplate()` after an
    exception has already occurred. If the request itself is null, the catch
    block can throw another `NullPointerException`, masking the primary
    failure and preventing the existing exception handlers from returning
    the intended error response.
    
    Fix: #10172
    
    ### Does this PR introduce _any_ user-facing change?
    
    No API or configuration contract changes. For malformed/null request
    bodies, error responses now preserve the original exception-handling
    path instead of being replaced by a secondary catch-path
    `NullPointerException`.
    
    ### How was this patch tested?
    
    - `JAVA_HOME=/opt/homebrew/opt/openjdk@17 ./gradlew :server:compileJava
    -PskipITs --no-daemon`
    - `JAVA_HOME=/opt/homebrew/opt/openjdk@17 ./gradlew :server:test --tests
    
org.apache.gravitino.server.web.rest.TestGroupOperations.testAddGroupWithNullRequestBodyDoesNotExposeNpe
    -PskipITs --no-daemon`
    - Ran the affected REST test classes as a wider targeted batch. 168/169
    passed; `TestTopicOperations.testRemoveTopicProperties` failed once with
    404 vs 200, then passed when rerun by itself, indicating an
    intermittent/shared-state test failure unrelated to this catch-path
    change.
    - `git diff --check`
---
 .../apache/gravitino/server/web/rest/CatalogOperations.java |  8 +++++---
 .../apache/gravitino/server/web/rest/FilesetOperations.java | 10 +++-------
 .../gravitino/server/web/rest/FunctionOperations.java       |  9 +++------
 .../apache/gravitino/server/web/rest/GroupOperations.java   |  4 ++--
 .../org/apache/gravitino/server/web/rest/JobOperations.java |  8 ++++----
 .../gravitino/server/web/rest/MetalakeOperations.java       |  4 ++--
 .../apache/gravitino/server/web/rest/ModelOperations.java   | 11 +++--------
 .../gravitino/server/web/rest/PermissionOperations.java     | 12 ++++++++----
 .../apache/gravitino/server/web/rest/PolicyOperations.java  |  4 ++--
 .../apache/gravitino/server/web/rest/RoleOperations.java    |  4 ++--
 .../apache/gravitino/server/web/rest/SchemaOperations.java  |  6 +++---
 .../gravitino/server/web/rest/StatisticOperations.java      | 13 +++++++++----
 .../apache/gravitino/server/web/rest/TableOperations.java   |  7 +++----
 .../org/apache/gravitino/server/web/rest/TagOperations.java |  4 ++--
 .../apache/gravitino/server/web/rest/TopicOperations.java   |  4 ++--
 .../apache/gravitino/server/web/rest/UserOperations.java    |  4 ++--
 .../gravitino/server/web/rest/TestGroupOperations.java      | 13 +++++++++++++
 17 files changed, 68 insertions(+), 57 deletions(-)

diff --git 
a/server/src/main/java/org/apache/gravitino/server/web/rest/CatalogOperations.java
 
b/server/src/main/java/org/apache/gravitino/server/web/rest/CatalogOperations.java
index 79a260bfef..e7a1aedb0d 100644
--- 
a/server/src/main/java/org/apache/gravitino/server/web/rest/CatalogOperations.java
+++ 
b/server/src/main/java/org/apache/gravitino/server/web/rest/CatalogOperations.java
@@ -143,6 +143,7 @@ public class CatalogOperations {
       @PathParam("metalake") @AuthorizationMetadata(type = 
Entity.EntityType.METALAKE)
           String metalake,
       CatalogCreateRequest request) {
+    String catalogName = request == null ? "" : request.getName();
     LOG.info("Received create catalog request for metalake: {}", metalake);
     try {
       return Utils.doAs(
@@ -166,7 +167,7 @@ public class CatalogOperations {
 
     } catch (Exception e) {
       return ExceptionHandlers.handleCatalogException(
-          OperationType.CREATE, request.getName(), metalake, e);
+          OperationType.CREATE, catalogName, metalake, e);
     }
   }
 
@@ -182,7 +183,8 @@ public class CatalogOperations {
       @PathParam("metalake") @AuthorizationMetadata(type = 
Entity.EntityType.METALAKE)
           String metalake,
       CatalogCreateRequest request) {
-    LOG.info("Received test connection request for catalog: {}.{}", metalake, 
request.getName());
+    String catalogName = request == null ? "" : request.getName();
+    LOG.info("Received test connection request for catalog: {}.{}", metalake, 
catalogName);
     try {
       return Utils.doAs(
           httpRequest,
@@ -202,7 +204,7 @@ public class CatalogOperations {
           });
 
     } catch (Exception e) {
-      LOG.info("Failed to test connection for catalog: {}.{}", metalake, 
request.getName());
+      LOG.info("Failed to test connection for catalog: {}.{}", metalake, 
catalogName);
       return ExceptionHandlers.handleTestConnectionException(e);
     }
   }
diff --git 
a/server/src/main/java/org/apache/gravitino/server/web/rest/FilesetOperations.java
 
b/server/src/main/java/org/apache/gravitino/server/web/rest/FilesetOperations.java
index 0802f852a5..11f1d6f18c 100644
--- 
a/server/src/main/java/org/apache/gravitino/server/web/rest/FilesetOperations.java
+++ 
b/server/src/main/java/org/apache/gravitino/server/web/rest/FilesetOperations.java
@@ -146,12 +146,9 @@ public class FilesetOperations {
       @PathParam("catalog") @AuthorizationMetadata(type = 
Entity.EntityType.CATALOG) String catalog,
       @PathParam("schema") @AuthorizationMetadata(type = 
Entity.EntityType.SCHEMA) String schema,
       FilesetCreateRequest request) {
+    String filesetName = request == null ? "" : request.getName();
     LOG.info(
-        "Received create fileset request: {}.{}.{}.{}",
-        metalake,
-        catalog,
-        schema,
-        request.getName());
+        "Received create fileset request: {}.{}.{}.{}", metalake, catalog, 
schema, filesetName);
     try {
       return Utils.doAs(
           httpRequest,
@@ -184,8 +181,7 @@ public class FilesetOperations {
           });
 
     } catch (Exception e) {
-      return ExceptionHandlers.handleFilesetException(
-          OperationType.CREATE, request.getName(), schema, e);
+      return ExceptionHandlers.handleFilesetException(OperationType.CREATE, 
filesetName, schema, e);
     }
   }
 
diff --git 
a/server/src/main/java/org/apache/gravitino/server/web/rest/FunctionOperations.java
 
b/server/src/main/java/org/apache/gravitino/server/web/rest/FunctionOperations.java
index 70b7b9e2ae..7e3fcd8a30 100644
--- 
a/server/src/main/java/org/apache/gravitino/server/web/rest/FunctionOperations.java
+++ 
b/server/src/main/java/org/apache/gravitino/server/web/rest/FunctionOperations.java
@@ -160,12 +160,9 @@ public class FunctionOperations {
       @PathParam("catalog") @AuthorizationMetadata(type = 
Entity.EntityType.CATALOG) String catalog,
       @PathParam("schema") @AuthorizationMetadata(type = 
Entity.EntityType.SCHEMA) String schema,
       FunctionRegisterRequest request) {
+    String functionName = request == null ? "" : request.getName();
     LOG.info(
-        "Received register function request: {}.{}.{}.{}",
-        metalake,
-        catalog,
-        schema,
-        request.getName());
+        "Received register function request: {}.{}.{}.{}", metalake, catalog, 
schema, functionName);
     try {
       return Utils.doAs(
           httpRequest,
@@ -194,7 +191,7 @@ public class FunctionOperations {
           });
     } catch (Exception e) {
       return ExceptionHandlers.handleFunctionException(
-          OperationType.REGISTER, request.getName(), schema, e);
+          OperationType.REGISTER, functionName, schema, e);
     }
   }
 
diff --git 
a/server/src/main/java/org/apache/gravitino/server/web/rest/GroupOperations.java
 
b/server/src/main/java/org/apache/gravitino/server/web/rest/GroupOperations.java
index ef44db299c..9164bf414e 100644
--- 
a/server/src/main/java/org/apache/gravitino/server/web/rest/GroupOperations.java
+++ 
b/server/src/main/java/org/apache/gravitino/server/web/rest/GroupOperations.java
@@ -113,6 +113,7 @@ public class GroupOperations {
       @PathParam("metalake") @AuthorizationMetadata(type = 
Entity.EntityType.METALAKE)
           String metalake,
       GroupAddRequest request) {
+    String groupName = request == null ? "" : request.getName();
     try {
       return Utils.doAs(
           httpRequest,
@@ -127,8 +128,7 @@ public class GroupOperations {
             return Utils.ok(new 
GroupResponse(DTOConverters.toDTO(addedGroup)));
           });
     } catch (Exception e) {
-      return ExceptionHandlers.handleGroupException(
-          OperationType.ADD, request.getName(), metalake, e);
+      return ExceptionHandlers.handleGroupException(OperationType.ADD, 
groupName, metalake, e);
     }
   }
 
diff --git 
a/server/src/main/java/org/apache/gravitino/server/web/rest/JobOperations.java 
b/server/src/main/java/org/apache/gravitino/server/web/rest/JobOperations.java
index 55f8b578e8..d339734c04 100644
--- 
a/server/src/main/java/org/apache/gravitino/server/web/rest/JobOperations.java
+++ 
b/server/src/main/java/org/apache/gravitino/server/web/rest/JobOperations.java
@@ -158,10 +158,10 @@ public class JobOperations {
       @PathParam("metalake") @AuthorizationMetadata(type = 
Entity.EntityType.METALAKE)
           String metalake,
       JobTemplateRegisterRequest request) {
+    String jobTemplateName =
+        request == null || request.getJobTemplate() == null ? "" : 
request.getJobTemplate().name();
     LOG.info(
-        "Received request to register job template {} in metalake: {}",
-        request.getJobTemplate().name(),
-        metalake);
+        "Received request to register job template {} in metalake: {}", 
jobTemplateName, metalake);
 
     try {
       return Utils.doAs(
@@ -181,7 +181,7 @@ public class JobOperations {
 
     } catch (Exception e) {
       return ExceptionHandlers.handleJobTemplateException(
-          OperationType.REGISTER, request.getJobTemplate().name(), metalake, 
e);
+          OperationType.REGISTER, jobTemplateName, metalake, e);
     }
   }
 
diff --git 
a/server/src/main/java/org/apache/gravitino/server/web/rest/MetalakeOperations.java
 
b/server/src/main/java/org/apache/gravitino/server/web/rest/MetalakeOperations.java
index a02eea506b..a42e0a9678 100644
--- 
a/server/src/main/java/org/apache/gravitino/server/web/rest/MetalakeOperations.java
+++ 
b/server/src/main/java/org/apache/gravitino/server/web/rest/MetalakeOperations.java
@@ -123,7 +123,8 @@ public class MetalakeOperations {
           OperationType.CREATE, "", new IllegalArgumentException("Request body 
cannot be null"));
     }
 
-    LOG.info("Received create metalake request for {}", request.getName());
+    String metalakeName = request.getName();
+    LOG.info("Received create metalake request for {}", metalakeName);
     try {
       return Utils.doAs(
           httpRequest,
@@ -139,7 +140,6 @@ public class MetalakeOperations {
           });
 
     } catch (Exception e) {
-      String metalakeName = request != null ? request.getName() : "";
       return ExceptionHandlers.handleMetalakeException(OperationType.CREATE, 
metalakeName, e);
     }
   }
diff --git 
a/server/src/main/java/org/apache/gravitino/server/web/rest/ModelOperations.java
 
b/server/src/main/java/org/apache/gravitino/server/web/rest/ModelOperations.java
index 3c5dd63946..1c51fc380d 100644
--- 
a/server/src/main/java/org/apache/gravitino/server/web/rest/ModelOperations.java
+++ 
b/server/src/main/java/org/apache/gravitino/server/web/rest/ModelOperations.java
@@ -172,12 +172,8 @@ public class ModelOperations {
       @PathParam("catalog") @AuthorizationMetadata(type = 
Entity.EntityType.CATALOG) String catalog,
       @PathParam("schema") @AuthorizationMetadata(type = 
Entity.EntityType.SCHEMA) String schema,
       ModelRegisterRequest request) {
-    LOG.info(
-        "Received register model request: {}.{}.{}.{}",
-        metalake,
-        catalog,
-        schema,
-        request.getName());
+    String modelName = request == null ? "" : request.getName();
+    LOG.info("Received register model request: {}.{}.{}.{}", metalake, 
catalog, schema, modelName);
 
     try {
       return Utils.doAs(
@@ -194,8 +190,7 @@ public class ModelOperations {
           });
 
     } catch (Exception e) {
-      return ExceptionHandlers.handleModelException(
-          OperationType.REGISTER, request.getName(), schema, e);
+      return ExceptionHandlers.handleModelException(OperationType.REGISTER, 
modelName, schema, e);
     }
   }
 
diff --git 
a/server/src/main/java/org/apache/gravitino/server/web/rest/PermissionOperations.java
 
b/server/src/main/java/org/apache/gravitino/server/web/rest/PermissionOperations.java
index 6ea1ea3390..b7d0690f5a 100644
--- 
a/server/src/main/java/org/apache/gravitino/server/web/rest/PermissionOperations.java
+++ 
b/server/src/main/java/org/apache/gravitino/server/web/rest/PermissionOperations.java
@@ -88,6 +88,7 @@ public class PermissionOperations {
           String metalake,
       @PathParam("user") String user,
       RoleGrantRequest request) {
+    String roleNames = request == null ? "" : 
StringUtils.join(request.getRoleNames(), ",");
     try {
       return Utils.doAs(
           httpRequest,
@@ -102,7 +103,7 @@ public class PermissionOperations {
           });
     } catch (Exception e) {
       return ExceptionHandlers.handleUserPermissionOperationException(
-          OperationType.GRANT, StringUtils.join(request.getRoleNames(), ","), 
user, e);
+          OperationType.GRANT, roleNames, user, e);
     }
   }
 
@@ -117,6 +118,7 @@ public class PermissionOperations {
           String metalake,
       @PathParam("group") String group,
       RoleGrantRequest request) {
+    String roleNames = request == null ? "" : 
StringUtils.join(request.getRoleNames(), ",");
     try {
       return Utils.doAs(
           httpRequest,
@@ -131,7 +133,7 @@ public class PermissionOperations {
           });
     } catch (Exception e) {
       return ExceptionHandlers.handleGroupPermissionOperationException(
-          OperationType.GRANT, StringUtils.join(request.getRoleNames(), ","), 
group, e);
+          OperationType.GRANT, roleNames, group, e);
     }
   }
 
@@ -146,6 +148,7 @@ public class PermissionOperations {
           String metalake,
       @PathParam("user") String user,
       RoleRevokeRequest request) {
+    String roleNames = request == null ? "" : 
StringUtils.join(request.getRoleNames(), ",");
     try {
       return Utils.doAs(
           httpRequest,
@@ -160,7 +163,7 @@ public class PermissionOperations {
           });
     } catch (Exception e) {
       return ExceptionHandlers.handleUserPermissionOperationException(
-          OperationType.REVOKE, StringUtils.join(request.getRoleNames(), ","), 
user, e);
+          OperationType.REVOKE, roleNames, user, e);
     }
   }
 
@@ -175,6 +178,7 @@ public class PermissionOperations {
           String metalake,
       @PathParam("group") String group,
       RoleRevokeRequest request) {
+    String roleNames = request == null ? "" : 
StringUtils.join(request.getRoleNames(), ",");
     try {
       return Utils.doAs(
           httpRequest,
@@ -189,7 +193,7 @@ public class PermissionOperations {
           });
     } catch (Exception e) {
       return ExceptionHandlers.handleGroupPermissionOperationException(
-          OperationType.REVOKE, StringUtils.join(request.getRoleNames(), ","), 
group, e);
+          OperationType.REVOKE, roleNames, group, e);
     }
   }
 
diff --git 
a/server/src/main/java/org/apache/gravitino/server/web/rest/PolicyOperations.java
 
b/server/src/main/java/org/apache/gravitino/server/web/rest/PolicyOperations.java
index 5e73e91236..d3a8243c98 100644
--- 
a/server/src/main/java/org/apache/gravitino/server/web/rest/PolicyOperations.java
+++ 
b/server/src/main/java/org/apache/gravitino/server/web/rest/PolicyOperations.java
@@ -141,6 +141,7 @@ public class PolicyOperations {
       @PathParam("metalake") @AuthorizationMetadata(type = 
Entity.EntityType.METALAKE)
           String metalake,
       PolicyCreateRequest request) {
+    String policyName = request == null ? "" : request.getName();
     LOG.info("Received create policy request under metalake: {}", metalake);
 
     try {
@@ -162,8 +163,7 @@ public class PolicyOperations {
             return Utils.ok(new PolicyResponse(toDTO(policy, 
Optional.empty())));
           });
     } catch (Exception e) {
-      return ExceptionHandlers.handlePolicyException(
-          OperationType.CREATE, request.getName(), metalake, e);
+      return ExceptionHandlers.handlePolicyException(OperationType.CREATE, 
policyName, metalake, e);
     }
   }
 
diff --git 
a/server/src/main/java/org/apache/gravitino/server/web/rest/RoleOperations.java 
b/server/src/main/java/org/apache/gravitino/server/web/rest/RoleOperations.java
index 684ac03b6f..c6a60b1b65 100644
--- 
a/server/src/main/java/org/apache/gravitino/server/web/rest/RoleOperations.java
+++ 
b/server/src/main/java/org/apache/gravitino/server/web/rest/RoleOperations.java
@@ -140,6 +140,7 @@ public class RoleOperations {
       @PathParam("metalake") @AuthorizationMetadata(type = 
Entity.EntityType.METALAKE)
           String metalake,
       RoleCreateRequest request) {
+    String roleName = request == null ? "" : request.getName();
     try {
 
       return Utils.doAs(
@@ -197,8 +198,7 @@ public class RoleOperations {
           });
 
     } catch (Exception e) {
-      return ExceptionHandlers.handleRoleException(
-          OperationType.CREATE, request.getName(), metalake, e);
+      return ExceptionHandlers.handleRoleException(OperationType.CREATE, 
roleName, metalake, e);
     }
   }
 
diff --git 
a/server/src/main/java/org/apache/gravitino/server/web/rest/SchemaOperations.java
 
b/server/src/main/java/org/apache/gravitino/server/web/rest/SchemaOperations.java
index 49fc72941a..6541c7ff6a 100644
--- 
a/server/src/main/java/org/apache/gravitino/server/web/rest/SchemaOperations.java
+++ 
b/server/src/main/java/org/apache/gravitino/server/web/rest/SchemaOperations.java
@@ -143,7 +143,8 @@ public class SchemaOperations {
       @PathParam("catalog") @AuthorizationMetadata(type = 
Entity.EntityType.CATALOG) String catalog,
       @AuthorizationRequest(type = 
AuthorizationRequest.RequestType.CREATE_SCHEMA)
           SchemaCreateRequest request) {
-    LOG.info("Received create schema request: {}.{}.{}", metalake, catalog, 
request.getName());
+    String schemaName = request == null ? "" : request.getName();
+    LOG.info("Received create schema request: {}.{}.{}", metalake, catalog, 
schemaName);
     try {
       return Utils.doAs(
           httpRequest,
@@ -164,8 +165,7 @@ public class SchemaOperations {
           });
 
     } catch (Exception e) {
-      return ExceptionHandlers.handleSchemaException(
-          OperationType.CREATE, request.getName(), catalog, e);
+      return ExceptionHandlers.handleSchemaException(OperationType.CREATE, 
schemaName, catalog, e);
     }
   }
 
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 420869c020..5b99050d95 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
@@ -154,6 +154,7 @@ public class StatisticOperations {
       @PathParam("type") @AuthorizationObjectType String type,
       @PathParam("fullName") @AuthorizationFullName String fullName,
       StatisticsUpdateRequest request) {
+    String statisticNames = getStatisticNames(request);
     try {
       LOG.info(
           "Received update statistics request for object full name: {} type: 
{} in the metalake {}",
@@ -194,7 +195,7 @@ public class StatisticOperations {
           });
     } catch (Exception e) {
       return ExceptionHandlers.handleStatisticException(
-          OperationType.UPDATE, getStatisticNames(request), fullName, e);
+          OperationType.UPDATE, statisticNames, fullName, e);
     }
   }
 
@@ -214,6 +215,10 @@ public class StatisticOperations {
       @PathParam("type") @AuthorizationObjectType String type,
       @PathParam("fullName") @AuthorizationFullName String fullName,
       StatisticsDropRequest request) {
+    String statisticNames =
+        request == null || request.getNames() == null
+            ? ""
+            : StringUtils.join(request.getNames(), ",");
     try {
       LOG.info(
           "Received drop statistics request for object full name: {} type: {} 
in the metalake {}",
@@ -242,7 +247,7 @@ public class StatisticOperations {
           });
     } catch (Exception e) {
       return ExceptionHandlers.handleStatisticException(
-          OperationType.DROP, StringUtils.join(request.getNames(), ","), 
fullName, e);
+          OperationType.DROP, statisticNames, fullName, e);
     }
   }
 
@@ -353,6 +358,7 @@ public class StatisticOperations {
       @PathParam("type") @AuthorizationObjectType String type,
       @PathParam("fullName") @AuthorizationFullName String fullName,
       PartitionStatisticsUpdateRequest request) {
+    String partitions = getPartitionNames(request);
     LOG.info("Updating partition statistics for table: {} in the metalake {}", 
fullName, metalake);
     try {
       return Utils.doAs(
@@ -404,7 +410,6 @@ public class StatisticOperations {
           fullName,
           metalake,
           e);
-      String partitions = getPartitionNames(request);
       return ExceptionHandlers.handlePartitionStatsException(
           OperationType.UPDATE, partitions, fullName, e);
     }
@@ -427,6 +432,7 @@ public class StatisticOperations {
       @PathParam("type") @AuthorizationObjectType String type,
       @PathParam("fullName") @AuthorizationFullName String fullName,
       PartitionStatisticsDropRequest request) {
+    String partitions = getDropPartitionNames(request);
 
     try {
       return Utils.doAs(
@@ -461,7 +467,6 @@ public class StatisticOperations {
           fullName,
           metalake,
           e);
-      String partitions = getDropPartitionNames(request);
       return ExceptionHandlers.handlePartitionStatsException(
           OperationType.DROP, partitions, fullName, e);
     }
diff --git 
a/server/src/main/java/org/apache/gravitino/server/web/rest/TableOperations.java
 
b/server/src/main/java/org/apache/gravitino/server/web/rest/TableOperations.java
index b44f7b1408..aa83ad78f7 100644
--- 
a/server/src/main/java/org/apache/gravitino/server/web/rest/TableOperations.java
+++ 
b/server/src/main/java/org/apache/gravitino/server/web/rest/TableOperations.java
@@ -129,8 +129,8 @@ public class TableOperations {
       @PathParam("catalog") @AuthorizationMetadata(type = 
Entity.EntityType.CATALOG) String catalog,
       @PathParam("schema") @AuthorizationMetadata(type = 
Entity.EntityType.SCHEMA) String schema,
       TableCreateRequest request) {
-    LOG.info(
-        "Received create table request: {}.{}.{}.{}", metalake, catalog, 
schema, request.getName());
+    String tableName = request == null ? "" : request.getName();
+    LOG.info("Received create table request: {}.{}.{}.{}", metalake, catalog, 
schema, tableName);
     try {
       return Utils.doAs(
           httpRequest,
@@ -155,8 +155,7 @@ public class TableOperations {
           });
 
     } catch (Exception e) {
-      return ExceptionHandlers.handleTableException(
-          OperationType.CREATE, request.getName(), schema, e);
+      return ExceptionHandlers.handleTableException(OperationType.CREATE, 
tableName, schema, e);
     }
   }
 
diff --git 
a/server/src/main/java/org/apache/gravitino/server/web/rest/TagOperations.java 
b/server/src/main/java/org/apache/gravitino/server/web/rest/TagOperations.java
index de6460fa2a..4a2fa3554d 100644
--- 
a/server/src/main/java/org/apache/gravitino/server/web/rest/TagOperations.java
+++ 
b/server/src/main/java/org/apache/gravitino/server/web/rest/TagOperations.java
@@ -151,6 +151,7 @@ public class TagOperations {
       @PathParam("metalake") @AuthorizationMetadata(type = 
Entity.EntityType.METALAKE)
           String metalake,
       TagCreateRequest request) {
+    String tagName = request == null ? "" : request.getName();
     LOG.info("Received create tag request under metalake: {}", metalake);
 
     try {
@@ -170,8 +171,7 @@ public class TagOperations {
             return Utils.ok(new TagResponse(DTOConverters.toDTO(tag, 
Optional.empty())));
           });
     } catch (Exception e) {
-      return ExceptionHandlers.handleTagException(
-          OperationType.CREATE, request.getName(), metalake, e);
+      return ExceptionHandlers.handleTagException(OperationType.CREATE, 
tagName, metalake, e);
     }
   }
 
diff --git 
a/server/src/main/java/org/apache/gravitino/server/web/rest/TopicOperations.java
 
b/server/src/main/java/org/apache/gravitino/server/web/rest/TopicOperations.java
index beedcac793..d031f267a4 100644
--- 
a/server/src/main/java/org/apache/gravitino/server/web/rest/TopicOperations.java
+++ 
b/server/src/main/java/org/apache/gravitino/server/web/rest/TopicOperations.java
@@ -124,6 +124,7 @@ public class TopicOperations {
       @PathParam("catalog") @AuthorizationMetadata(type = 
Entity.EntityType.CATALOG) String catalog,
       @PathParam("schema") @AuthorizationMetadata(type = 
Entity.EntityType.SCHEMA) String schema,
       TopicCreateRequest request) {
+    String topicName = request == null ? "" : request.getName();
     LOG.info("Received create topic request: {}.{}.{}", metalake, catalog, 
schema);
     try {
       return Utils.doAs(
@@ -150,8 +151,7 @@ public class TopicOperations {
             return response;
           });
     } catch (Exception e) {
-      return ExceptionHandlers.handleTopicException(
-          OperationType.CREATE, request.getName(), schema, e);
+      return ExceptionHandlers.handleTopicException(OperationType.CREATE, 
topicName, schema, e);
     }
   }
 
diff --git 
a/server/src/main/java/org/apache/gravitino/server/web/rest/UserOperations.java 
b/server/src/main/java/org/apache/gravitino/server/web/rest/UserOperations.java
index 57e21c844c..a984b469d7 100644
--- 
a/server/src/main/java/org/apache/gravitino/server/web/rest/UserOperations.java
+++ 
b/server/src/main/java/org/apache/gravitino/server/web/rest/UserOperations.java
@@ -155,6 +155,7 @@ public class UserOperations {
       @PathParam("metalake") @AuthorizationMetadata(type = 
Entity.EntityType.METALAKE)
           String metalake,
       UserAddRequest request) {
+    String userName = request == null ? "" : request.getName();
     try {
       return Utils.doAs(
           httpRequest,
@@ -172,8 +173,7 @@ public class UserOperations {
             return Utils.ok(new UserResponse(DTOConverters.toDTO(addedUser)));
           });
     } catch (Exception e) {
-      return ExceptionHandlers.handleUserException(
-          OperationType.ADD, request.getName(), metalake, e);
+      return ExceptionHandlers.handleUserException(OperationType.ADD, 
userName, metalake, e);
     }
   }
 
diff --git 
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestGroupOperations.java
 
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestGroupOperations.java
index d35faee879..1bcf6deaa5 100644
--- 
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestGroupOperations.java
+++ 
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestGroupOperations.java
@@ -213,6 +213,19 @@ public class TestGroupOperations extends 
BaseOperationsTest {
     Assertions.assertEquals(RuntimeException.class.getSimpleName(), 
errorResponse2.getType());
   }
 
+  @Test
+  public void testAddGroupWithNullRequestBodyDoesNotExposeNpe() {
+    Response resp =
+        target("/metalakes/metalake1/groups")
+            .request(MediaType.APPLICATION_JSON_TYPE)
+            .accept("application/vnd.gravitino.v1+json")
+            .post(Entity.entity("null", MediaType.APPLICATION_JSON_TYPE));
+
+    Assertions.assertEquals(Status.INTERNAL_SERVER_ERROR.getStatusCode(), 
resp.getStatus());
+    ErrorResponse error = resp.readEntity(ErrorResponse.class);
+    Assertions.assertNotEquals(NullPointerException.class.getSimpleName(), 
error.getType());
+  }
+
   @Test
   public void testAddGroupWithExternalId() throws IOException {
     GroupAddRequest req = new GroupAddRequest("group1", "ext-group-1");

Reply via email to