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 391493c317 [#12769] fix(server): handle null request bodies in 
createView (#12770)
391493c317 is described below

commit 391493c317bafcb6aff2499fdce8847f1bd9a6e2
Author: mchades <[email protected]>
AuthorDate: Tue Sep 1 18:32:33 2026 +0800

    [#12769] fix(server): handle null request bodies in createView (#12770)
    
    ### What changes were proposed in this pull request?
    
    - Guard `ViewOperations.createView` against a null request before
    accessing any
      request fields or invoking `request.validate()`.
    - Route the validation failure through the existing view exception
    handler so
      the endpoint returns a structured HTTP 400 response.
    - Cache the view name after the null guard and reuse it for logging,
    identifier
      construction, and catch-path error handling.
    - Add `TestViewOperations` coverage for an empty/null request entity.
    - Verify that malformed JSON continues to use the existing JSON
    exception
      mappers and returns HTTP 400.
    
    ### Why are the changes needed?
    
    An empty create-view request currently causes
    `ViewOperations.createView` to
    dereference `request` before null validation. This produces an unhandled
    HTTP
    500 response with an empty body instead of the structured client-error
    response
    used by other REST endpoints.
    
    The change follows the existing null-request handling pattern in
    `MetalakeOperations.createMetalake`.
    
    Fix: #12769
    
    ### Does this PR introduce _any_ user-facing change?
    
    Yes. A create-view request with an empty or null body now returns a
    structured
    HTTP 400 response instead of an empty HTTP 500 response.
    
    There are no API schema or configuration changes. Valid requests and
    malformed
    JSON handling are unchanged.
    
    ### How was this patch tested?
    
    Before the fix, the null-request regression test failed with:
    
    ```text
    expected: <400> but was: <500>
    ```
    
    The malformed-JSON regression test passed independently, confirming that
    the
    existing mapper behavior was not the cause.
    
    After the fix:
    
    ```shell
    ./gradlew :server:test \
      --tests org.apache.gravitino.server.web.rest.TestViewOperations \
      -PskipITs --no-daemon
    ```
    
    Result: 9 tests passed, 0 failures, 0 errors.
    
    Additional checks:
    
    ```shell
    ./gradlew :server:spotlessCheck --no-daemon
    git diff --check
    ```
    
    Both checks passed.
---
 .../server/web/rest/CatalogOperations.java         |  8 ++++
 .../server/web/rest/FilesetOperations.java         |  8 ++++
 .../server/web/rest/FunctionOperations.java        |  8 ++++
 .../gravitino/server/web/rest/JobOperations.java   |  7 ++++
 .../server/web/rest/MetalakeOperations.java        |  7 ++++
 .../gravitino/server/web/rest/ModelOperations.java | 29 +++++++++++++
 .../server/web/rest/PolicyOperations.java          |  7 ++++
 .../server/web/rest/SchemaOperations.java          |  8 ++++
 .../gravitino/server/web/rest/TableOperations.java |  8 ++++
 .../gravitino/server/web/rest/TagOperations.java   |  7 ++++
 .../gravitino/server/web/rest/TopicOperations.java |  8 ++++
 .../gravitino/server/web/rest/ViewOperations.java  | 29 +++++++++----
 .../server/web/rest/BaseOperationsTest.java        | 13 ++++++
 .../server/web/rest/TestCatalogOperations.java     | 11 +++++
 .../server/web/rest/TestFilesetOperations.java     | 11 +++++
 .../server/web/rest/TestFunctionOperations.java    | 12 ++++++
 .../server/web/rest/TestJobOperations.java         | 12 ++++++
 .../server/web/rest/TestMetalakeOperations.java    | 11 +++++
 .../server/web/rest/TestModelOperations.java       | 40 ++++++++++++++++++
 .../server/web/rest/TestPolicyOperations.java      | 12 ++++++
 .../server/web/rest/TestSchemaOperations.java      | 12 ++++++
 .../server/web/rest/TestTableOperations.java       | 11 +++++
 .../server/web/rest/TestTagOperations.java         | 12 ++++++
 .../server/web/rest/TestTopicOperations.java       | 11 +++++
 .../server/web/rest/TestViewOperations.java        | 49 ++++++++++++++++++++++
 25 files changed, 344 insertions(+), 7 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 e7a1aedb0d..4b5b354f16 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
@@ -331,6 +331,14 @@ public class CatalogOperations {
           String catalogName,
       CatalogUpdatesRequest request) {
     LOG.info("Received alter catalog request for catalog: {}.{}", 
metalakeName, catalogName);
+    if (request == null) {
+      return ExceptionHandlers.handleCatalogException(
+          OperationType.ALTER,
+          catalogName,
+          metalakeName,
+          new IllegalArgumentException("Request body cannot be null"));
+    }
+
     try {
       return Utils.doAs(
           httpRequest,
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 11f1d6f18c..40ba231c54 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
@@ -289,6 +289,14 @@ public class FilesetOperations {
       @PathParam("fileset") @AuthorizationMetadata(type = 
Entity.EntityType.FILESET) String fileset,
       FilesetUpdatesRequest request) {
     LOG.info("Received alter fileset request: {}.{}.{}.{}", metalake, catalog, 
schema, fileset);
+    if (request == null) {
+      return ExceptionHandlers.handleFilesetException(
+          OperationType.ALTER,
+          fileset,
+          schema,
+          new IllegalArgumentException("Request body cannot be null"));
+    }
+
     try {
       return Utils.doAs(
           httpRequest,
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 7e3fcd8a30..085f09d4ad 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
@@ -249,6 +249,14 @@ public class FunctionOperations {
           String function,
       FunctionUpdatesRequest request) {
     LOG.info("Received alter function request: {}.{}.{}.{}", metalake, 
catalog, schema, function);
+    if (request == null) {
+      return ExceptionHandlers.handleFunctionException(
+          OperationType.ALTER,
+          function,
+          schema,
+          new IllegalArgumentException("Request body cannot be null"));
+    }
+
     try {
       return Utils.doAs(
           httpRequest,
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 d339734c04..0df9b9bf74 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
@@ -261,6 +261,13 @@ public class JobOperations {
       JobTemplateUpdatesRequest request) {
     LOG.info(
         "Received request to alter job template: {} in metalake: {}", 
jobTemplateName, metalake);
+    if (request == null) {
+      return ExceptionHandlers.handleJobTemplateException(
+          OperationType.ALTER,
+          jobTemplateName,
+          metalake,
+          new IllegalArgumentException("Request body cannot be null"));
+    }
 
     try {
       return Utils.doAs(
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 a42e0a9678..8d511a01dd 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
@@ -218,6 +218,13 @@ public class MetalakeOperations {
           String metalakeName,
       MetalakeUpdatesRequest updatesRequest) {
     LOG.info("Received alter metalake request for metalake: {}", metalakeName);
+    if (updatesRequest == null) {
+      return ExceptionHandlers.handleMetalakeException(
+          OperationType.ALTER,
+          metalakeName,
+          new IllegalArgumentException("Request body cannot be null"));
+    }
+
     try {
       return Utils.doAs(
           httpRequest,
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 1c51fc380d..7c0bda83d0 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
@@ -414,6 +414,13 @@ public class ModelOperations {
       ModelVersionLinkRequest request) {
     LOG.info("Received link model version request: {}.{}.{}.{}", metalake, 
catalog, schema, model);
     NameIdentifier modelId = NameIdentifierUtil.ofModel(metalake, catalog, 
schema, model);
+    if (request == null) {
+      return ExceptionHandlers.handleModelException(
+          OperationType.LINK,
+          model,
+          schema,
+          new IllegalArgumentException("Request body cannot be null"));
+    }
 
     try {
       return Utils.doAs(
@@ -568,6 +575,13 @@ public class ModelOperations {
         schema,
         model,
         version);
+    if (request == null) {
+      return ExceptionHandlers.handleModelException(
+          OperationType.ALTER,
+          versionString(model, version),
+          schema,
+          new IllegalArgumentException("Request body cannot be null"));
+    }
 
     try {
       NameIdentifier modelId = NameIdentifierUtil.ofModel(metalake, catalog, 
schema, model);
@@ -622,6 +636,13 @@ public class ModelOperations {
         schema,
         model,
         alias);
+    if (request == null) {
+      return ExceptionHandlers.handleModelException(
+          OperationType.ALTER,
+          aliasString(model, alias),
+          schema,
+          new IllegalArgumentException("Request body cannot be null"));
+    }
 
     try {
       NameIdentifier modelId = NameIdentifierUtil.ofModel(metalake, catalog, 
schema, model);
@@ -668,6 +689,14 @@ public class ModelOperations {
       @PathParam("model") @AuthorizationMetadata(type = 
Entity.EntityType.MODEL) String model,
       ModelUpdatesRequest request) {
     LOG.info("Received alter model request: {}.{}.{}.{}", metalake, catalog, 
schema, model);
+    if (request == null) {
+      return ExceptionHandlers.handleModelException(
+          OperationType.ALTER,
+          model,
+          schema,
+          new IllegalArgumentException("Request body cannot be null"));
+    }
+
     try {
       return Utils.doAs(
           httpRequest,
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 d3a8243c98..1b4102ec1b 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
@@ -205,6 +205,13 @@ public class PolicyOperations {
       @PathParam("policy") @AuthorizationMetadata(type = 
Entity.EntityType.POLICY) String name,
       PolicyUpdatesRequest request) {
     LOG.info("Received alter policy request for policy: {} under metalake: 
{}", name, metalake);
+    if (request == null) {
+      return ExceptionHandlers.handlePolicyException(
+          OperationType.ALTER,
+          name,
+          metalake,
+          new IllegalArgumentException("Request body cannot be null"));
+    }
 
     try {
       return Utils.doAs(
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 6541c7ff6a..8203568728 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
@@ -214,6 +214,14 @@ public class SchemaOperations {
       @PathParam("schema") @AuthorizationMetadata(type = 
Entity.EntityType.SCHEMA) String schema,
       SchemaUpdatesRequest request) {
     LOG.info("Received alter schema request: {}.{}.{}", metalake, catalog, 
schema);
+    if (request == null) {
+      return ExceptionHandlers.handleSchemaException(
+          OperationType.ALTER,
+          schema,
+          catalog,
+          new IllegalArgumentException("Request body cannot be null"));
+    }
+
     try {
       return Utils.doAs(
           httpRequest,
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 aa83ad78f7..2525f08f65 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
@@ -213,6 +213,14 @@ public class TableOperations {
       @PathParam("table") @AuthorizationMetadata(type = 
Entity.EntityType.TABLE) String table,
       TableUpdatesRequest request) {
     LOG.info("Received alter table request: {}.{}.{}.{}", metalake, catalog, 
schema, table);
+    if (request == null) {
+      return ExceptionHandlers.handleTableException(
+          OperationType.ALTER,
+          table,
+          schema,
+          new IllegalArgumentException("Request body cannot be null"));
+    }
+
     try {
       return Utils.doAs(
           httpRequest,
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 4a2fa3554d..12d2866214 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
@@ -214,6 +214,13 @@ public class TagOperations {
       @PathParam("tag") @AuthorizationMetadata(type = Entity.EntityType.TAG) 
String name,
       TagUpdatesRequest request) {
     LOG.info("Received alter tag request for tag: {} under metalake: {}", 
name, metalake);
+    if (request == null) {
+      return ExceptionHandlers.handleTagException(
+          OperationType.ALTER,
+          name,
+          metalake,
+          new IllegalArgumentException("Request body cannot be null"));
+    }
 
     try {
       return Utils.doAs(
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 d031f267a4..cbf59711b0 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
@@ -208,6 +208,14 @@ public class TopicOperations {
       @PathParam("topic") @AuthorizationMetadata(type = 
Entity.EntityType.TOPIC) String topic,
       TopicUpdatesRequest request) {
     LOG.info("Received alter topic request: {}.{}.{}.{}", metalake, catalog, 
schema, topic);
+    if (request == null) {
+      return ExceptionHandlers.handleTopicException(
+          OperationType.ALTER,
+          topic,
+          schema,
+          new IllegalArgumentException("Request body cannot be null"));
+    }
+
     try {
       return Utils.doAs(
           httpRequest,
diff --git 
a/server/src/main/java/org/apache/gravitino/server/web/rest/ViewOperations.java 
b/server/src/main/java/org/apache/gravitino/server/web/rest/ViewOperations.java
index 7d2cfd11dd..77e5fbc938 100644
--- 
a/server/src/main/java/org/apache/gravitino/server/web/rest/ViewOperations.java
+++ 
b/server/src/main/java/org/apache/gravitino/server/web/rest/ViewOperations.java
@@ -99,15 +99,23 @@ public class ViewOperations {
       @PathParam("catalog") String catalog,
       @PathParam("schema") String schema,
       ViewCreateRequest request) {
-    LOG.info(
-        "Received create view request: {}.{}.{}.{}", metalake, catalog, 
schema, request.getName());
+    if (request == null) {
+      LOG.warn("Received create view request with null request body");
+      return ExceptionHandlers.handleViewException(
+          OperationType.CREATE,
+          "",
+          schema,
+          new IllegalArgumentException("Request body cannot be null"));
+    }
+
+    String viewName = request.getName();
+    LOG.info("Received create view request: {}.{}.{}.{}", metalake, catalog, 
schema, viewName);
     try {
       return Utils.doAs(
           httpRequest,
           () -> {
             request.validate();
-            NameIdentifier ident =
-                NameIdentifierUtil.ofView(metalake, catalog, schema, 
request.getName());
+            NameIdentifier ident = NameIdentifierUtil.ofView(metalake, 
catalog, schema, viewName);
 
             View view =
                 dispatcher.createView(
@@ -119,13 +127,12 @@ public class ViewOperations {
                     request.getDefaultSchema(),
                     request.getProperties());
             Response response = Utils.ok(new 
ViewResponse(DTOConverters.toDTO(view)));
-            LOG.info("View created: {}.{}.{}.{}", metalake, catalog, schema, 
request.getName());
+            LOG.info("View created: {}.{}.{}.{}", metalake, catalog, schema, 
viewName);
             return response;
           });
 
     } catch (Exception e) {
-      return ExceptionHandlers.handleViewException(
-          OperationType.CREATE, request.getName(), schema, e);
+      return ExceptionHandlers.handleViewException(OperationType.CREATE, 
viewName, schema, e);
     }
   }
 
@@ -167,6 +174,14 @@ public class ViewOperations {
       @PathParam("view") String view,
       ViewUpdatesRequest request) {
     LOG.info("Received alter view request: {}.{}.{}.{}", metalake, catalog, 
schema, view);
+    if (request == null) {
+      return ExceptionHandlers.handleViewException(
+          OperationType.ALTER,
+          view,
+          schema,
+          new IllegalArgumentException("Request body cannot be null"));
+    }
+
     try {
       return Utils.doAs(
           httpRequest,
diff --git 
a/server/src/test/java/org/apache/gravitino/server/web/rest/BaseOperationsTest.java
 
b/server/src/test/java/org/apache/gravitino/server/web/rest/BaseOperationsTest.java
index 97933126d6..b603ae5c58 100644
--- 
a/server/src/test/java/org/apache/gravitino/server/web/rest/BaseOperationsTest.java
+++ 
b/server/src/test/java/org/apache/gravitino/server/web/rest/BaseOperationsTest.java
@@ -18,10 +18,14 @@
 package org.apache.gravitino.server.web.rest;
 
 import java.io.IOException;
+import javax.ws.rs.core.Response;
+import org.apache.gravitino.dto.responses.ErrorConstants;
+import org.apache.gravitino.dto.responses.ErrorResponse;
 import org.apache.gravitino.server.ServerConfig;
 import org.apache.gravitino.server.authorization.GravitinoAuthorizerProvider;
 import org.glassfish.jersey.test.JerseyTest;
 import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeAll;
 
 public abstract class BaseOperationsTest extends JerseyTest {
@@ -35,4 +39,13 @@ public abstract class BaseOperationsTest extends JerseyTest {
   public static void stop() throws IOException {
     GravitinoAuthorizerProvider.getInstance().close();
   }
+
+  static void assertNullRequestBodyRejected(Response response) {
+    Assertions.assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), 
response.getStatus());
+    ErrorResponse errorResponse = response.readEntity(ErrorResponse.class);
+    Assertions.assertEquals(ErrorConstants.ILLEGAL_ARGUMENTS_CODE, 
errorResponse.getCode());
+    Assertions.assertEquals(
+        IllegalArgumentException.class.getSimpleName(), 
errorResponse.getType());
+    Assertions.assertTrue(errorResponse.getMessage().contains("Request body 
cannot be null"));
+  }
 }
diff --git 
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestCatalogOperations.java
 
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestCatalogOperations.java
index 8f0d7e98d5..b56d7c1378 100644
--- 
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestCatalogOperations.java
+++ 
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestCatalogOperations.java
@@ -491,6 +491,17 @@ public class TestCatalogOperations extends 
BaseOperationsTest {
     Assertions.assertEquals(RuntimeException.class.getSimpleName(), 
errorResponse2.getType());
   }
 
+  @Test
+  public void testAlterCatalogWithNullRequest() {
+    Response resp =
+        target("/metalakes/metalake1/catalogs/catalog1")
+            .request(MediaType.APPLICATION_JSON_TYPE)
+            .accept("application/vnd.gravitino.v1+json")
+            .put(Entity.entity(new byte[0], MediaType.APPLICATION_JSON_TYPE));
+
+    assertNullRequestBodyRejected(resp);
+  }
+
   @Test
   public void testAlterCatalog() {
     TestCatalog catalog = buildCatalog("metalake1", "catalog2");
diff --git 
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestFilesetOperations.java
 
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestFilesetOperations.java
index ca77641129..76f7658c31 100644
--- 
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestFilesetOperations.java
+++ 
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestFilesetOperations.java
@@ -397,6 +397,17 @@ public class TestFilesetOperations extends 
BaseOperationsTest {
     Assertions.assertEquals(RuntimeException.class.getSimpleName(), 
errorResp4.getType());
   }
 
+  @Test
+  public void testAlterFilesetWithNullRequest() {
+    Response resp =
+        target(filesetPath(metalake, catalog, schema) + "fileset1")
+            .request(MediaType.APPLICATION_JSON_TYPE)
+            .accept("application/vnd.gravitino.v1+json")
+            .put(Entity.entity(new byte[0], MediaType.APPLICATION_JSON_TYPE));
+
+    assertNullRequestBodyRejected(resp);
+  }
+
   @Test
   public void testRenameFileset() {
     FilesetUpdateRequest req = new 
FilesetUpdateRequest.RenameFilesetRequest("new name");
diff --git 
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestFunctionOperations.java
 
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestFunctionOperations.java
index 65cf114ab1..5aad775be8 100644
--- 
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestFunctionOperations.java
+++ 
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestFunctionOperations.java
@@ -407,6 +407,18 @@ public class TestFunctionOperations extends 
BaseOperationsTest {
     Assertions.assertEquals(FunctionType.TABLE, 
funcResp.getFunction().functionType());
   }
 
+  @Test
+  public void testAlterFunctionWithNullRequest() {
+    Response resp =
+        target(functionPath())
+            .path("func1")
+            .request(MediaType.APPLICATION_JSON_TYPE)
+            .accept("application/vnd.gravitino.v1+json")
+            .put(Entity.entity(new byte[0], MediaType.APPLICATION_JSON_TYPE));
+
+    assertNullRequestBodyRejected(resp);
+  }
+
   @Test
   public void testAlterFunction() {
     NameIdentifier funcId = NameIdentifierUtil.ofFunction(metalake, catalog, 
schema, "func1");
diff --git 
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestJobOperations.java
 
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestJobOperations.java
index 130fae9434..fe19825831 100644
--- 
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestJobOperations.java
+++ 
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestJobOperations.java
@@ -515,6 +515,18 @@ public class TestJobOperations extends JerseyTest {
     Assertions.assertEquals(InUseException.class.getSimpleName(), 
errorResp4.getType());
   }
 
+  @Test
+  public void testAlterJobTemplateWithNullRequest() {
+    Response resp =
+        target(jobTemplatePath())
+            .path("shell_template_1")
+            .request(APPLICATION_JSON_TYPE)
+            .accept("application/vnd.gravitino.v1+json")
+            .put(Entity.entity(new byte[0], APPLICATION_JSON_TYPE));
+
+    BaseOperationsTest.assertNullRequestBodyRejected(resp);
+  }
+
   @Test
   public void testAlterJobTemplate() {
     String templateName = "shell_template_1";
diff --git 
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestMetalakeOperations.java
 
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestMetalakeOperations.java
index 0cbf2594c8..ae7eb39133 100644
--- 
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestMetalakeOperations.java
+++ 
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestMetalakeOperations.java
@@ -252,6 +252,17 @@ public class TestMetalakeOperations extends 
BaseOperationsTest {
     Assertions.assertTrue(errorResponse.getMessage().contains("Request body 
cannot be null"));
   }
 
+  @Test
+  public void testAlterMetalakeWithNullRequest() {
+    Response resp =
+        target("/metalakes/test")
+            .request(MediaType.APPLICATION_JSON_TYPE)
+            .accept("application/vnd.gravitino.v1+json")
+            .put(Entity.entity(new byte[0], MediaType.APPLICATION_JSON_TYPE));
+
+    assertNullRequestBodyRejected(resp);
+  }
+
   @Test
   public void testLoadMetalake() {
     String metalakeName = "test";
diff --git 
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestModelOperations.java
 
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestModelOperations.java
index 12c1695768..5f26d8e9d1 100644
--- 
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestModelOperations.java
+++ 
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestModelOperations.java
@@ -270,6 +270,46 @@ public class TestModelOperations extends 
BaseOperationsTest {
     Assertions.assertEquals(RuntimeException.class.getSimpleName(), 
errorResp1.getType());
   }
 
+  @Test
+  public void testModelLinkAndAlterOperationsWithNullRequests() {
+    Response linkVersionResponse =
+        target(modelPath())
+            .path("model1")
+            .path("versions")
+            .request(MediaType.APPLICATION_JSON_TYPE)
+            .accept("application/vnd.gravitino.v1+json")
+            .post(Entity.entity(null, MediaType.APPLICATION_JSON_TYPE));
+    assertNullRequestBodyRejected(linkVersionResponse);
+
+    Response alterModelResponse =
+        target(modelPath())
+            .path("model1")
+            .request(MediaType.APPLICATION_JSON_TYPE)
+            .accept("application/vnd.gravitino.v1+json")
+            .put(Entity.entity(new byte[0], MediaType.APPLICATION_JSON_TYPE));
+    assertNullRequestBodyRejected(alterModelResponse);
+
+    Response alterVersionResponse =
+        target(modelPath())
+            .path("model1")
+            .path("versions")
+            .path("0")
+            .request(MediaType.APPLICATION_JSON_TYPE)
+            .accept("application/vnd.gravitino.v1+json")
+            .put(Entity.entity(new byte[0], MediaType.APPLICATION_JSON_TYPE));
+    assertNullRequestBodyRejected(alterVersionResponse);
+
+    Response alterVersionByAliasResponse =
+        target(modelPath())
+            .path("model1")
+            .path("aliases")
+            .path("alias1")
+            .request(MediaType.APPLICATION_JSON_TYPE)
+            .accept("application/vnd.gravitino.v1+json")
+            .put(Entity.entity(new byte[0], MediaType.APPLICATION_JSON_TYPE));
+    assertNullRequestBodyRejected(alterVersionByAliasResponse);
+  }
+
   @Test
   public void testRegisterModel() {
     NameIdentifier modelId = NameIdentifierUtil.ofModel(metalake, catalog, 
schema, "model1");
diff --git 
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestPolicyOperations.java
 
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestPolicyOperations.java
index af8056b666..382e1f9d8b 100644
--- 
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestPolicyOperations.java
+++ 
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestPolicyOperations.java
@@ -504,6 +504,18 @@ public class TestPolicyOperations extends 
BaseOperationsTest {
     Assertions.assertEquals(RuntimeException.class.getSimpleName(), 
errorResp1.getType());
   }
 
+  @Test
+  public void testAlterPolicyWithNullRequest() {
+    Response resp =
+        target(policyPath(metalake))
+            .path("policy1")
+            .request(MediaType.APPLICATION_JSON_TYPE)
+            .accept("application/vnd.gravitino.v1+json")
+            .put(Entity.entity(new byte[0], MediaType.APPLICATION_JSON_TYPE));
+
+    assertNullRequestBodyRejected(resp);
+  }
+
   @Test
   public void testAlterPolicy() {
     ImmutableMap<String, Object> contentFields = 
ImmutableMap.of("target_file_size_bytes", 1000);
diff --git 
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestSchemaOperations.java
 
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestSchemaOperations.java
index 08f2fb2be9..1a9ffc43ad 100644
--- 
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestSchemaOperations.java
+++ 
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestSchemaOperations.java
@@ -38,6 +38,7 @@ import java.io.IOException;
 import java.time.Instant;
 import java.util.Map;
 import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.client.Entity;
 import javax.ws.rs.core.Application;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
@@ -352,6 +353,17 @@ public class TestSchemaOperations extends 
BaseOperationsTest {
     Assertions.assertEquals(RuntimeException.class.getSimpleName(), 
errorResp2.getType());
   }
 
+  @Test
+  public void testAlterSchemaWithNullRequest() {
+    Response resp =
+        target("/metalakes/" + metalake + "/catalogs/" + catalog + 
"/schemas/schema1")
+            .request(MediaType.APPLICATION_JSON_TYPE)
+            .accept("application/vnd.gravitino.v1+json")
+            .put(Entity.entity(new byte[0], MediaType.APPLICATION_JSON_TYPE));
+
+    assertNullRequestBodyRejected(resp);
+  }
+
   @Test
   public void testAlterSchema() {
     SchemaUpdateRequest setReq = new 
SchemaUpdateRequest.SetSchemaPropertyRequest("key2", "value2");
diff --git 
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestTableOperations.java
 
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestTableOperations.java
index e2b12910a8..9c41650d48 100644
--- 
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestTableOperations.java
+++ 
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestTableOperations.java
@@ -567,6 +567,17 @@ public class TestTableOperations extends 
BaseOperationsTest {
     Assertions.assertEquals(RuntimeException.class.getSimpleName(), 
errorResp2.getType());
   }
 
+  @Test
+  public void testAlterTableWithNullRequest() {
+    Response resp =
+        target(tablePath(metalake, catalog, schema) + "table1")
+            .request(MediaType.APPLICATION_JSON_TYPE)
+            .accept("application/vnd.gravitino.v1+json")
+            .put(Entity.entity(new byte[0], MediaType.APPLICATION_JSON_TYPE));
+
+    assertNullRequestBodyRejected(resp);
+  }
+
   @Test
   public void testRenameTable() {
     TableUpdateRequest.RenameTableRequest req = new 
TableUpdateRequest.RenameTableRequest("table2");
diff --git 
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestTagOperations.java
 
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestTagOperations.java
index 6127bb77e5..090e49d78f 100644
--- 
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestTagOperations.java
+++ 
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestTagOperations.java
@@ -401,6 +401,18 @@ public class TestTagOperations extends BaseOperationsTest {
     Assertions.assertEquals(RuntimeException.class.getSimpleName(), 
errorResp1.getType());
   }
 
+  @Test
+  public void testAlterTagWithNullRequest() {
+    Response resp =
+        target(tagPath(metalake))
+            .path("tag1")
+            .request(MediaType.APPLICATION_JSON_TYPE)
+            .accept("application/vnd.gravitino.v1+json")
+            .put(Entity.entity(new byte[0], MediaType.APPLICATION_JSON_TYPE));
+
+    assertNullRequestBodyRejected(resp);
+  }
+
   @Test
   public void testAlterTag() {
     TagEntity newTag =
diff --git 
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestTopicOperations.java
 
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestTopicOperations.java
index f74e49feb4..67c9cdbbb4 100644
--- 
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestTopicOperations.java
+++ 
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestTopicOperations.java
@@ -303,6 +303,17 @@ public class TestTopicOperations extends 
BaseOperationsTest {
     Assertions.assertEquals(RuntimeException.class.getSimpleName(), 
errorResp3.getType());
   }
 
+  @Test
+  public void testAlterTopicWithNullRequest() {
+    Response resp =
+        target(topicPath(metalake, catalog, schema) + "/topic1")
+            .request(MediaType.APPLICATION_JSON_TYPE)
+            .accept("application/vnd.gravitino.v1+json")
+            .put(Entity.entity(new byte[0], MediaType.APPLICATION_JSON_TYPE));
+
+    assertNullRequestBodyRejected(resp);
+  }
+
   @Test
   public void testSetTopicProperties() {
     TopicUpdateRequest req = new 
TopicUpdateRequest.SetTopicPropertyRequest("key1", "value1");
diff --git 
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestViewOperations.java
 
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestViewOperations.java
index 2bd2c0df7e..c82253c497 100644
--- 
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestViewOperations.java
+++ 
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestViewOperations.java
@@ -65,6 +65,9 @@ import org.apache.gravitino.rel.SQLRepresentation;
 import org.apache.gravitino.rel.View;
 import org.apache.gravitino.rel.ViewChange;
 import org.apache.gravitino.rest.RESTUtils;
+import org.apache.gravitino.server.web.mapper.JsonMappingExceptionMapper;
+import org.apache.gravitino.server.web.mapper.JsonParseExceptionMapper;
+import org.apache.gravitino.server.web.mapper.JsonProcessingExceptionMapper;
 import org.glassfish.jersey.internal.inject.AbstractBinder;
 import org.glassfish.jersey.server.ResourceConfig;
 import org.glassfish.jersey.test.TestProperties;
@@ -123,6 +126,9 @@ public class TestViewOperations extends BaseOperationsTest {
                 .to(HttpServletRequest.class);
           }
         });
+    resourceConfig.register(JsonProcessingExceptionMapper.class);
+    resourceConfig.register(JsonParseExceptionMapper.class);
+    resourceConfig.register(JsonMappingExceptionMapper.class);
 
     return resourceConfig;
   }
@@ -296,6 +302,49 @@ public class TestViewOperations extends BaseOperationsTest 
{
     Assertions.assertEquals(ErrorConstants.ILLEGAL_ARGUMENTS_CODE, 
errorResp3.getCode());
   }
 
+  @Test
+  public void testCreateViewWithNullRequest() {
+    Response resp =
+        target(viewPath(metalake, catalog, schema))
+            .request(MediaType.APPLICATION_JSON_TYPE)
+            .accept(VND_V1_JSON)
+            .post(Entity.entity(null, VND_V1_JSON));
+
+    Assertions.assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), 
resp.getStatus());
+    ErrorResponse errorResponse = resp.readEntity(ErrorResponse.class);
+    Assertions.assertEquals(ErrorConstants.ILLEGAL_ARGUMENTS_CODE, 
errorResponse.getCode());
+    Assertions.assertEquals(
+        IllegalArgumentException.class.getSimpleName(), 
errorResponse.getType());
+    Assertions.assertTrue(errorResponse.getMessage().contains("Request body 
cannot be null"));
+  }
+
+  @Test
+  public void testCreateViewWithMalformedJson() {
+    Response resp =
+        target(viewPath(metalake, catalog, schema))
+            .request(MediaType.APPLICATION_JSON_TYPE)
+            .accept(VND_V1_JSON)
+            .post(Entity.entity("{", VND_V1_JSON));
+
+    Assertions.assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), 
resp.getStatus());
+    ErrorResponse errorResponse = resp.readEntity(ErrorResponse.class);
+    Assertions.assertEquals(ErrorConstants.ILLEGAL_ARGUMENTS_CODE, 
errorResponse.getCode());
+    Assertions.assertEquals(
+        IllegalArgumentException.class.getSimpleName(), 
errorResponse.getType());
+    Assertions.assertTrue(errorResponse.getMessage().contains("Malformed json 
request"));
+  }
+
+  @Test
+  public void testAlterViewWithNullRequest() {
+    Response resp =
+        target(viewPath(metalake, catalog, schema) + "/view1")
+            .request(MediaType.APPLICATION_JSON_TYPE)
+            .accept(VND_V1_JSON)
+            .put(Entity.entity(new byte[0], VND_V1_JSON));
+
+    assertNullRequestBodyRejected(resp);
+  }
+
   @Test
   public void testRenameView() {
     ViewUpdateRequest req = new ViewUpdateRequest.RenameViewRequest("view2");

Reply via email to