Skip to content

Commit 26cfe57

Browse files
committed
Find @ResponseStatus recursively on getCause()
Issue: SPR-12903
1 parent c172d9d commit 26cfe57

File tree

3 files changed

+66
-4
lines changed

3 files changed

+66
-4
lines changed

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2013 the original author or authors.
2+
* Copyright 2002-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -61,6 +61,10 @@ protected ModelAndView doResolveException(HttpServletRequest request, HttpServle
6161
logger.warn("Handling of @ResponseStatus resulted in Exception", resolveEx);
6262
}
6363
}
64+
else if (ex.getCause() != null && ex.getCause() instanceof Exception) {
65+
ex = (Exception) ex.getCause();
66+
return doResolveException(request, response, handler, ex);
67+
}
6468
return null;
6569
}
6670

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

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,21 +16,23 @@
1616

1717
package org.springframework.web.servlet.mvc.annotation;
1818

19+
import static org.junit.Assert.*;
20+
1921
import java.util.Locale;
2022

2123
import org.junit.Before;
2224
import org.junit.Test;
2325

26+
import org.springframework.beans.TypeMismatchException;
2427
import org.springframework.context.i18n.LocaleContextHolder;
2528
import org.springframework.context.support.StaticMessageSource;
2629
import org.springframework.http.HttpStatus;
2730
import org.springframework.mock.web.test.MockHttpServletRequest;
2831
import org.springframework.mock.web.test.MockHttpServletResponse;
32+
import org.springframework.tests.sample.beans.ITestBean;
2933
import org.springframework.web.bind.annotation.ResponseStatus;
3034
import org.springframework.web.servlet.ModelAndView;
3135

32-
import static org.junit.Assert.*;
33-
3436
/** @author Arjen Poutsma */
3537
public class ResponseStatusExceptionResolverTests {
3638

@@ -93,6 +95,18 @@ public void notAnnotated() {
9395
assertNull("ModelAndView returned", mav);
9496
}
9597

98+
// SPR-12903
99+
100+
@Test
101+
public void nestedException() throws Exception {
102+
Exception cause = new StatusCodeAndReasonMessageException();
103+
TypeMismatchException ex = new TypeMismatchException("value", ITestBean.class, cause);
104+
ModelAndView mav = exceptionResolver.resolveException(request, response, null, ex);
105+
assertNotNull("No ModelAndView returned", mav);
106+
assertTrue("No Empty ModelAndView returned", mav.isEmpty());
107+
assertEquals("Invalid status code", 410, response.getStatus());
108+
}
109+
96110
@ResponseStatus(HttpStatus.BAD_REQUEST)
97111
@SuppressWarnings("serial")
98112
private static class StatusCodeException extends Exception {

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

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@
113113
import org.springframework.web.bind.annotation.ExceptionHandler;
114114
import org.springframework.web.bind.annotation.InitBinder;
115115
import org.springframework.web.bind.annotation.ModelAttribute;
116+
import org.springframework.web.bind.annotation.PathVariable;
116117
import org.springframework.web.bind.annotation.RequestBody;
117118
import org.springframework.web.bind.annotation.RequestHeader;
118119
import org.springframework.web.bind.annotation.RequestMapping;
@@ -284,6 +285,29 @@ public void initialize(GenericWebApplicationContext context) {
284285
assertEquals("[1, 2]-org.springframework.tests.sample.beans.TestBean", response.getContentAsString());
285286
}
286287

288+
// SPR-12903
289+
290+
@Test
291+
public void pathVariableWithCustomConverter() throws Exception {
292+
initServlet(new ApplicationContextInitializer<GenericWebApplicationContext>() {
293+
@Override
294+
public void initialize(GenericWebApplicationContext context) {
295+
RootBeanDefinition csDef = new RootBeanDefinition(FormattingConversionServiceFactoryBean.class);
296+
csDef.getPropertyValues().add("converters", new AnnotatedExceptionRaisingConverter());
297+
RootBeanDefinition wbiDef = new RootBeanDefinition(ConfigurableWebBindingInitializer.class);
298+
wbiDef.getPropertyValues().add("conversionService", csDef);
299+
RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
300+
adapterDef.getPropertyValues().add("webBindingInitializer", wbiDef);
301+
context.registerBeanDefinition("handlerAdapter", adapterDef);
302+
}
303+
}, PathVariableWithCustomConverterController.class);
304+
305+
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath/1");
306+
MockHttpServletResponse response = new MockHttpServletResponse();
307+
getServlet().service(request, response);
308+
assertEquals(404, response.getStatus());
309+
}
310+
287311
@Test
288312
public void methodNotAllowed() throws Exception {
289313
initServletWithControllers(MethodNotAllowedController.class);
@@ -2370,6 +2394,26 @@ public ITestBean convert(String source) {
23702394
}
23712395
}
23722396

2397+
@Controller
2398+
public static class PathVariableWithCustomConverterController {
2399+
2400+
@RequestMapping("/myPath/{id}")
2401+
public void myHandle(@PathVariable("id") ITestBean bean) throws Exception {
2402+
}
2403+
}
2404+
2405+
public static class AnnotatedExceptionRaisingConverter implements Converter<String, ITestBean> {
2406+
2407+
@Override
2408+
public ITestBean convert(String source) {
2409+
throw new NotFoundException();
2410+
}
2411+
2412+
@ResponseStatus(HttpStatus.NOT_FOUND)
2413+
private static class NotFoundException extends RuntimeException {
2414+
}
2415+
}
2416+
23732417
@Controller
23742418
public static class MethodNotAllowedController {
23752419

0 commit comments

Comments
 (0)