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

jerryshao pushed a commit to branch branch-1.3
in repository https://gitbox.apache.org/repos/asf/gravitino.git


The following commit(s) were added to refs/heads/branch-1.3 by this push:
     new 7bec3c215b [Cherry-pick to branch-1.3] [#12783] fix(server): return 
JSON errors for the whole pre-resource-method WebApplicationException family 
(#12878) (#12910)
7bec3c215b is described below

commit 7bec3c215b2af003434fd674e96922f73fb4d2e2
Author: github-actions[bot] 
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Fri Sep 4 15:54:57 2026 +0800

    [Cherry-pick to branch-1.3] [#12783] fix(server): return JSON errors for 
the whole pre-resource-method WebApplicationException family (#12878) (#12910)
    
    **Cherry-pick Information:**
    - Original commit: deb1e2d21f007535e21d67fd7e5f8e8f09240f3c
    - Target branch: `branch-1.3`
    - Status: ⚠️ **Has conflicts - manual resolution required**
    
    **Do not merge** until conflict markers are resolved and the
    `cherry-pick-conflict` label is removed.
    
    Please review and resolve the conflicts before merging.
    
    ---------
    
    Co-authored-by: Jerry Shao <[email protected]>
    Co-authored-by: Claude Sonnet 5 <[email protected]>
    Co-authored-by: Copilot Autofix powered by AI 
<[email protected]>
    Co-authored-by: Jerry Shao <[email protected]>
---
 .../integration/test/JsonErrorHandlerIT.java       | 64 +++++++++++++-----
 .../apache/gravitino/server/GravitinoServer.java   |  2 +
 .../gravitino/server/web/VersioningFilter.java     | 12 +++-
 .../web/mapper/WebApplicationExceptionMapper.java  | 77 ++++++++++++++++++++++
 .../gravitino/server/web/TestVersioningFilter.java | 38 +++++++++--
 .../mapper/TestWebApplicationExceptionMapper.java  | 67 +++++++++++++++++++
 6 files changed, 236 insertions(+), 24 deletions(-)

diff --git 
a/clients/client-java/src/test/java/org/apache/gravitino/client/integration/test/JsonErrorHandlerIT.java
 
b/clients/client-java/src/test/java/org/apache/gravitino/client/integration/test/JsonErrorHandlerIT.java
index 797f9eda3c..c3841ae975 100644
--- 
a/clients/client-java/src/test/java/org/apache/gravitino/client/integration/test/JsonErrorHandlerIT.java
+++ 
b/clients/client-java/src/test/java/org/apache/gravitino/client/integration/test/JsonErrorHandlerIT.java
@@ -30,13 +30,16 @@ import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
 /**
- * Integration test verifying that a malformed typed path parameter on the 
metadata API (e.g. a
- * non-numeric model version) returns the same structured JSON {@link 
ErrorResponse} used by every
- * other error on the API, instead of Jetty's default HTML error page.
+ * Integration test verifying that requests rejected before reaching a 
resource method (malformed
+ * typed parameters, unmatched routes, wrong HTTP methods, an unsupported API 
version) return the
+ * same structured JSON {@link ErrorResponse} used by every other error on the 
API, instead of
+ * Jetty's default HTML error page.
  *
- * <p>Jersey fails to convert the path segment into the resource method's 
typed {@code @PathParam}
- * before any resource method runs, so the metalake/catalog/schema/model in 
the URL need not
- * actually exist for this failure to occur.
+ * <p>Most of these cases are handled by Jersey itself — converting a typed
+ * {@code @PathParam}/{@code @QueryParam}, matching a route, matching an HTTP 
method to a resource —
+ * before any resource method runs. The unsupported-API-version case is 
rejected earlier still, by
+ * {@code VersioningFilter} before the request ever reaches Jersey. Either 
way, the
+ * metalake/catalog/schema/model in the URL need not actually exist for these 
failures to occur.
  */
 public class JsonErrorHandlerIT extends BaseIT {
 
@@ -45,42 +48,69 @@ public class JsonErrorHandlerIT extends BaseIT {
   @Test
   public void testMalformedModelVersionReturnsJsonErrorBody() throws Exception 
{
     HttpResponse<String> response =
-        
sendGet("/api/metalakes/m/catalogs/c/schemas/s/models/mo/versions/abc");
+        sendRequest("GET", 
"/api/metalakes/m/catalogs/c/schemas/s/models/mo/versions/abc");
 
     Assertions.assertEquals(404, response.statusCode());
-    assertJsonNotFoundBody(response, "PathParamException");
+    assertJsonErrorBody(response, ErrorConstants.NOT_FOUND_CODE, 
"PathParamException");
   }
 
   @Test
   public void testMalformedModelVersionUriReturnsJsonErrorBody() throws 
Exception {
     HttpResponse<String> response =
-        
sendGet("/api/metalakes/m/catalogs/c/schemas/s/models/mo/versions/abc/uri");
+        sendRequest("GET", 
"/api/metalakes/m/catalogs/c/schemas/s/models/mo/versions/abc/uri");
 
     Assertions.assertEquals(404, response.statusCode());
-    assertJsonNotFoundBody(response, "PathParamException");
+    assertJsonErrorBody(response, ErrorConstants.NOT_FOUND_CODE, 
"PathParamException");
   }
 
   @Test
   public void testUnknownApiRouteStillReturnsJsonErrorBody() throws Exception {
     // A route that Jersey cannot match at all is a different failure (no 
@PathParam conversion
     // is even attempted), but it must be covered by the same fix.
-    HttpResponse<String> response = sendGet("/api/v99/nonexistent/route");
+    HttpResponse<String> response = sendRequest("GET", 
"/api/v99/nonexistent/route");
 
     Assertions.assertEquals(404, response.statusCode());
-    assertJsonNotFoundBody(response, "NotFoundException");
+    assertJsonErrorBody(response, ErrorConstants.NOT_FOUND_CODE, 
"NotFoundException");
   }
 
-  private HttpResponse<String> sendGet(String path) throws Exception {
+  @Test
+  public void testWrongHttpMethodReturnsJsonErrorBody() throws Exception {
+    // /api/version only supports GET; POSTing to it never reaches a resource 
method either.
+    HttpResponse<String> response = sendRequest("POST", "/api/version");
+
+    Assertions.assertEquals(405, response.statusCode());
+    assertJsonErrorBody(
+        response, ErrorConstants.UNSUPPORTED_OPERATION_CODE, 
"UnsupportedOperationException");
+  }
+
+  @Test
+  public void testUnsupportedApiVersionReturnsJsonErrorBody() throws Exception 
{
+    // VersioningFilter rejects an unrecognized API version before the request 
ever reaches
+    // Jersey, so this is not covered by any JAX-RS ExceptionMapper.
     HttpRequest request =
         HttpRequest.newBuilder()
-            .uri(new URI("http://localhost:"; + getGravitinoServerPort() + 
path))
+            .uri(new URI("http://localhost:"; + getGravitinoServerPort() + 
"/api/version"))
+            .header("Accept", "application/vnd.gravitino.v99+json")
             .GET()
             .build();
+    HttpResponse<String> response = httpClient.send(request, 
HttpResponse.BodyHandlers.ofString());
+
+    Assertions.assertEquals(406, response.statusCode());
+    assertJsonErrorBody(
+        response, ErrorConstants.ILLEGAL_ARGUMENTS_CODE, 
"IllegalArgumentException");
+  }
+
+  private HttpResponse<String> sendRequest(String method, String path) throws 
Exception {
+    HttpRequest request =
+        HttpRequest.newBuilder()
+            .uri(new URI("http://localhost:"; + getGravitinoServerPort() + 
path))
+            .method(method, HttpRequest.BodyPublishers.noBody())
+            .build();
     return httpClient.send(request, HttpResponse.BodyHandlers.ofString());
   }
 
-  private void assertJsonNotFoundBody(HttpResponse<String> response, String 
expectedType)
-      throws Exception {
+  private void assertJsonErrorBody(
+      HttpResponse<String> response, int expectedCode, String expectedType) 
throws Exception {
     String contentType = 
response.headers().firstValue("Content-Type").orElse("");
     Assertions.assertTrue(
         contentType.contains("application/json"),
@@ -90,7 +120,7 @@ public class JsonErrorHandlerIT extends BaseIT {
 
     ErrorResponse errorResponse =
         ObjectMapperProvider.objectMapper().readValue(response.body(), 
ErrorResponse.class);
-    Assertions.assertEquals(ErrorConstants.NOT_FOUND_CODE, 
errorResponse.getCode());
+    Assertions.assertEquals(expectedCode, errorResponse.getCode());
     Assertions.assertEquals(expectedType, errorResponse.getType());
     Assertions.assertFalse(errorResponse.getMessage().isEmpty());
   }
diff --git 
a/server/src/main/java/org/apache/gravitino/server/GravitinoServer.java 
b/server/src/main/java/org/apache/gravitino/server/GravitinoServer.java
index 31f820af32..831422ebc6 100644
--- a/server/src/main/java/org/apache/gravitino/server/GravitinoServer.java
+++ b/server/src/main/java/org/apache/gravitino/server/GravitinoServer.java
@@ -64,6 +64,7 @@ import 
org.apache.gravitino.server.web.mapper.JsonParseExceptionMapper;
 import org.apache.gravitino.server.web.mapper.JsonProcessingExceptionMapper;
 import org.apache.gravitino.server.web.mapper.NotFoundExceptionMapper;
 import org.apache.gravitino.server.web.mapper.ParamExceptionMapper;
+import org.apache.gravitino.server.web.mapper.WebApplicationExceptionMapper;
 import org.apache.gravitino.server.web.ui.WebUIFilter;
 import org.apache.gravitino.stats.StatisticDispatcher;
 import org.apache.gravitino.tag.TagDispatcher;
@@ -169,6 +170,7 @@ public class GravitinoServer extends ResourceConfig {
     register(JsonMappingExceptionMapper.class);
     register(ParamExceptionMapper.class);
     register(NotFoundExceptionMapper.class);
+    register(WebApplicationExceptionMapper.class);
     register(ObjectMapperProvider.class).register(JacksonFeature.class);
     property(CommonProperties.JSON_JACKSON_DISABLED_MODULES, 
"DefaultScalaModule");
 
diff --git 
a/server/src/main/java/org/apache/gravitino/server/web/VersioningFilter.java 
b/server/src/main/java/org/apache/gravitino/server/web/VersioningFilter.java
index 7c2c71b32d..b2263e7f40 100644
--- a/server/src/main/java/org/apache/gravitino/server/web/VersioningFilter.java
+++ b/server/src/main/java/org/apache/gravitino/server/web/VersioningFilter.java
@@ -19,6 +19,7 @@
 package org.apache.gravitino.server.web;
 
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Enumeration;
@@ -36,6 +37,7 @@ import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletRequestWrapper;
 import javax.servlet.http.HttpServletResponse;
+import org.apache.gravitino.dto.responses.ErrorResponse;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -104,9 +106,17 @@ public class VersioningFilter implements Filter {
 
         if (!ApiVersion.isSupportedVersion(version)) {
           LOG.error("Unsupported version v{} in Request Header {}.", version, 
value);
+          String message = String.format("Unsupported version v%d in request 
header", version);
+          ErrorResponse errorResponse = 
ErrorResponse.illegalArguments(message);
 
+          // Write the JSON ErrorResponse directly instead of calling
+          // HttpServletResponse#sendError, so this filter -- which runs 
before Jersey ever sees
+          // the request -- doesn't fall through to Jetty's default HTML error 
page.
           HttpServletResponse resp = (HttpServletResponse) response;
-          resp.sendError(HttpServletResponse.SC_NOT_ACCEPTABLE, "Unsupported 
version");
+          resp.setStatus(HttpServletResponse.SC_NOT_ACCEPTABLE);
+          resp.setContentType("application/json");
+          resp.setCharacterEncoding(StandardCharsets.UTF_8.name());
+          ObjectMapperProvider.objectMapper().writeValue(resp.getWriter(), 
errorResponse);
         } else {
           chain.doFilter(request, response);
         }
diff --git 
a/server/src/main/java/org/apache/gravitino/server/web/mapper/WebApplicationExceptionMapper.java
 
b/server/src/main/java/org/apache/gravitino/server/web/mapper/WebApplicationExceptionMapper.java
new file mode 100644
index 0000000000..94ed1b48c4
--- /dev/null
+++ 
b/server/src/main/java/org/apache/gravitino/server/web/mapper/WebApplicationExceptionMapper.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.gravitino.server.web.mapper;
+
+import javax.annotation.Priority;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.gravitino.dto.responses.ErrorResponse;
+import org.eclipse.jetty.http.HttpStatus;
+
+/**
+ * WebApplicationExceptionMapper returns a structured JSON error body for any 
{@link
+ * WebApplicationException} that JAX-RS/Jersey raises itself before a resource 
method runs (e.g. a
+ * wrong HTTP method or an unacceptable {@code Accept}/{@code Content-Type} 
header), instead of
+ * letting the servlet container fall back to Jetty's default HTML error page.
+ *
+ * <p>{@link org.glassfish.jersey.server.ParamException} and {@link 
javax.ws.rs.NotFoundException}
+ * are subtypes of {@link WebApplicationException} with their own, more 
specific mappers ({@link
+ * ParamExceptionMapper}, {@link NotFoundExceptionMapper}); JAX-RS always 
prefers the mapper
+ * registered for the nearest type in the exception's class hierarchy, so this 
mapper only applies
+ * to every other case in the family.
+ *
+ * <p>Whatever entity {@code exception.getResponse()} may already carry is 
deliberately not
+ * preserved: every error under {@code /api/*} must be the same {@link 
ErrorResponse} JSON shape, so
+ * an exception that needs to convey more than a status code should do so 
through {@link
+ * WebApplicationException#getMessage()}, which this mapper does read.
+ */
+@Priority(1)
+public class WebApplicationExceptionMapper implements 
ExceptionMapper<WebApplicationException> {
+
+  @Override
+  public Response toResponse(WebApplicationException exception) {
+    int status = exception.getResponse().getStatus();
+    String message =
+        StringUtils.isBlank(exception.getMessage())
+            ? HttpStatus.getMessage(status)
+            : exception.getMessage();
+
+    return Response.fromResponse(exception.getResponse())
+        .entity(toErrorResponse(status, message))
+        .type(MediaType.APPLICATION_JSON)
+        .build();
+  }
+
+  private static ErrorResponse toErrorResponse(int status, String message) {
+    switch (status) {
+      case HttpServletResponse.SC_BAD_REQUEST:
+        return ErrorResponse.illegalArguments(message);
+      case HttpServletResponse.SC_FORBIDDEN:
+        return ErrorResponse.forbidden(message, null);
+      case HttpServletResponse.SC_METHOD_NOT_ALLOWED:
+        return ErrorResponse.unsupportedOperation(message);
+      default:
+        return ErrorResponse.restError(message);
+    }
+  }
+}
diff --git 
a/server/src/test/java/org/apache/gravitino/server/web/TestVersioningFilter.java
 
b/server/src/test/java/org/apache/gravitino/server/web/TestVersioningFilter.java
index 6da270ea4f..d7cb3ba303 100644
--- 
a/server/src/test/java/org/apache/gravitino/server/web/TestVersioningFilter.java
+++ 
b/server/src/test/java/org/apache/gravitino/server/web/TestVersioningFilter.java
@@ -31,6 +31,8 @@ import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Enumeration;
@@ -40,12 +42,30 @@ import javax.servlet.FilterChain;
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import org.apache.gravitino.dto.responses.ErrorConstants;
+import org.apache.gravitino.dto.responses.ErrorResponse;
 import 
org.apache.gravitino.server.web.VersioningFilter.MutableHttpServletRequest;
 import org.junit.jupiter.api.Test;
 import org.mockito.ArgumentCaptor;
 
 public class TestVersioningFilter {
 
+  private static StringWriter stubWriter(HttpServletResponse mockResponse) 
throws IOException {
+    StringWriter stringWriter = new StringWriter();
+    when(mockResponse.getWriter()).thenReturn(new PrintWriter(stringWriter));
+    return stringWriter;
+  }
+
+  private static void assertUnsupportedVersionResponse(
+      HttpServletResponse mockResponse, StringWriter writer) throws 
IOException {
+    verify(mockResponse).setStatus(HttpServletResponse.SC_NOT_ACCEPTABLE);
+    verify(mockResponse).setContentType("application/json");
+    ErrorResponse errorResponse =
+        ObjectMapperProvider.objectMapper().readValue(writer.toString(), 
ErrorResponse.class);
+    assertEquals(ErrorConstants.ILLEGAL_ARGUMENTS_CODE, 
errorResponse.getCode());
+    assertTrue(errorResponse.getMessage().contains("Unsupported version"));
+  }
+
   @Test
   public void testDoFilterWithSupportedVersion() throws ServletException, 
IOException {
     VersioningFilter filter = new VersioningFilter();
@@ -75,11 +95,12 @@ public class TestVersioningFilter {
         .thenReturn(
             new 
Vector<>(Collections.singletonList("application/vnd.gravitino.v2+json"))
                 .elements());
+    StringWriter writer = stubWriter(mockResponse);
 
     filter.doFilter(mockRequest, mockResponse, mockChain);
 
     verify(mockChain, never()).doFilter(any(), any());
-    verify(mockResponse).sendError(HttpServletResponse.SC_NOT_ACCEPTABLE, 
"Unsupported version");
+    assertUnsupportedVersionResponse(mockResponse, writer);
   }
 
   @Test
@@ -145,10 +166,11 @@ public class TestVersioningFilter {
     verify(mockChain).doFilter(any(), any());
 
     reset(mockChain, mockResponse);
+    StringWriter writer = stubWriter(mockResponse);
 
     filter.doFilter(mockRequest, mockResponse, mockChain);
     verify(mockChain, never()).doFilter(any(), any());
-    verify(mockResponse).sendError(HttpServletResponse.SC_NOT_ACCEPTABLE, 
"Unsupported version");
+    assertUnsupportedVersionResponse(mockResponse, writer);
   }
 
   @Test
@@ -229,16 +251,18 @@ public class TestVersioningFilter {
     verify(mockChain).doFilter(any(), any());
 
     reset(mockChain, mockResponse);
+    StringWriter writer1 = stubWriter(mockResponse);
 
     filter.doFilter(mockRequest, mockResponse, mockChain);
     verify(mockChain, never()).doFilter(any(), any());
-    verify(mockResponse).sendError(HttpServletResponse.SC_NOT_ACCEPTABLE, 
"Unsupported version");
+    assertUnsupportedVersionResponse(mockResponse, writer1);
 
     reset(mockChain, mockResponse);
+    StringWriter writer2 = stubWriter(mockResponse);
 
     filter.doFilter(mockRequest, mockResponse, mockChain);
     verify(mockChain, never()).doFilter(any(), any());
-    verify(mockResponse).sendError(HttpServletResponse.SC_NOT_ACCEPTABLE, 
"Unsupported version");
+    assertUnsupportedVersionResponse(mockResponse, writer2);
   }
 
   @Test
@@ -285,9 +309,10 @@ public class TestVersioningFilter {
                         "application/vnd.gravitino.v2+json, application/json"))
                 .elements());
 
+    StringWriter writer1 = stubWriter(mockResponse);
     filter.doFilter(mockRequest, mockResponse, mockChain);
     verify(mockChain, never()).doFilter(any(), any());
-    verify(mockResponse).sendError(HttpServletResponse.SC_NOT_ACCEPTABLE, 
"Unsupported version");
+    assertUnsupportedVersionResponse(mockResponse, writer1);
 
     reset(mockChain, mockResponse);
 
@@ -297,8 +322,9 @@ public class TestVersioningFilter {
                     Collections.singletonList(
                         "application/vnd.gravitino.v3+json; q=0.9, 
application/json"))
                 .elements());
+    StringWriter writer2 = stubWriter(mockResponse);
     filter.doFilter(mockRequest, mockResponse, mockChain);
     verify(mockChain, never()).doFilter(any(), any());
-    verify(mockResponse).sendError(HttpServletResponse.SC_NOT_ACCEPTABLE, 
"Unsupported version");
+    assertUnsupportedVersionResponse(mockResponse, writer2);
   }
 }
diff --git 
a/server/src/test/java/org/apache/gravitino/server/web/mapper/TestWebApplicationExceptionMapper.java
 
b/server/src/test/java/org/apache/gravitino/server/web/mapper/TestWebApplicationExceptionMapper.java
new file mode 100644
index 0000000000..5aa2dc7d9c
--- /dev/null
+++ 
b/server/src/test/java/org/apache/gravitino/server/web/mapper/TestWebApplicationExceptionMapper.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.gravitino.server.web.mapper;
+
+import javax.ws.rs.NotAcceptableException;
+import javax.ws.rs.NotAllowedException;
+import javax.ws.rs.NotSupportedException;
+import javax.ws.rs.core.Response;
+import org.apache.gravitino.dto.responses.ErrorConstants;
+import org.apache.gravitino.dto.responses.ErrorResponse;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class TestWebApplicationExceptionMapper {
+
+  private final WebApplicationExceptionMapper mapper = new 
WebApplicationExceptionMapper();
+
+  @Test
+  public void testWrongHttpMethodReturnsJsonBody() {
+    Response response = mapper.toResponse(new NotAllowedException("GET"));
+    ErrorResponse entity = (ErrorResponse) response.getEntity();
+
+    Assertions.assertEquals(
+        Response.Status.METHOD_NOT_ALLOWED.getStatusCode(), 
response.getStatus());
+    Assertions.assertEquals(ErrorConstants.UNSUPPORTED_OPERATION_CODE, 
entity.getCode());
+    Assertions.assertFalse(entity.getMessage().isEmpty());
+    Assertions.assertTrue(
+        response.getHeaderString("Allow") != null
+            && response.getHeaderString("Allow").contains("GET"));
+  }
+
+  @Test
+  public void testUnsupportedMediaTypeReturnsJsonBody() {
+    Response response = mapper.toResponse(new 
NotSupportedException("unsupported content type"));
+    ErrorResponse entity = (ErrorResponse) response.getEntity();
+
+    Assertions.assertEquals(
+        Response.Status.UNSUPPORTED_MEDIA_TYPE.getStatusCode(), 
response.getStatus());
+    Assertions.assertEquals(ErrorConstants.REST_ERROR_CODE, entity.getCode());
+    Assertions.assertEquals("unsupported content type", entity.getMessage());
+  }
+
+  @Test
+  public void testNotAcceptableReturnsJsonBody() {
+    Response response = mapper.toResponse(new NotAcceptableException());
+    ErrorResponse entity = (ErrorResponse) response.getEntity();
+
+    Assertions.assertEquals(Response.Status.NOT_ACCEPTABLE.getStatusCode(), 
response.getStatus());
+    Assertions.assertFalse(entity.getMessage().isEmpty());
+  }
+}

Reply via email to