Issue
I am implementing all the methods of ResponseEntityExceptionHandler
because i don't want Spring to send any standard error responses towards the client. There are two seemingly similar methods that confuse me a bit. Namely handleExceptionInternal
and handleException
. These are the definitions of both methods according to the official documentation.
handleException(Exception ex, WebRequest request)
Provides handling for standard Spring MVC exceptions.
handleExceptionInternal(Exception ex, Object body, HttpHeaders headers, HttpStatus status, WebRequest request)
A single place to customize the response body of all exception types.
I find these explanations a bit vague. What can be considered 'standard spring mvc exceptions' for example? And should handleExceptionInternal
be considered like a 'default' handler method that is used when none of the other methods can catch the spring exception? Please correct me if i'm wrong.
Thank you
Solution
handleException
method is a common exception handler for standard spring mvc exceptions. Its main task is it maps these exception to respective status code as per http response code convention, which most likely you are not going to change.
e.g.
HttpRequestMethodNotSupportedException -> 405
HttpMediaTypeNotSupportedException -> 415
NoHandlerFoundException -> 404
All these exceptions are handled in their specific handler methods handle{ExceptionName}
so that for some reason, if you want to change the status code (or add response body for detailed info), you can do so by overriding specific handler. All these handlers further delegate to handleExceptionInternal
.
One thing you have noticed each handle{ExceptionName}
methods pass body
as null to handleExceptionInternal
. These methods just return the status code with no body which doesn't give you more details about the error.
A common practice is to return a custom error response body with details so that your api consumers know the exact error cause. This is the place you can inject your custom body by creating an Error
object. A simple error message would look like.
public class ApiError {
private final int status;
private final int message;
public ApiError(int status, int message) {
this.status = status;
this.message = message;
}
// getters
}
And you can override handleExceptionInternal
method as:
@Override
protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body, HttpHeaders headers, HttpStatus status, WebRequest request) {
ApiError error = new ApiError(status.value(), ex.getMessage());
return super.handleExceptionInternal(ex, error, headers, status, request);
}
Summary
If handleException
wouldn't there, then you need to manually map each exceptions to respective error code. If handleExceptionInternal
were missing then to inject error body you would need to override each handle{Exception}
methods.
Update
RFC for http status code definition.
Answered By - Pratapi Hemant Patel