Skip to content

Commit 48b963a

Browse files
committed
Add error request attribute for 500 reponses
DefaultHandlerExceptionResolver and ResponseEntityExceptionHandler now both set the "javax.servlet.error.exception" request attribute to the raised exception, allowing custom error pages configured via web.xml. Issue: SPR-9653
1 parent 787d8f5 commit 48b963a

File tree

4 files changed

+39
-2
lines changed

4 files changed

+39
-2
lines changed

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,10 @@ else if (ex instanceof BindException) {
179179
protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body,
180180
HttpHeaders headers, HttpStatus status, WebRequest request) {
181181

182+
if (HttpStatus.INTERNAL_SERVER_ERROR.equals(status)) {
183+
request.setAttribute("javax.servlet.error.exception", ex, WebRequest.SCOPE_REQUEST);
184+
}
185+
182186
return new ResponseEntity<Object>(body, headers, status);
183187
}
184188

spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/support/DefaultHandlerExceptionResolver.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -294,10 +294,21 @@ protected ModelAndView handleServletRequestBindingException(ServletRequestBindin
294294
protected ModelAndView handleConversionNotSupported(ConversionNotSupportedException ex,
295295
HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
296296

297-
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
297+
sendServerError(ex, request, response);
298298
return new ModelAndView();
299299
}
300300

301+
/**
302+
* Invoked to send a server error. Sets the status to 500 and also sets the
303+
* request attribute "javax.servlet.error.exception" to the Exception.
304+
*/
305+
protected void sendServerError(Exception ex,
306+
HttpServletRequest request, HttpServletResponse response) throws IOException {
307+
308+
request.setAttribute("javax.servlet.error.exception", ex);
309+
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
310+
}
311+
301312
/**
302313
* Handle the case when a {@link org.springframework.web.bind.WebDataBinder} conversion error occurs.
303314
* <p>The default implementation sends an HTTP 400 error, and returns an empty {@code ModelAndView}.
@@ -352,7 +363,7 @@ protected ModelAndView handleHttpMessageNotReadable(HttpMessageNotReadableExcept
352363
protected ModelAndView handleHttpMessageNotWritable(HttpMessageNotWritableException ex,
353364
HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
354365

355-
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
366+
sendServerError(ex, request, response);
356367
return new ModelAndView();
357368
}
358369

spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ResponseEntityExceptionHandlerTests.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package org.springframework.web.servlet.mvc.method.annotation;
1717

1818
import static org.junit.Assert.assertEquals;
19+
import static org.junit.Assert.assertSame;
1920
import static org.junit.Assert.assertTrue;
2021

2122
import java.lang.reflect.Method;
@@ -204,6 +205,12 @@ public void controllerAdvice() throws Exception {
204205

205206
private ResponseEntity<Object> testException(Exception ex) {
206207
ResponseEntity<Object> responseEntity = this.exceptionHandlerSupport.handleException(ex, this.request);
208+
209+
// SPR-9653
210+
if (HttpStatus.INTERNAL_SERVER_ERROR.equals(responseEntity.getStatusCode())) {
211+
assertSame(ex, this.servletRequest.getAttribute("javax.servlet.error.exception"));
212+
}
213+
207214
this.defaultExceptionResolver.resolveException(this.servletRequest, this.servletResponse, null, ex);
208215

209216
assertEquals(this.servletResponse.getStatus(), responseEntity.getStatusCode().value());

spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/support/DefaultHandlerExceptionResolverTests.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@
1818

1919
import static org.junit.Assert.assertEquals;
2020
import static org.junit.Assert.assertNotNull;
21+
import static org.junit.Assert.assertSame;
2122
import static org.junit.Assert.assertTrue;
2223

2324
import java.util.Collections;
2425

2526
import org.junit.Before;
2627
import org.junit.Test;
28+
import org.springframework.beans.ConversionNotSupportedException;
2729
import org.springframework.beans.TestBean;
2830
import org.springframework.beans.TypeMismatchException;
2931
import org.springframework.core.MethodParameter;
@@ -169,6 +171,19 @@ public void handleBindException() throws Exception {
169171
assertEquals("Invalid status code", 400, response.getStatus());
170172
}
171173

174+
@Test
175+
public void handleConversionNotSupportedException() throws Exception {
176+
ConversionNotSupportedException ex =
177+
new ConversionNotSupportedException(new Object(), String.class, new Exception());
178+
ModelAndView mav = exceptionResolver.resolveException(request, response, null, ex);
179+
assertNotNull("No ModelAndView returned", mav);
180+
assertTrue("No Empty ModelAndView returned", mav.isEmpty());
181+
assertEquals("Invalid status code", 500, response.getStatus());
182+
183+
// SPR-9653
184+
assertSame(ex, request.getAttribute("javax.servlet.error.exception"));
185+
}
186+
172187
public void handle(String arg) {
173188
}
174189

0 commit comments

Comments
 (0)