Emanuel Hategan opened SPR-13490 and commented

When handling a POST request in a @RestController, the payload parameter annotated with @RequestBody can be null, regardless of the value of the required attribute.

Payload is JSON (content-type header is included) and deserialization is handled by Jackson.

In case it matters, the project is inheriting from spring-boot-starter-parent version 1.2.5.RELEASE.


Affects: 4.1.7

Reference URL: http://stackoverflow.com/questions/32222099/spring-4-reject-null-requestbody-for-all-endpoints

Issue Links: - #17768 Avoid reading (empty) RequestBody for HTTP methods that aren't expected to have a body ("duplicates")

Referenced from: commits https://github.com/spring-projects/spring-framework-issues/commit/5bf23a09e2e12e83125614d0b33c6c6217b31952, https://github.com/spring-projects/spring-framework-issues/commit/c93c892f95072913df125b5234612f5fae8e86c7, https://github.com/spring-projects/spring-framework-issues/commit/0319caf3d713cbf7c482eb3eb092e491b388dcea

Comment From: spring-projects-issues

Brian Clozel commented

Hi Emanuel Hategan

I couldn't reproduce the issue you're referring to here, using Boot or plain Spring Framework.

Here is a repro project that demonstrates that:

  • a empty body will be rejected by @RequestBody since it's marked as required by default
  • an empty JSON object "{}" will be rejected by the Validator

Could you take a look at this repro project and your app?

Thanks,

Comment From: spring-projects-issues

Emanuel Hategan commented

I've made a pull request with updated tests: https://github.com/spring-projects/spring-framework-issues/pull/111

What I'm thinking is that it should reject payloads that are "null" not only empty "{}" since the null string is deserialized as null payload.

Comment From: spring-projects-issues

Brian Clozel commented

I don't think this behavior is a bug, since:

  • @RequestBody(required=true) states that the body should be injected here and should not be null
  • @Valid states that the method argument should be processed by validators

Now for each case: * "{}" is deserialized as an empty Payload object, which will be rejected by the validator that rejects empty messages * "" is rejected by @RequestBody(required=true) because the request body is empty * "null" is deserialized by Jackson as null, and the Validator is never called on such object

In my opinion, there are several ways to deal with this - manually checking for null values, using @NotNull or even using a custom HandlerMethodArgumentResolver.

One more thing: your SO question was spot on (sorry if it took me a while to understand the whole context) and I understand your concerns - even if there may be "no problem to solve" strictly in the framework, I'd like to find the best answer for this.

Is this "null" request payload a common use case? This looks to me as if you've JSON.stringify(null) on the client side...

Comment From: spring-projects-issues

Emanuel Hategan commented

Hi Brian, thank you for looking into this.

You are saying "null" is deserialized by Jackson as null, and the Validator is never called on such object and you are right validator is not called in this case.

However, I still believe "null" values should be rejected earlier, because of the @RequestBody(required=true) according to its documentation: "leading to an exception thrown in case there is no body content. Switch this to {@code false} if you prefer {@code null} to be passed when the body content is {@code null}."

Interestingly enough, in version 4.2.3.RELEASE the issue is fixed: just replace 4.1.7.RELEASE with 4.2.3.RELEASE in the pom and all tests pass. The fix seems to be in this commit: https://github.com/spring-projects/spring-framework/commit/3272a3b8badc29fd6f6022476dfb0124fbfeca85 which is related to #17768

Comment From: spring-projects-issues

Brian Clozel commented

Indeed, this is now fixed. We're now checking if the resolved arg is null after it's been deserialized, taking care of this use case.

Thanks for the report!

Comment From: fveerden

Issue seems to reappear in springboot 3

Comment From: bclozel

@fveerden commenting on a 7 year old issue won't help here unfortunately. Could you create a new issue with a sample application showing the problem?