Find @ResponseStatus recursively on getCause()

Issue: SPR-12903
master
Rossen Stoyanchev 10 years ago
parent c172d9d745
commit 26cfe5795f
  1. 6
      spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/annotation/ResponseStatusExceptionResolver.java
  2. 20
      spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/annotation/ResponseStatusExceptionResolverTests.java
  3. 44
      spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ServletAnnotationControllerHandlerMethodTests.java

@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -61,6 +61,10 @@ public class ResponseStatusExceptionResolver extends AbstractHandlerExceptionRes
logger.warn("Handling of @ResponseStatus resulted in Exception", resolveEx);
}
}
else if (ex.getCause() != null && ex.getCause() instanceof Exception) {
ex = (Exception) ex.getCause();
return doResolveException(request, response, handler, ex);
}
return null;
}

@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,21 +16,23 @@
package org.springframework.web.servlet.mvc.annotation;
import static org.junit.Assert.*;
import java.util.Locale;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.TypeMismatchException;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.context.support.StaticMessageSource;
import org.springframework.http.HttpStatus;
import org.springframework.mock.web.test.MockHttpServletRequest;
import org.springframework.mock.web.test.MockHttpServletResponse;
import org.springframework.tests.sample.beans.ITestBean;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.servlet.ModelAndView;
import static org.junit.Assert.*;
/** @author Arjen Poutsma */
public class ResponseStatusExceptionResolverTests {
@ -93,6 +95,18 @@ public class ResponseStatusExceptionResolverTests {
assertNull("ModelAndView returned", mav);
}
// SPR-12903
@Test
public void nestedException() throws Exception {
Exception cause = new StatusCodeAndReasonMessageException();
TypeMismatchException ex = new TypeMismatchException("value", ITestBean.class, cause);
ModelAndView mav = exceptionResolver.resolveException(request, response, null, ex);
assertNotNull("No ModelAndView returned", mav);
assertTrue("No Empty ModelAndView returned", mav.isEmpty());
assertEquals("Invalid status code", 410, response.getStatus());
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@SuppressWarnings("serial")
private static class StatusCodeException extends Exception {

@ -113,6 +113,7 @@ import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
@ -284,6 +285,29 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
assertEquals("[1, 2]-org.springframework.tests.sample.beans.TestBean", response.getContentAsString());
}
// SPR-12903
@Test
public void pathVariableWithCustomConverter() throws Exception {
initServlet(new ApplicationContextInitializer<GenericWebApplicationContext>() {
@Override
public void initialize(GenericWebApplicationContext context) {
RootBeanDefinition csDef = new RootBeanDefinition(FormattingConversionServiceFactoryBean.class);
csDef.getPropertyValues().add("converters", new AnnotatedExceptionRaisingConverter());
RootBeanDefinition wbiDef = new RootBeanDefinition(ConfigurableWebBindingInitializer.class);
wbiDef.getPropertyValues().add("conversionService", csDef);
RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
adapterDef.getPropertyValues().add("webBindingInitializer", wbiDef);
context.registerBeanDefinition("handlerAdapter", adapterDef);
}
}, PathVariableWithCustomConverterController.class);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath/1");
MockHttpServletResponse response = new MockHttpServletResponse();
getServlet().service(request, response);
assertEquals(404, response.getStatus());
}
@Test
public void methodNotAllowed() throws Exception {
initServletWithControllers(MethodNotAllowedController.class);
@ -2370,6 +2394,26 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
}
@Controller
public static class PathVariableWithCustomConverterController {
@RequestMapping("/myPath/{id}")
public void myHandle(@PathVariable("id") ITestBean bean) throws Exception {
}
}
public static class AnnotatedExceptionRaisingConverter implements Converter<String, ITestBean> {
@Override
public ITestBean convert(String source) {
throw new NotFoundException();
}
@ResponseStatus(HttpStatus.NOT_FOUND)
private static class NotFoundException extends RuntimeException {
}
}
@Controller
public static class MethodNotAllowedController {

Loading…
Cancel
Save