Skip to content

Commit

Permalink
[RESTEASY-3380 ]Introduce an ExceptionMapper which handles JsonProces…
Browse files Browse the repository at this point in the history
…singException's, logs the error then returns an innocuous response.

https://issues.redhat.com/browse/RESTEASY-3380
Signed-off-by: James R. Perkins <jperkins@redhat.com>
  • Loading branch information
jamezp committed Nov 29, 2023
1 parent 12db996 commit 2aa01a2
Show file tree
Hide file tree
Showing 8 changed files with 108 additions and 36 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* JBoss, Home of Professional Open Source.
*
* Copyright 2023 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed 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.jboss.resteasy.plugins.providers.jackson;

import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.ExceptionMapper;
import jakarta.ws.rs.ext.Provider;

import org.jboss.resteasy.plugins.providers.jackson._private.JacksonLogger;

import com.fasterxml.jackson.core.JsonProcessingException;

/**
* @author <a href="mailto:jperkins@redhat.com">James R. Perkins</a>
*/
@Provider
public class JsonProcessingExceptionMapper implements ExceptionMapper<JsonProcessingException> {
@Override
public Response toResponse(final JsonProcessingException exception) {
JacksonLogger.LOGGER.logCannotDeserialize(exception);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(JacksonLogger.LOGGER.cannotDeserialize()).build();
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* JBoss, Home of Professional Open Source.
*
* Copyright 2023 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed 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.jboss.resteasy.plugins.providers.jackson._private;

import org.jboss.logging.Logger;
import org.jboss.logging.annotations.Cause;
import org.jboss.logging.annotations.LogMessage;
import org.jboss.logging.annotations.Message;
import org.jboss.logging.annotations.MessageLogger;

/**
* @author <a href="mailto:jperkins@redhat.com">James R. Perkins</a>
*/
@MessageLogger(projectCode = "RESTEASY-JACKSON")
public interface JacksonLogger {

JacksonLogger LOGGER = Logger.getMessageLogger(JacksonLogger.class, "org.jboss.resteasy.plugins.providers.jackson");

/**
* Returns a message indicating the data could not be deserialized.
*
* @return a message indicating the data could not be deserialized
*/
// Note we must use Message.NONE here. Otherwise, a prefix is added, and we do not want to expose where this is
// coming from in the response.
@Message(id = Message.NONE, value = "Not able to deserialize data provided.")
String cannotDeserialize();

/**
* Logs a message indicating the data could not be deserialized.
*
* @param cause the cause of the error
*/
@LogMessage(level = Logger.Level.ERROR)
@Message(id = 100, value = "Not able to deserialize data provided")
void logCannotDeserialize(@Cause Throwable cause);
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
org.jboss.resteasy.plugins.providers.jackson.ResteasyJackson2Provider
org.jboss.resteasy.plugins.providers.jackson.UnrecognizedPropertyExceptionHandler
org.jboss.resteasy.plugins.providers.jackson.PatchMethodFilter
org.jboss.resteasy.plugins.providers.jackson.JsonProcessingExceptionMapper
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,16 @@
import jakarta.ws.rs.ext.ExceptionMapper;
import jakarta.ws.rs.ext.Provider;

import com.fasterxml.jackson.core.JsonProcessingException;

/**
* User: rsearls
* Date: 10/26/16
*/
@Provider
public class ExceptionMapperIOExceptionMapper implements ExceptionMapper<Throwable> {
public class ExceptionMapperIOExceptionMapper implements ExceptionMapper<JsonProcessingException> {
@Override
public Response toResponse(Throwable e) {
public Response toResponse(JsonProcessingException e) {
Map<String, Object> result = new HashMap<>();
result.put("err_msg", "UN_KNOWN_ERR");
result.put("err_detail", "please contact admin for help");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ public void testAircraftFailure() throws Exception {
logger.info("response: " + response);
Assert.assertNotNull(response);
Assert.assertTrue(response.contains("Response code: " + HttpResponseCodes.SC_INTERNAL_SERVER_ERROR));
Assert.assertTrue(response.contains("Configured `PolymorphicTypeValidator`") && response.contains("denied resolution"));
Assert.assertTrue("Expected response to contain \"Not able to deserialize data provided\" but was \"" + response + "\"",
response.contains("Not able to deserialize data provided"));
}

@Test
Expand All @@ -96,7 +97,8 @@ public void testAutomobileFailure() throws Exception {
logger.info("response: " + response);
Assert.assertNotNull(response);
Assert.assertTrue(response.contains("Response code: " + HttpResponseCodes.SC_INTERNAL_SERVER_ERROR));
Assert.assertTrue(response.contains("Configured `PolymorphicTypeValidator`") && response.contains("denied resolution"));
Assert.assertTrue("Expected response to contain \"Not able to deserialize data provided\" but was \"" + response + "\"",
response.contains("Not able to deserialize data provided"));
}

private String createJSONString(TestPolymorphicType t) throws Exception {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ public void testBad() throws Exception {
logger.info("response: " + response);
Assert.assertNotNull(response);
Assert.assertTrue(response.contains("Response code: " + HttpResponseCodes.SC_INTERNAL_SERVER_ERROR));
Assert.assertTrue(response.contains("Configured `PolymorphicTypeValidator`") && response.contains("denied resolution"));
Assert.assertTrue("Expected response to contain \"Not able to deserialize data provided\" but was \"" + response + "\"",
response.contains("Not able to deserialize data provided"));
}

private String createJSONString(TestPolymorphicType t) throws Exception {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,9 @@ private void test(String deployment) {
String responseText = response.readEntity(String.class);

if (deployment.equals(NO_JSON_B)) {
Assert.assertTrue("Unrecognized token does not show", responseText.contains(trimmed));
Assert.assertFalse("Unrecognized token is not reasonably trimmed", responseText.contains(trimmed.concat("A")));
Assert.assertTrue(
"Expected response to contain \"Not able to deserialize data provided\" but was \"" + response + "\"",
responseText.contains("Not able to deserialize data provided"));
}
Assert.assertTrue("Response is longer than 550 characters", responseText.length() <= 550);

Expand Down

0 comments on commit 2aa01a2

Please sign in to comment.