|
|
|
@ -70,7 +70,7 @@ import org.springframework.web.util.WebUtils; |
|
|
|
* using view resolution (e.g., via {@code ContentNegotiatingViewResolver}), |
|
|
|
* using view resolution (e.g., via {@code ContentNegotiatingViewResolver}), |
|
|
|
* then {@code DefaultHandlerExceptionResolver} is good enough. |
|
|
|
* then {@code DefaultHandlerExceptionResolver} is good enough. |
|
|
|
* |
|
|
|
* |
|
|
|
* <p>Note that in order for an {@code @ControllerAdvice} sub-class to be |
|
|
|
* <p>Note that in order for an {@code @ControllerAdvice} subclass to be |
|
|
|
* detected, {@link ExceptionHandlerExceptionResolver} must be configured. |
|
|
|
* detected, {@link ExceptionHandlerExceptionResolver} must be configured. |
|
|
|
* |
|
|
|
* |
|
|
|
* @author Rossen Stoyanchev |
|
|
|
* @author Rossen Stoyanchev |
|
|
|
@ -121,8 +121,9 @@ public abstract class ResponseEntityExceptionHandler { |
|
|
|
AsyncRequestTimeoutException.class |
|
|
|
AsyncRequestTimeoutException.class |
|
|
|
}) |
|
|
|
}) |
|
|
|
@Nullable |
|
|
|
@Nullable |
|
|
|
public final ResponseEntity<Object> handleException(Exception ex, WebRequest request) { |
|
|
|
public final ResponseEntity<Object> handleException(Exception ex, WebRequest request) throws Exception { |
|
|
|
HttpHeaders headers = new HttpHeaders(); |
|
|
|
HttpHeaders headers = new HttpHeaders(); |
|
|
|
|
|
|
|
|
|
|
|
if (ex instanceof HttpRequestMethodNotSupportedException) { |
|
|
|
if (ex instanceof HttpRequestMethodNotSupportedException) { |
|
|
|
HttpStatus status = HttpStatus.METHOD_NOT_ALLOWED; |
|
|
|
HttpStatus status = HttpStatus.METHOD_NOT_ALLOWED; |
|
|
|
return handleHttpRequestMethodNotSupported((HttpRequestMethodNotSupportedException) ex, headers, status, request); |
|
|
|
return handleHttpRequestMethodNotSupported((HttpRequestMethodNotSupportedException) ex, headers, status, request); |
|
|
|
@ -181,36 +182,15 @@ public abstract class ResponseEntityExceptionHandler { |
|
|
|
} |
|
|
|
} |
|
|
|
else if (ex instanceof AsyncRequestTimeoutException) { |
|
|
|
else if (ex instanceof AsyncRequestTimeoutException) { |
|
|
|
HttpStatus status = HttpStatus.SERVICE_UNAVAILABLE; |
|
|
|
HttpStatus status = HttpStatus.SERVICE_UNAVAILABLE; |
|
|
|
return handleAsyncRequestTimeoutException( |
|
|
|
return handleAsyncRequestTimeoutException((AsyncRequestTimeoutException) ex, headers, status, request); |
|
|
|
(AsyncRequestTimeoutException) ex, headers, status, request); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
else { |
|
|
|
if (logger.isWarnEnabled()) { |
|
|
|
// Unknown exception, typically a wrapper with a common MVC exception as cause
|
|
|
|
logger.warn("Unknown exception type: " + ex.getClass().getName()); |
|
|
|
// (since @ExceptionHandler type declarations also match first-level causes):
|
|
|
|
} |
|
|
|
// We only deal with top-level MVC exceptions here, so let's rethrow the given
|
|
|
|
HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR; |
|
|
|
// exception for further processing through the HandlerExceptionResolver chain.
|
|
|
|
return handleExceptionInternal(ex, null, headers, status, request); |
|
|
|
throw ex; |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* A single place to customize the response body of all Exception types. |
|
|
|
|
|
|
|
* <p>The default implementation sets the {@link WebUtils#ERROR_EXCEPTION_ATTRIBUTE} |
|
|
|
|
|
|
|
* request attribute and creates a {@link ResponseEntity} from the given |
|
|
|
|
|
|
|
* body, headers, and status. |
|
|
|
|
|
|
|
* @param ex the exception |
|
|
|
|
|
|
|
* @param body the body for the response |
|
|
|
|
|
|
|
* @param headers the headers for the response |
|
|
|
|
|
|
|
* @param status the response status |
|
|
|
|
|
|
|
* @param request the current request |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
protected ResponseEntity<Object> handleExceptionInternal(Exception ex, @Nullable Object body, |
|
|
|
|
|
|
|
HttpHeaders headers, HttpStatus status, WebRequest request) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (HttpStatus.INTERNAL_SERVER_ERROR.equals(status)) { |
|
|
|
|
|
|
|
request.setAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE, ex, WebRequest.SCOPE_REQUEST); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
return new ResponseEntity<>(body, headers, status); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
@ -223,8 +203,8 @@ public abstract class ResponseEntityExceptionHandler { |
|
|
|
* @param request the current request |
|
|
|
* @param request the current request |
|
|
|
* @return a {@code ResponseEntity} instance |
|
|
|
* @return a {@code ResponseEntity} instance |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
protected ResponseEntity<Object> handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException ex, |
|
|
|
protected ResponseEntity<Object> handleHttpRequestMethodNotSupported( |
|
|
|
HttpHeaders headers, HttpStatus status, WebRequest request) { |
|
|
|
HttpRequestMethodNotSupportedException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { |
|
|
|
|
|
|
|
|
|
|
|
pageNotFoundLogger.warn(ex.getMessage()); |
|
|
|
pageNotFoundLogger.warn(ex.getMessage()); |
|
|
|
|
|
|
|
|
|
|
|
@ -245,8 +225,8 @@ public abstract class ResponseEntityExceptionHandler { |
|
|
|
* @param request the current request |
|
|
|
* @param request the current request |
|
|
|
* @return a {@code ResponseEntity} instance |
|
|
|
* @return a {@code ResponseEntity} instance |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
protected ResponseEntity<Object> handleHttpMediaTypeNotSupported(HttpMediaTypeNotSupportedException ex, |
|
|
|
protected ResponseEntity<Object> handleHttpMediaTypeNotSupported( |
|
|
|
HttpHeaders headers, HttpStatus status, WebRequest request) { |
|
|
|
HttpMediaTypeNotSupportedException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { |
|
|
|
|
|
|
|
|
|
|
|
List<MediaType> mediaTypes = ex.getSupportedMediaTypes(); |
|
|
|
List<MediaType> mediaTypes = ex.getSupportedMediaTypes(); |
|
|
|
if (!CollectionUtils.isEmpty(mediaTypes)) { |
|
|
|
if (!CollectionUtils.isEmpty(mediaTypes)) { |
|
|
|
@ -265,8 +245,8 @@ public abstract class ResponseEntityExceptionHandler { |
|
|
|
* @param request the current request |
|
|
|
* @param request the current request |
|
|
|
* @return a {@code ResponseEntity} instance |
|
|
|
* @return a {@code ResponseEntity} instance |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
protected ResponseEntity<Object> handleHttpMediaTypeNotAcceptable(HttpMediaTypeNotAcceptableException ex, |
|
|
|
protected ResponseEntity<Object> handleHttpMediaTypeNotAcceptable( |
|
|
|
HttpHeaders headers, HttpStatus status, WebRequest request) { |
|
|
|
HttpMediaTypeNotAcceptableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { |
|
|
|
|
|
|
|
|
|
|
|
return handleExceptionInternal(ex, null, headers, status, request); |
|
|
|
return handleExceptionInternal(ex, null, headers, status, request); |
|
|
|
} |
|
|
|
} |
|
|
|
@ -281,8 +261,8 @@ public abstract class ResponseEntityExceptionHandler { |
|
|
|
* @return a {@code ResponseEntity} instance |
|
|
|
* @return a {@code ResponseEntity} instance |
|
|
|
* @since 4.2 |
|
|
|
* @since 4.2 |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
protected ResponseEntity<Object> handleMissingPathVariable(MissingPathVariableException ex, |
|
|
|
protected ResponseEntity<Object> handleMissingPathVariable( |
|
|
|
HttpHeaders headers, HttpStatus status, WebRequest request) { |
|
|
|
MissingPathVariableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { |
|
|
|
|
|
|
|
|
|
|
|
return handleExceptionInternal(ex, null, headers, status, request); |
|
|
|
return handleExceptionInternal(ex, null, headers, status, request); |
|
|
|
} |
|
|
|
} |
|
|
|
@ -296,8 +276,8 @@ public abstract class ResponseEntityExceptionHandler { |
|
|
|
* @param request the current request |
|
|
|
* @param request the current request |
|
|
|
* @return a {@code ResponseEntity} instance |
|
|
|
* @return a {@code ResponseEntity} instance |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
protected ResponseEntity<Object> handleMissingServletRequestParameter(MissingServletRequestParameterException ex, |
|
|
|
protected ResponseEntity<Object> handleMissingServletRequestParameter( |
|
|
|
HttpHeaders headers, HttpStatus status, WebRequest request) { |
|
|
|
MissingServletRequestParameterException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { |
|
|
|
|
|
|
|
|
|
|
|
return handleExceptionInternal(ex, null, headers, status, request); |
|
|
|
return handleExceptionInternal(ex, null, headers, status, request); |
|
|
|
} |
|
|
|
} |
|
|
|
@ -311,8 +291,8 @@ public abstract class ResponseEntityExceptionHandler { |
|
|
|
* @param request the current request |
|
|
|
* @param request the current request |
|
|
|
* @return a {@code ResponseEntity} instance |
|
|
|
* @return a {@code ResponseEntity} instance |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
protected ResponseEntity<Object> handleServletRequestBindingException(ServletRequestBindingException ex, |
|
|
|
protected ResponseEntity<Object> handleServletRequestBindingException( |
|
|
|
HttpHeaders headers, HttpStatus status, WebRequest request) { |
|
|
|
ServletRequestBindingException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { |
|
|
|
|
|
|
|
|
|
|
|
return handleExceptionInternal(ex, null, headers, status, request); |
|
|
|
return handleExceptionInternal(ex, null, headers, status, request); |
|
|
|
} |
|
|
|
} |
|
|
|
@ -326,8 +306,8 @@ public abstract class ResponseEntityExceptionHandler { |
|
|
|
* @param request the current request |
|
|
|
* @param request the current request |
|
|
|
* @return a {@code ResponseEntity} instance |
|
|
|
* @return a {@code ResponseEntity} instance |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
protected ResponseEntity<Object> handleConversionNotSupported(ConversionNotSupportedException ex, |
|
|
|
protected ResponseEntity<Object> handleConversionNotSupported( |
|
|
|
HttpHeaders headers, HttpStatus status, WebRequest request) { |
|
|
|
ConversionNotSupportedException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { |
|
|
|
|
|
|
|
|
|
|
|
return handleExceptionInternal(ex, null, headers, status, request); |
|
|
|
return handleExceptionInternal(ex, null, headers, status, request); |
|
|
|
} |
|
|
|
} |
|
|
|
@ -341,8 +321,8 @@ public abstract class ResponseEntityExceptionHandler { |
|
|
|
* @param request the current request |
|
|
|
* @param request the current request |
|
|
|
* @return a {@code ResponseEntity} instance |
|
|
|
* @return a {@code ResponseEntity} instance |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
protected ResponseEntity<Object> handleTypeMismatch(TypeMismatchException ex, HttpHeaders headers, |
|
|
|
protected ResponseEntity<Object> handleTypeMismatch( |
|
|
|
HttpStatus status, WebRequest request) { |
|
|
|
TypeMismatchException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { |
|
|
|
|
|
|
|
|
|
|
|
return handleExceptionInternal(ex, null, headers, status, request); |
|
|
|
return handleExceptionInternal(ex, null, headers, status, request); |
|
|
|
} |
|
|
|
} |
|
|
|
@ -356,8 +336,8 @@ public abstract class ResponseEntityExceptionHandler { |
|
|
|
* @param request the current request |
|
|
|
* @param request the current request |
|
|
|
* @return a {@code ResponseEntity} instance |
|
|
|
* @return a {@code ResponseEntity} instance |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
protected ResponseEntity<Object> handleHttpMessageNotReadable(HttpMessageNotReadableException ex, |
|
|
|
protected ResponseEntity<Object> handleHttpMessageNotReadable( |
|
|
|
HttpHeaders headers, HttpStatus status, WebRequest request) { |
|
|
|
HttpMessageNotReadableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { |
|
|
|
|
|
|
|
|
|
|
|
return handleExceptionInternal(ex, null, headers, status, request); |
|
|
|
return handleExceptionInternal(ex, null, headers, status, request); |
|
|
|
} |
|
|
|
} |
|
|
|
@ -371,8 +351,8 @@ public abstract class ResponseEntityExceptionHandler { |
|
|
|
* @param request the current request |
|
|
|
* @param request the current request |
|
|
|
* @return a {@code ResponseEntity} instance |
|
|
|
* @return a {@code ResponseEntity} instance |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
protected ResponseEntity<Object> handleHttpMessageNotWritable(HttpMessageNotWritableException ex, |
|
|
|
protected ResponseEntity<Object> handleHttpMessageNotWritable( |
|
|
|
HttpHeaders headers, HttpStatus status, WebRequest request) { |
|
|
|
HttpMessageNotWritableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { |
|
|
|
|
|
|
|
|
|
|
|
return handleExceptionInternal(ex, null, headers, status, request); |
|
|
|
return handleExceptionInternal(ex, null, headers, status, request); |
|
|
|
} |
|
|
|
} |
|
|
|
@ -386,8 +366,8 @@ public abstract class ResponseEntityExceptionHandler { |
|
|
|
* @param request the current request |
|
|
|
* @param request the current request |
|
|
|
* @return a {@code ResponseEntity} instance |
|
|
|
* @return a {@code ResponseEntity} instance |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, |
|
|
|
protected ResponseEntity<Object> handleMethodArgumentNotValid( |
|
|
|
HttpHeaders headers, HttpStatus status, WebRequest request) { |
|
|
|
MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { |
|
|
|
|
|
|
|
|
|
|
|
return handleExceptionInternal(ex, null, headers, status, request); |
|
|
|
return handleExceptionInternal(ex, null, headers, status, request); |
|
|
|
} |
|
|
|
} |
|
|
|
@ -401,8 +381,8 @@ public abstract class ResponseEntityExceptionHandler { |
|
|
|
* @param request the current request |
|
|
|
* @param request the current request |
|
|
|
* @return a {@code ResponseEntity} instance |
|
|
|
* @return a {@code ResponseEntity} instance |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
protected ResponseEntity<Object> handleMissingServletRequestPart(MissingServletRequestPartException ex, |
|
|
|
protected ResponseEntity<Object> handleMissingServletRequestPart( |
|
|
|
HttpHeaders headers, HttpStatus status, WebRequest request) { |
|
|
|
MissingServletRequestPartException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { |
|
|
|
|
|
|
|
|
|
|
|
return handleExceptionInternal(ex, null, headers, status, request); |
|
|
|
return handleExceptionInternal(ex, null, headers, status, request); |
|
|
|
} |
|
|
|
} |
|
|
|
@ -416,8 +396,8 @@ public abstract class ResponseEntityExceptionHandler { |
|
|
|
* @param request the current request |
|
|
|
* @param request the current request |
|
|
|
* @return a {@code ResponseEntity} instance |
|
|
|
* @return a {@code ResponseEntity} instance |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
protected ResponseEntity<Object> handleBindException(BindException ex, HttpHeaders headers, |
|
|
|
protected ResponseEntity<Object> handleBindException( |
|
|
|
HttpStatus status, WebRequest request) { |
|
|
|
BindException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { |
|
|
|
|
|
|
|
|
|
|
|
return handleExceptionInternal(ex, null, headers, status, request); |
|
|
|
return handleExceptionInternal(ex, null, headers, status, request); |
|
|
|
} |
|
|
|
} |
|
|
|
@ -467,4 +447,24 @@ public abstract class ResponseEntityExceptionHandler { |
|
|
|
return handleExceptionInternal(ex, null, headers, status, webRequest); |
|
|
|
return handleExceptionInternal(ex, null, headers, status, webRequest); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* A single place to customize the response body of all Exception types. |
|
|
|
|
|
|
|
* <p>The default implementation sets the {@link WebUtils#ERROR_EXCEPTION_ATTRIBUTE} |
|
|
|
|
|
|
|
* request attribute and creates a {@link ResponseEntity} from the given |
|
|
|
|
|
|
|
* body, headers, and status. |
|
|
|
|
|
|
|
* @param ex the exception |
|
|
|
|
|
|
|
* @param body the body for the response |
|
|
|
|
|
|
|
* @param headers the headers for the response |
|
|
|
|
|
|
|
* @param status the response status |
|
|
|
|
|
|
|
* @param request the current request |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
protected ResponseEntity<Object> handleExceptionInternal( |
|
|
|
|
|
|
|
Exception ex, @Nullable Object body, HttpHeaders headers, HttpStatus status, WebRequest request) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (HttpStatus.INTERNAL_SERVER_ERROR.equals(status)) { |
|
|
|
|
|
|
|
request.setAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE, ex, WebRequest.SCOPE_REQUEST); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return new ResponseEntity<>(body, headers, status); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|