Skip to content

CodecException (from JSON conversion) in RestController is not mapped to 400 but 500 (SB 2.2.5 & Kotlin) #24646

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
csh0711 opened this issue Mar 3, 2020 · 6 comments
Assignees
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: regression A bug that is also a regression
Milestone

Comments

@csh0711
Copy link

csh0711 commented Mar 3, 2020

We just upgraded our Kotlin project from Spring Boot 2.2.4 to 2.2.5.

Unfortunately now some WebFlux-RestController tests fail because a mandatory JSON payload field now leads to a 500 Internal Server Error instead of a 400 Bad Request.

This is an exemplary RestController with its Kotlin data class for the request payload:

@RestController
class Controller {

    @PostMapping("/hello")
    fun post(@RequestBody request: RequestPayload) =
        ResponseEntity.ok().body("Hello ${request.foo} - ${request.bar}")

}

data class RequestPayload(
    val foo: String,
    val bar: String?
)

Please notice that attribute foo is mandatory (no ?).

This is the invalid payload (missing JSON field foo):
{ "bar": "bar text" }

When calling this RestController in a Spring Boot 2.2.4 app this results in a DecodingException which is correctly mapped to the status code 400.

But when calling this RestController in a Spring Boot 2.2.5 app this leads to CodecException which is not mapped to the status code 400 but results in a 500.

Please find the example in my GitHub repo: https://github.com/csh0711/boot-2-2-5-kotlin-codec-exception

Or use this ControllerTest:

@WebFluxTest(Controller::class)
internal class ControllerTests(
    @Autowired private val webTestClient: WebTestClient
) {
    @Test
    fun `responds with HTTP 400 BAD_REQUEST for missing foo in payload`() {
        webTestClient.post()
            .uri("/hello")
            .contentType(MediaType.APPLICATION_JSON)
            .bodyValue(""" { "bar": "bar text" } """)
            .exchange()
            .expectStatus().isBadRequest
    }
}

Many thanks in advance! :-)

@gmariotti
Copy link

This is happening also for WebMVC based projects

@csh0711
Copy link
Author

csh0711 commented Mar 4, 2020

I took a closer look at the problem. This seems to be the place that is responsible for this behaviour:

Class AbstractJackson2Decoder

SB 2.2.4

private CodecException processException(IOException ex) {
    if (ex instanceof InvalidDefinitionException) {
        JavaType type = ((InvalidDefinitionException) ex).getType();
        return new CodecException("Type definition error: " + type, ex);
    }
    if (ex instanceof JsonProcessingException) {
        String originalMessage = ((JsonProcessingException) ex).getOriginalMessage();
        return new DecodingException("JSON decoding error: " + originalMessage, ex);
    }
    return new DecodingException("I/O error while parsing input stream", ex);
}

--> All JsonProcessingException are mapped to a DecodingException

SB 2.2.5

private CodecException processException(IOException ex) {
    if (ex instanceof MismatchedInputException) {  // specific kind of JsonMappingException
        String originalMessage = ((MismatchedInputException) ex).getOriginalMessage();
        return new DecodingException("Invalid JSON input: " + originalMessage, ex);
    }
    if (ex instanceof InvalidDefinitionException) {  // another kind of JsonMappingException
        JavaType type = ((InvalidDefinitionException) ex).getType();
        return new CodecException("Type definition error: " + type, ex);
    }
    if (ex instanceof JsonMappingException) {  // typically ValueInstantiationException
        String originalMessage = ((JsonMappingException) ex).getOriginalMessage();
        return new CodecException("JSON conversion problem: " + originalMessage, ex);
    }
    if (ex instanceof JsonProcessingException) {
        String originalMessage = ((JsonProcessingException) ex).getOriginalMessage();
        return new DecodingException("JSON decoding error: " + originalMessage, ex);
    }
    return new DecodingException("I/O error while parsing input stream", ex);   
}

--> The specialized JsonMappingException is mapped to a CodecException

@dreis2211
Copy link
Contributor

@csh0711 AbstractJackson2Decoder is a class in Spring-Framework and not in Boot itself.

The issues look closely related to the following issues there:

Maybe the Boot team can transfer this in case it's a new variant of the above issues, but I guess otherwise it's gonna be fixed simply in Spring Framework.

@snicoll snicoll transferred this issue from spring-projects/spring-boot Mar 5, 2020
@snicoll
Copy link
Member

snicoll commented Mar 5, 2020

Thanks @dreis2211, I agree. I've moved the issue to framework for further consideration. We might close it as duplicate if it turns out to be the same problem.

@snicoll snicoll added the status: waiting-for-triage An issue we've not yet triaged or decided on label Mar 5, 2020
@csh0711
Copy link
Author

csh0711 commented Mar 5, 2020

Okay, thanks @snicoll and @dreis2211 👍

@jhoeller jhoeller self-assigned this Mar 5, 2020
@jhoeller jhoeller added in: web Issues in web modules (web, webmvc, webflux, websocket) type: regression A bug that is also a regression and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Mar 5, 2020
@jhoeller jhoeller added this to the 5.2.5 milestone Mar 5, 2020
@jhoeller
Copy link
Contributor

jhoeller commented Mar 5, 2020

This is indeed the same problem, just in the reactive codec implementation as opposed to the HttpMessageConverter infrastructure (which are kept in sync in that respect). I'll keep this issue open as a variant of the same issue, closing it along with the others.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: regression A bug that is also a regression
Projects
None yet
Development

No branches or pull requests

5 participants