Spring allows the definition of @ExceptionHandlers
inside of @RestControllerAdvice
.
I already defined a lot of other ExceptionHandlers
in there for HTTP 400, 404, 405,... However the ExceptionHandler for HTTP 406 (NOT_ACCEPTABLE) does not seem to work. The handler is triggered, I checked that in the logs, but the result is not used.
My goal is it to return a HTTP 406 with a JSON body.
Variant 1
@ResponseStatus(HttpStatus.NOT_ACCEPTABLE)
@ExceptionHandler(HttpMediaTypeNotAcceptableException.class)
public ErrorDTO requestMethodNotSupported(final HttpMediaTypeNotAcceptableException e) {
final ErrorDTO dto = new ErrorDTO(HttpStatus.NOT_ACCEPTABLE, "http.media_not_acceptable");
return dto;
}
Variant 2
@ExceptionHandler(HttpMediaTypeNotAcceptableException.class)
public ResponseEntity<ErrorDTO> requestMethodNotSupported2(final HttpMediaTypeNotAcceptableException e) {
final ErrorDTO dto = new ErrorDTO(HttpStatus.NOT_ACCEPTABLE, "http.media_not_acceptable");
return ResponseEntity.status(HttpStatus.NOT_ACCEPTABLE).contentType(MediaType.APPLICATION_JSON_UTF8).body(dto);
}
But I always get a HTML response similar to this from the Tomcat:
HTTP Status 406 -
type: Status report
message:
description: The resource identified by this request is only capable of generating responses with characteristics not acceptable according to the request "accept" headers.
instead of
{ "errorCode": 406, "errorMessage": "http.media_not_acceptable" }
Request-Headers:
- Accept: application/stuff-that-cannot-be-present
Actual-Response-Headers:
- Content-Type: text/html
Expected-Response-Headers:
- Content-Type: application/json
I know that I could simply "fix" the Accept-Header that is send by the client, however the server should always respond in JSON, if it does not know how to respond.
I use Spring 4.3.3.RELEASE and Jackson 2.8.4.
Finally I found a solution for this:
Instead of returning a serializable object just return the bytes directly.
EDIT:
As an alternative you can create a custom
HttpMessageConverter<ErrorResponse>
for yourErrorResponse
object.WebMvcConfigurerAdapter#extendMessageConverters(converters)
HttpMessageConverter
that is capable of creating your expected result/content type.getSupportedMediaTypes()
returnsMediaType.ALL
canRead()
returns falsecanWrite()
returns only true for yourErrorResponse
write()
sets the forced CT and forward your expected content type to the wrapped converter.