1. Overview

In this tutorial, we'll investigate the RequestBodyAdvice interface in Spring MVC.

By using its implementations, we can customize how Spring MVC reads the request body.

2. Sample Application

Let's start with our sample application.

public class QuestionController {

    @PostMapping(value = "/ask", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    public Answer ask(@RequestBody Question question) {
        System.out.println("In controller method");
        Answer answer = new Answer();
        answer.setAnswerMessage("I don't know!");
        return answer;

In the QuestionController class, we have a single endpoint which reads a Question from the request body and returns an Answer in the response body. Note the usage of @RequestBody in the controller method. This annotation tells Spring MVC to read the request body, convert it to Question and assign the converted object to the question variable.

public class Question {

    private String questionMessage;
    private Date date;

    // Getters & setters

public class Answer {

    private String answerMessage;
    private Question question;

    // Getters & setters

Then we have the Question and Answer classes which hold the related fields.

3. Implementing RequestBodyAdvice

RequestBodyAdvice allows customization of the request body before it is converted into an Object. Additionally, we can modify the converted object before it is passed into our controller methods.

Let's provide a basic implementation to investigate the interface methods:

public class CustomRequestBodyAdvice implements RequestBodyAdvice {

    public boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        System.out.println("In supports() method of " + getClass().getSimpleName());
        return methodParameter.getContainingClass() == QuestionController.class && targetType.getTypeName() == Question.class.getTypeName();

    public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType,
                                           Class<? extends HttpMessageConverter<?>> converterType) throws IOException {
        System.out.println("In beforeBodyRead() method of " + getClass().getSimpleName());
        return inputMessage;

    public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType,
                                Class<? extends HttpMessageConverter<?>> converterType) {
        System.out.println("In afterBodyRead() method of " + getClass().getSimpleName());
        if (body instanceof Question) {
            Question question = (Question) body;
            question.setDate(new Date());
            return question;

        return body;

    public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType,
                                  Class<? extends HttpMessageConverter<?>> converterType) {
        System.out.println("In handleEmptyBody() method of " + getClass().getSimpleName());
        return body;

In the CustomRequestBodyAdvice class, we're implementing all four methods of RequestBodyAdvice.

Firstly, the supports method decides whether this implementation should run for the current request. To perform this decision, Spring MVC provides some contextual information like the method parameter or target conversion type. In our example, we're checking the controller class and target conversion type.

Then, we have the beforeBodyRead method which runs before Spring MVC reads the request body.

Similarly, the afterBodyRead method runs after the body is read and converted into an Object. In afterBodyRead, we have access to the converted object. Hence we can cast it to an appropriate type and modify its fields. In our case, we're casting it to Question and setting the Date field.

Lastly, when the request body is empty, we can put our custom logic into the handleEmptyBody method. We must return a value to use, either the provided object or an entirely new object. In CustomRequestBodyAdvice, we're returning the provided value without any modification.

4. Invocation Order

Now, let's see in which order Spring MVC calls our RequestBodyAdvice and controller methods.

public class QuestionControllerTest {

    private MockMvc mockMvc;

    private ObjectMapper objectMapper;

    public void shouldApplyAdvices() throws Exception {
        Question question = new Question();
        question.setQuestionMessage("How is weather?");

Here, we have a simple test case which calls our /ask endpoint.

When we run the test, the print statements outline the order:

In supports() method of CustomRequestBodyAdvice
In beforeBodyRead() method of CustomRequestBodyAdvice
In supports() method of CustomRequestBodyAdvice
In afterBodyRead() method of CustomRequestBodyAdvice
In controller method

The methods of RequestBodyAdvice run first. Then the controller methods run after Spring MVC calls all other RequestBodyAdvices.

5. Registering RequestBodyAdvice

In order to register the RequestBodyAdvice implementations, we have two ways.

Primarily, we can annotate our implementation with @ControllerAdvice - as we did previously:

public class CustomRequestBodyAdvice implements RequestBodyAdvice {

    // Implementation

Alternatively, we can register a RequestBodyAdvice implementation manually by using the RequestMappingHandlerAdapter class:

public class CustomWebMvcConfiguration extends DelegatingWebMvcConfiguration {

    public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
        RequestMappingHandlerAdapter requestMappingHandlerAdapter = super.requestMappingHandlerAdapter();
        List<RequestBodyAdvice> additionalAdvices = new ArrayList<>();
        additionalAdvices.add(new CustomRequestBodyAdvice());
        return requestMappingHandlerAdapter;

Here, we're extending the DelegatingWebMvcConfiguration class and marking it as @Configuration. Then we're creating a RequestMappingHandlerAdapter bean where we're also registering our RequestBodyAdvice implementation.

6. Summary

In this tutorial, we've investigated the RequestBodyAdvice interface to customize the way Spring MVC reads the request body.

Finally, check out the source code for all examples in this tutorial over on Github.