1. Overview

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

By using its implementations, we can modify the payload before Spring MVC writes it to the response body. It is the response-related counterpart of RequestBodyAdvice and has similar features in terms of usage and registration.

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 returns an Answer in the response body. Since we're annotating QuestionController with @RestController, all endpoint methods will implicitly have the @ResponseBody annotation. As a result, Spring MVC will write the method return value to the response.

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 ResponseBodyAdvice

ResponseBodyAdvice allows the customization of the response object before Spring MVC writes it to the response body.

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

public class CustomResponseBodyAdvice implements ResponseBodyAdvice<Answer> {

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

    public Answer beforeBodyWrite(Answer answer, MethodParameter returnType, MediaType selectedContentType,
                                  Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request,
                                  ServerHttpResponse response) {
        System.out.println("In beforeBodyWrite() method of " + getClass().getSimpleName());
        answer.setAnswerMessage(answer.getAnswerMessage() + " by Spring");
        return answer;

In the CustomResponseBodyAdvice class, we're implementing two methods.

Firstly, the supports method decides whether this implementation should run for the current response. To perform this decision, Spring MVC provides the return value type and converter type. In our example, we're checking the types of the controller and return value.

Then, we have the beforeBodyWrite method. It runs after the execution of the controller method but before the response is written. Here we have the chance to make modifications to our response object. In our case, we're changing the answerMessage field of the Answer.

4. Invocation Order

Now, let's see in which order Spring MVC calls our ResponseBodyAdvice 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 controller method
In supports() method of CustomResponseBodyAdvice
In beforeBodyWrite() method of CustomResponseBodyAdvice

The controller methods run first. Then Spring MVC invokes the ResponseBodyAdvice methods.

5. Registering ResponseBodyAdvice

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

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

public class CustomResponseBodyAdvice implements ResponseBodyAdvice<Answer> {

    // Implementation

Also, we can register a ResponseBodyAdvice implementation manually by using the RequestMappingHandlerAdapter class:

public class CustomWebMvcConfiguration extends DelegatingWebMvcConfiguration {

    public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
        RequestMappingHandlerAdapter requestMappingHandlerAdapter = super.requestMappingHandlerAdapter();

        List<ResponseBodyAdvice<?>> responseBodyAdvices = new ArrayList<>();
        responseBodyAdvices.add(new CustomResponseBodyAdvice());

        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 ResponseBodyAdvice implementation.

6. Summary

In this tutorial, we've investigated theResponseBodyAdvice interface to customize the way Spring MVC writes to the response body.

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