Skip to content

Commit 193c289

Browse files
committed
ResponseEntityExceptionHandler rethrows unknown exception (for further processing in DispatcherServlet's HandlerExceptionResolver chain)
Issue: SPR-16743 (cherry picked from commit 7b894fe)
1 parent 9c3270a commit 193c289

File tree

2 files changed

+156
-75
lines changed

2 files changed

+156
-75
lines changed

spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ResponseEntityExceptionHandler.java

Lines changed: 56 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@
6969
* using view resolution (e.g., via {@code ContentNegotiatingViewResolver}),
7070
* then {@code DefaultHandlerExceptionResolver} is good enough.
7171
*
72-
* <p>Note that in order for an {@code @ControllerAdvice} sub-class to be
72+
* <p>Note that in order for an {@code @ControllerAdvice} subclass to be
7373
* detected, {@link ExceptionHandlerExceptionResolver} must be configured.
7474
*
7575
* @author Rossen Stoyanchev
@@ -121,7 +121,7 @@ public abstract class ResponseEntityExceptionHandler {
121121
NoHandlerFoundException.class,
122122
AsyncRequestTimeoutException.class
123123
})
124-
public final ResponseEntity<Object> handleException(Exception ex, WebRequest request) {
124+
public final ResponseEntity<Object> handleException(Exception ex, WebRequest request) throws Exception {
125125
HttpHeaders headers = new HttpHeaders();
126126
if (ex instanceof org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException) {
127127
HttpStatus status = HttpStatus.NOT_FOUND;
@@ -185,38 +185,17 @@ else if (ex instanceof NoHandlerFoundException) {
185185
}
186186
else if (ex instanceof AsyncRequestTimeoutException) {
187187
HttpStatus status = HttpStatus.SERVICE_UNAVAILABLE;
188-
return handleAsyncRequestTimeoutException(
189-
(AsyncRequestTimeoutException) ex, headers, status, request);
188+
return handleAsyncRequestTimeoutException((AsyncRequestTimeoutException) ex, headers, status, request);
190189
}
191190
else {
192-
if (logger.isWarnEnabled()) {
193-
logger.warn("Unknown exception type: " + ex.getClass().getName());
194-
}
195-
HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
196-
return handleExceptionInternal(ex, null, headers, status, request);
191+
// Unknown exception, typically a wrapper with a common MVC exception as cause
192+
// (since @ExceptionHandler type declarations also match first-level causes):
193+
// We only deal with top-level MVC exceptions here, so let's rethrow the given
194+
// exception for further processing through the HandlerExceptionResolver chain.
195+
throw ex;
197196
}
198197
}
199198

200-
/**
201-
* A single place to customize the response body of all Exception types.
202-
* <p>The default implementation sets the {@link WebUtils#ERROR_EXCEPTION_ATTRIBUTE}
203-
* request attribute and creates a {@link ResponseEntity} from the given
204-
* body, headers, and status.
205-
* @param ex the exception
206-
* @param body the body for the response
207-
* @param headers the headers for the response
208-
* @param status the response status
209-
* @param request the current request
210-
*/
211-
protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body,
212-
HttpHeaders headers, HttpStatus status, WebRequest request) {
213-
214-
if (HttpStatus.INTERNAL_SERVER_ERROR.equals(status)) {
215-
request.setAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE, ex, WebRequest.SCOPE_REQUEST);
216-
}
217-
return new ResponseEntity<Object>(body, headers, status);
218-
}
219-
220199
/**
221200
* Customize the response for NoSuchRequestHandlingMethodException.
222201
* <p>This method logs a warning and delegates to {@link #handleExceptionInternal}.
@@ -228,7 +207,8 @@ protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object bo
228207
* @deprecated as of 4.3, along with {@link org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException}
229208
*/
230209
@Deprecated
231-
protected ResponseEntity<Object> handleNoSuchRequestHandlingMethod(org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException ex,
210+
protected ResponseEntity<Object> handleNoSuchRequestHandlingMethod(
211+
org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException ex,
232212
HttpHeaders headers, HttpStatus status, WebRequest request) {
233213

234214
pageNotFoundLogger.warn(ex.getMessage());
@@ -246,8 +226,8 @@ protected ResponseEntity<Object> handleNoSuchRequestHandlingMethod(org.springfra
246226
* @param request the current request
247227
* @return a {@code ResponseEntity} instance
248228
*/
249-
protected ResponseEntity<Object> handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException ex,
250-
HttpHeaders headers, HttpStatus status, WebRequest request) {
229+
protected ResponseEntity<Object> handleHttpRequestMethodNotSupported(
230+
HttpRequestMethodNotSupportedException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
251231

252232
pageNotFoundLogger.warn(ex.getMessage());
253233

@@ -268,8 +248,8 @@ protected ResponseEntity<Object> handleHttpRequestMethodNotSupported(HttpRequest
268248
* @param request the current request
269249
* @return a {@code ResponseEntity} instance
270250
*/
271-
protected ResponseEntity<Object> handleHttpMediaTypeNotSupported(HttpMediaTypeNotSupportedException ex,
272-
HttpHeaders headers, HttpStatus status, WebRequest request) {
251+
protected ResponseEntity<Object> handleHttpMediaTypeNotSupported(
252+
HttpMediaTypeNotSupportedException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
273253

274254
List<MediaType> mediaTypes = ex.getSupportedMediaTypes();
275255
if (!CollectionUtils.isEmpty(mediaTypes)) {
@@ -288,8 +268,8 @@ protected ResponseEntity<Object> handleHttpMediaTypeNotSupported(HttpMediaTypeNo
288268
* @param request the current request
289269
* @return a {@code ResponseEntity} instance
290270
*/
291-
protected ResponseEntity<Object> handleHttpMediaTypeNotAcceptable(HttpMediaTypeNotAcceptableException ex,
292-
HttpHeaders headers, HttpStatus status, WebRequest request) {
271+
protected ResponseEntity<Object> handleHttpMediaTypeNotAcceptable(
272+
HttpMediaTypeNotAcceptableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
293273

294274
return handleExceptionInternal(ex, null, headers, status, request);
295275
}
@@ -304,8 +284,8 @@ protected ResponseEntity<Object> handleHttpMediaTypeNotAcceptable(HttpMediaTypeN
304284
* @return a {@code ResponseEntity} instance
305285
* @since 4.2
306286
*/
307-
protected ResponseEntity<Object> handleMissingPathVariable(MissingPathVariableException ex,
308-
HttpHeaders headers, HttpStatus status, WebRequest request) {
287+
protected ResponseEntity<Object> handleMissingPathVariable(
288+
MissingPathVariableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
309289

310290
return handleExceptionInternal(ex, null, headers, status, request);
311291
}
@@ -319,8 +299,8 @@ protected ResponseEntity<Object> handleMissingPathVariable(MissingPathVariableEx
319299
* @param request the current request
320300
* @return a {@code ResponseEntity} instance
321301
*/
322-
protected ResponseEntity<Object> handleMissingServletRequestParameter(MissingServletRequestParameterException ex,
323-
HttpHeaders headers, HttpStatus status, WebRequest request) {
302+
protected ResponseEntity<Object> handleMissingServletRequestParameter(
303+
MissingServletRequestParameterException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
324304

325305
return handleExceptionInternal(ex, null, headers, status, request);
326306
}
@@ -334,8 +314,8 @@ protected ResponseEntity<Object> handleMissingServletRequestParameter(MissingSer
334314
* @param request the current request
335315
* @return a {@code ResponseEntity} instance
336316
*/
337-
protected ResponseEntity<Object> handleServletRequestBindingException(ServletRequestBindingException ex,
338-
HttpHeaders headers, HttpStatus status, WebRequest request) {
317+
protected ResponseEntity<Object> handleServletRequestBindingException(
318+
ServletRequestBindingException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
339319

340320
return handleExceptionInternal(ex, null, headers, status, request);
341321
}
@@ -349,8 +329,8 @@ protected ResponseEntity<Object> handleServletRequestBindingException(ServletReq
349329
* @param request the current request
350330
* @return a {@code ResponseEntity} instance
351331
*/
352-
protected ResponseEntity<Object> handleConversionNotSupported(ConversionNotSupportedException ex,
353-
HttpHeaders headers, HttpStatus status, WebRequest request) {
332+
protected ResponseEntity<Object> handleConversionNotSupported(
333+
ConversionNotSupportedException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
354334

355335
return handleExceptionInternal(ex, null, headers, status, request);
356336
}
@@ -364,8 +344,8 @@ protected ResponseEntity<Object> handleConversionNotSupported(ConversionNotSuppo
364344
* @param request the current request
365345
* @return a {@code ResponseEntity} instance
366346
*/
367-
protected ResponseEntity<Object> handleTypeMismatch(TypeMismatchException ex, HttpHeaders headers,
368-
HttpStatus status, WebRequest request) {
347+
protected ResponseEntity<Object> handleTypeMismatch(
348+
TypeMismatchException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
369349

370350
return handleExceptionInternal(ex, null, headers, status, request);
371351
}
@@ -379,8 +359,8 @@ protected ResponseEntity<Object> handleTypeMismatch(TypeMismatchException ex, Ht
379359
* @param request the current request
380360
* @return a {@code ResponseEntity} instance
381361
*/
382-
protected ResponseEntity<Object> handleHttpMessageNotReadable(HttpMessageNotReadableException ex,
383-
HttpHeaders headers, HttpStatus status, WebRequest request) {
362+
protected ResponseEntity<Object> handleHttpMessageNotReadable(
363+
HttpMessageNotReadableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
384364

385365
return handleExceptionInternal(ex, null, headers, status, request);
386366
}
@@ -394,8 +374,8 @@ protected ResponseEntity<Object> handleHttpMessageNotReadable(HttpMessageNotRead
394374
* @param request the current request
395375
* @return a {@code ResponseEntity} instance
396376
*/
397-
protected ResponseEntity<Object> handleHttpMessageNotWritable(HttpMessageNotWritableException ex,
398-
HttpHeaders headers, HttpStatus status, WebRequest request) {
377+
protected ResponseEntity<Object> handleHttpMessageNotWritable(
378+
HttpMessageNotWritableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
399379

400380
return handleExceptionInternal(ex, null, headers, status, request);
401381
}
@@ -409,8 +389,8 @@ protected ResponseEntity<Object> handleHttpMessageNotWritable(HttpMessageNotWrit
409389
* @param request the current request
410390
* @return a {@code ResponseEntity} instance
411391
*/
412-
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex,
413-
HttpHeaders headers, HttpStatus status, WebRequest request) {
392+
protected ResponseEntity<Object> handleMethodArgumentNotValid(
393+
MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
414394

415395
return handleExceptionInternal(ex, null, headers, status, request);
416396
}
@@ -424,8 +404,8 @@ protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotV
424404
* @param request the current request
425405
* @return a {@code ResponseEntity} instance
426406
*/
427-
protected ResponseEntity<Object> handleMissingServletRequestPart(MissingServletRequestPartException ex,
428-
HttpHeaders headers, HttpStatus status, WebRequest request) {
407+
protected ResponseEntity<Object> handleMissingServletRequestPart(
408+
MissingServletRequestPartException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
429409

430410
return handleExceptionInternal(ex, null, headers, status, request);
431411
}
@@ -439,8 +419,8 @@ protected ResponseEntity<Object> handleMissingServletRequestPart(MissingServletR
439419
* @param request the current request
440420
* @return a {@code ResponseEntity} instance
441421
*/
442-
protected ResponseEntity<Object> handleBindException(BindException ex, HttpHeaders headers,
443-
HttpStatus status, WebRequest request) {
422+
protected ResponseEntity<Object> handleBindException(
423+
BindException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
444424

445425
return handleExceptionInternal(ex, null, headers, status, request);
446426
}
@@ -489,4 +469,24 @@ protected ResponseEntity<Object> handleAsyncRequestTimeoutException(
489469
return handleExceptionInternal(ex, null, headers, status, webRequest);
490470
}
491471

472+
/**
473+
* A single place to customize the response body of all Exception types.
474+
* <p>The default implementation sets the {@link WebUtils#ERROR_EXCEPTION_ATTRIBUTE}
475+
* request attribute and creates a {@link ResponseEntity} from the given
476+
* body, headers, and status.
477+
* @param ex the exception
478+
* @param body the body for the response
479+
* @param headers the headers for the response
480+
* @param status the response status
481+
* @param request the current request
482+
*/
483+
protected ResponseEntity<Object> handleExceptionInternal(
484+
Exception ex, Object body, HttpHeaders headers, HttpStatus status, WebRequest request) {
485+
486+
if (HttpStatus.INTERNAL_SERVER_ERROR.equals(status)) {
487+
request.setAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE, ex, WebRequest.SCOPE_REQUEST);
488+
}
489+
return new ResponseEntity<Object>(body, headers, status);
490+
}
491+
492492
}

0 commit comments

Comments
 (0)