I'm working on a Spring REST controller, specifically on an exception handler. The exception handler works as intended and my JUnit-Test (using the Spring HTTP client) shows that the correct HTTP Status code (400) is received at the client. The HTTP client automatically translates this into a HttpClientErrorException
.
However, printing the HttpClientErrorException
always produces the following result for me:
HttpClientErrorException: 400 null
... and the null
part is what worries me. Shouldn't this be the place where the message of the server-side exception is supposed to be?
I checked the source code of the HTTP client to see where the client-side exception is thrown. It looks like this:
throw new HttpClientErrorException(statusCode, response.getStatusText(), response.getHeaders(), getResponseBody(response), getCharset(response));
Debugging this call revealed that response.getStatusText()
is null
in my case.
My question is: How do you design your ResponseEntity
on the server-side such that the HTTP client finds the server-side exception message in response.getStatusText()
instead of null
?
Mine currently looks like this:
@ExceptionHandler({ MyCustomException.class })
public ResponseEntity<String> handleException(final HttpServletRequest req, final MyCustomException e) {
HttpHeaders headers = new HttpHeaders();
headers.set("Content-type", "text/plain");
String body = e.toString();
return new ResponseEntity<>(body, headers, HttpStatus.BAD_REQUEST);
}
... and I get null
in the client side status text.
The most basic way of returning an error message from a REST API is to use the @ResponseStatus annotation. We can add the error message in the annotation's reason field. Although we can only return a generic error message, we can specify exception-specific error messages.
If we want to specify the response status of a controller method, we need to annotate that method with the @ResponseStatus annotation. It has two interchangeable arguments for the desired response type: code and value. Note, that when we set reason, Spring calls HttpServletResponse. sendError().
The @ExceptionHandler is an annotation used to handle the specific exceptions and sending the custom responses to the client. Define a class that extends the RuntimeException class. You can define the @ExceptionHandler method to handle the exceptions as shown.
I must admit that I got fooled on this one. The null
value printed by the Spring HttpClientErrorException
is the statusText
. This text is static. For example, for Status Code 404, the defined status text is "not found". There is no way to change it.
In order to receive the actual exception code, then the method suggested by Utku is exactly right. The small gotcha is that the error message needs to be extracted from HttpClientErrorException#getResponseBodyAsString()
, not from HttpClientErrorException#getStatusText()
like I tried.
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