I have a simple webservice that returns content either as json
or as plain text
(depending on the clients' accept
http header).
Problem: if an error occurs during text/plain
request, Spring somehow returns a 406 Not Acceptable
. Which is kind of wrong, because spring could as well just write the error out as plain error text, and moreover should absolutely preserve the 400
error status:
@RestController
public class TestServlet {
@PostMapping(value = "/test", produces = {APPLICATION_JSON_VALUE, TEXT_PLAIN_VALUE, "text/csv"})
public Object post() {
throw new BadRequestException("bad req");
}
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
public class BadRequestException extends RuntimeException {
public BadRequestException(String msg) {
super(msg);
}
}
POST request with accept=application/json
:
{
"timestamp": "2018-07-30T14:26:02",
"status": 400,
"error": "Bad Request",
"message": "bad req",
"path": "/test"
}
BUT with accept=text/csv
(or text/plain
) shows an empty response with status 406 Not Acceptable
.
I also noticed the DispatcherServlet.processDispatchResult()
is called twice: first with my BadRequest
exception, 2nd time with HttpMediaTypeNotAcceptableException
. So clearly the rendering of my custom exception fails, but why?
The problem is the restrictive Accept header allowing only one content type as response. In case of an error, Spring MVC needs to handle the BadRequestException
and produce the required content type using a registered HttpMessageConverter
.
By default Spring Boot has no message converter to produce text/plain
directly from any object. You may register an ObjectToStringHttpMessageConverter
(as a bean should work for Spring Boot) to allow this and you will get the result of BadRequestException.toString()
as response body.
I assume a similar problem for text/csv
but I am not sure how your setup for CSV message conversion looks like.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With