@RestController
public class ErrorServlet {
@GetMapping(value = "/test", produces = MediaType.TEXT_PLAIN_VALUE)
public String test() {
throw new ResponseStatusException(HttpStatus.NOT_IMPLEMENTED, "you should not call this method");
}
}
localhost:8080/test without accept header produces:
{
"timestamp": "2020-03-10T10:27:53.965+0000",
"status": 501,
"error": "Not Implemented",
"message": "you should not call this method",
"path": "/test"
}
(even though I configured my endpoint to NOT output JSON here. But that's ok, as clients will benefit from error body).
Now, what if the client sends a request that matches the produces field. I'd still expect a error message in the body. BUT, currently the body is dropped:
localhost:8080/test with Accept: plain/text produces an empty body (while http status code 501 is still correct).
What is strange: if I change the endpoint to produces = MediaType.APPLICATION_XML_VALUE and send a request with accept: application/xml, the message body is still empty. Shouldn't spring convert the error at least to xml output here?
If this is not a bug: how could I possibly preserve the json error response for this endpoint?
spring-boot.2.2.5.RELEASE.
Comment From: rstoyanchev
I was going to point you to https://github.com/spring-projects/spring-framework/issues/23421#issuecomment-570601435 but then I realized you are the reporter on that issue too.
The thing to keep in mind is that success and error do not share that produces condition. What the method serves may or may not be how errors are rendered. Errors are rendered as JSON in Spring Boot but as a result of the linked issues, it now avoids rendering if it can't match the Accept header. A client could also send Accept: text/plain;application/problem+json.
You could make the case that JSON should be rendered anyway but I'm not sure the Boot team would be willing to do that out of the box. If you wanted to override the behavior you could use a ResponseEntity from an @ExceptionHandler method with a preset content-type.