Spring MVC - Automatically return 204 when rest controller response type is void

Viewed 5617

I'm trying to have spring automatically return HTTP Status 204 when the controller method response type is void. Ex:

Let's say I have a controller method like this:

@DeleteMapping(value = "/{heroId}")
public void delete(@PathVariable Long heroId) {
    heroService.delete(heroId);
}

I'm looking for a way to automatically return 204 without having to annotate the method with @ResponseStatus(value = HttpStatus.NO_CONTENT).

Is it possible to do this with a handler or AOP or some other facility?

PS. I see this answer, Return HTTP 204 on null with spring @RestController, but does not answer my specific question on how this can be implemented for methods with a void return type. Also, this method should work with a method that has no input arguments.

2 Answers

I was able to implement a solution based on the link provided by Yoshua. I'm not 100% sure on the implementation details, but it's working for me.

This captures the response from all of the controller methods that have a return type of void and changes their HTTP Status to 204.

import org.springframework.core.MethodParameter;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

@ControllerAdvice
public class NoContentControllerAdvice implements ResponseBodyAdvice<Void> {

    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        if(returnType.getParameterType().isAssignableFrom(void.class)) {
            return true;
        }

        return false;
    }



    @Override
    public Void beforeBodyWrite(Void body, MethodParameter returnType, MediaType mediaType,
            Class<? extends HttpMessageConverter<?>> converterType, ServerHttpRequest request, ServerHttpResponse response) {

        if(returnType.getParameterType().isAssignableFrom(void.class)) {
            response.setStatusCode(HttpStatus.NO_CONTENT);
        }

        return body;
    }
}

I see this has already been answered, but this solution is a little cleaner:

import org.springframework.core.MethodParameter;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

@ControllerAdvice
public class NoContentControllerAdvice implements ResponseBodyAdvice<Void> {

  @Override
  public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
    return returnType.getParameterType() == void.class;
  }

  @Override
  public Void beforeBodyWrite(Void body, MethodParameter returnType, MediaType selectedContentType,
      Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
    response.setStatusCode(HttpStatus.NO_CONTENT);
    return body;
  }
}
Related