Skip to content

Commit aa82da8

Browse files
committed
Set ResponseStatusExceptionResolver.messageSource in the MVC Java config
Issue: SPR-12380 (cherry picked from commit 17b9bde)
1 parent 16a4fe7 commit aa82da8

File tree

2 files changed

+77
-42
lines changed

2 files changed

+77
-42
lines changed

spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java

Lines changed: 44 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -87,53 +87,54 @@
8787
*
8888
* <p>This class registers the following {@link HandlerMapping}s:</p>
8989
* <ul>
90-
* <li>{@link RequestMappingHandlerMapping}
91-
* ordered at 0 for mapping requests to annotated controller methods.
92-
* <li>{@link HandlerMapping}
93-
* ordered at 1 to map URL paths directly to view names.
94-
* <li>{@link BeanNameUrlHandlerMapping}
95-
* ordered at 2 to map URL paths to controller bean names.
96-
* <li>{@link HandlerMapping}
97-
* ordered at {@code Integer.MAX_VALUE-1} to serve static resource requests.
98-
* <li>{@link HandlerMapping}
99-
* ordered at {@code Integer.MAX_VALUE} to forward requests to the default servlet.
90+
* <li>{@link RequestMappingHandlerMapping}
91+
* ordered at 0 for mapping requests to annotated controller methods.
92+
* <li>{@link HandlerMapping}
93+
* ordered at 1 to map URL paths directly to view names.
94+
* <li>{@link BeanNameUrlHandlerMapping}
95+
* ordered at 2 to map URL paths to controller bean names.
96+
* <li>{@link HandlerMapping}
97+
* ordered at {@code Integer.MAX_VALUE-1} to serve static resource requests.
98+
* <li>{@link HandlerMapping}
99+
* ordered at {@code Integer.MAX_VALUE} to forward requests to the default servlet.
100100
* </ul>
101101
*
102102
* <p>Registers these {@link HandlerAdapter}s:
103103
* <ul>
104-
* <li>{@link RequestMappingHandlerAdapter}
105-
* for processing requests with annotated controller methods.
106-
* <li>{@link HttpRequestHandlerAdapter}
107-
* for processing requests with {@link HttpRequestHandler}s.
108-
* <li>{@link SimpleControllerHandlerAdapter}
109-
* for processing requests with interface-based {@link Controller}s.
104+
* <li>{@link RequestMappingHandlerAdapter}
105+
* for processing requests with annotated controller methods.
106+
* <li>{@link HttpRequestHandlerAdapter}
107+
* for processing requests with {@link HttpRequestHandler}s.
108+
* <li>{@link SimpleControllerHandlerAdapter}
109+
* for processing requests with interface-based {@link Controller}s.
110110
* </ul>
111111
*
112112
* <p>Registers a {@link HandlerExceptionResolverComposite} with this chain of
113113
* exception resolvers:
114114
* <ul>
115-
* <li>{@link ExceptionHandlerExceptionResolver} for handling exceptions
116-
* through @{@link ExceptionHandler} methods.
117-
* <li>{@link ResponseStatusExceptionResolver} for exceptions annotated
118-
* with @{@link ResponseStatus}.
119-
* <li>{@link DefaultHandlerExceptionResolver} for resolving known Spring
120-
* exception types
115+
* <li>{@link ExceptionHandlerExceptionResolver} for handling exceptions
116+
* through @{@link ExceptionHandler} methods.
117+
* <li>{@link ResponseStatusExceptionResolver} for exceptions annotated
118+
* with @{@link ResponseStatus}.
119+
* <li>{@link DefaultHandlerExceptionResolver} for resolving known Spring
120+
* exception types
121121
* </ul>
122122
*
123123
* <p>Both the {@link RequestMappingHandlerAdapter} and the
124124
* {@link ExceptionHandlerExceptionResolver} are configured with default
125125
* instances of the following by default:
126126
* <ul>
127-
* <li>A {@link ContentNegotiationManager}
128-
* <li>A {@link DefaultFormattingConversionService}
129-
* <li>A {@link org.springframework.validation.beanvalidation.OptionalValidatorFactoryBean}
130-
* if a JSR-303 implementation is available on the classpath
131-
* <li>A range of {@link HttpMessageConverter}s depending on the 3rd party
132-
* libraries available on the classpath.
127+
* <li>a {@link ContentNegotiationManager}
128+
* <li>a {@link DefaultFormattingConversionService}
129+
* <li>a {@link org.springframework.validation.beanvalidation.OptionalValidatorFactoryBean}
130+
* if a JSR-303 implementation is available on the classpath
131+
* <li>a range of {@link HttpMessageConverter}s depending on the third-party
132+
* libraries available on the classpath.
133133
* </ul>
134134
*
135135
* @author Rossen Stoyanchev
136136
* @author Brian Clozel
137+
* @author Sebastien Deleuze
137138
* @since 3.1
138139
* @see EnableWebMvc
139140
* @see WebMvcConfigurer
@@ -373,9 +374,9 @@ protected void configureDefaultServletHandling(DefaultServletHandlerConfigurer c
373374
* through annotated controller methods. Consider overriding one of these
374375
* other more fine-grained methods:
375376
* <ul>
376-
* <li>{@link #addArgumentResolvers} for adding custom argument resolvers.
377-
* <li>{@link #addReturnValueHandlers} for adding custom return value handlers.
378-
* <li>{@link #configureMessageConverters} for adding custom message converters.
377+
* <li>{@link #addArgumentResolvers} for adding custom argument resolvers.
378+
* <li>{@link #addReturnValueHandlers} for adding custom return value handlers.
379+
* <li>{@link #configureMessageConverters} for adding custom message converters.
379380
* </ul>
380381
*/
381382
@Bean
@@ -653,23 +654,26 @@ protected void configureHandlerExceptionResolvers(List<HandlerExceptionResolver>
653654
* A method available to subclasses for adding default {@link HandlerExceptionResolver}s.
654655
* <p>Adds the following exception resolvers:
655656
* <ul>
656-
* <li>{@link ExceptionHandlerExceptionResolver}
657-
* for handling exceptions through @{@link ExceptionHandler} methods.
658-
* <li>{@link ResponseStatusExceptionResolver}
659-
* for exceptions annotated with @{@link ResponseStatus}.
660-
* <li>{@link DefaultHandlerExceptionResolver}
661-
* for resolving known Spring exception types
657+
* <li>{@link ExceptionHandlerExceptionResolver}
658+
* for handling exceptions through @{@link ExceptionHandler} methods.
659+
* <li>{@link ResponseStatusExceptionResolver}
660+
* for exceptions annotated with @{@link ResponseStatus}.
661+
* <li>{@link DefaultHandlerExceptionResolver}
662+
* for resolving known Spring exception types
662663
* </ul>
663664
*/
664665
protected final void addDefaultHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
665666
ExceptionHandlerExceptionResolver exceptionHandlerExceptionResolver = new ExceptionHandlerExceptionResolver();
666-
exceptionHandlerExceptionResolver.setApplicationContext(this.applicationContext);
667667
exceptionHandlerExceptionResolver.setContentNegotiationManager(mvcContentNegotiationManager());
668668
exceptionHandlerExceptionResolver.setMessageConverters(getMessageConverters());
669+
exceptionHandlerExceptionResolver.setApplicationContext(this.applicationContext);
669670
exceptionHandlerExceptionResolver.afterPropertiesSet();
670-
671671
exceptionResolvers.add(exceptionHandlerExceptionResolver);
672-
exceptionResolvers.add(new ResponseStatusExceptionResolver());
672+
673+
ResponseStatusExceptionResolver responseStatusExceptionResolver = new ResponseStatusExceptionResolver();
674+
responseStatusExceptionResolver.setMessageSource(this.applicationContext);
675+
exceptionResolvers.add(responseStatusExceptionResolver);
676+
673677
exceptionResolvers.add(new DefaultHandlerExceptionResolver());
674678
}
675679

spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportTests.java

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,28 +17,35 @@
1717
package org.springframework.web.servlet.config.annotation;
1818

1919
import java.util.List;
20+
import java.util.Locale;
2021
import javax.servlet.http.HttpServletRequest;
2122

2223
import org.joda.time.DateTime;
2324
import org.junit.Before;
2425
import org.junit.Test;
2526

27+
import org.springframework.context.MessageSource;
2628
import org.springframework.context.annotation.Bean;
2729
import org.springframework.context.annotation.Configuration;
2830
import org.springframework.context.annotation.Scope;
2931
import org.springframework.context.annotation.ScopedProxyMode;
32+
import org.springframework.context.i18n.LocaleContextHolder;
33+
import org.springframework.context.support.StaticMessageSource;
3034
import org.springframework.core.convert.ConversionService;
3135
import org.springframework.format.annotation.DateTimeFormat;
3236
import org.springframework.format.annotation.DateTimeFormat.ISO;
3337
import org.springframework.format.support.FormattingConversionService;
3438
import org.springframework.http.HttpEntity;
39+
import org.springframework.http.HttpStatus;
3540
import org.springframework.mock.web.test.MockHttpServletRequest;
41+
import org.springframework.mock.web.test.MockHttpServletResponse;
3642
import org.springframework.mock.web.test.MockServletContext;
3743
import org.springframework.stereotype.Controller;
3844
import org.springframework.validation.Validator;
3945
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
4046
import org.springframework.web.bind.annotation.PathVariable;
4147
import org.springframework.web.bind.annotation.RequestMapping;
48+
import org.springframework.web.bind.annotation.ResponseStatus;
4249
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
4350
import org.springframework.web.context.WebApplicationContext;
4451
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
@@ -63,6 +70,7 @@
6370
*
6471
* @author Rossen Stoyanchev
6572
* @author Juergen Hoeller
73+
* @author Sebastien Deleuze
6674
*/
6775
public class WebMvcConfigurationSupportTests {
6876

@@ -169,10 +177,9 @@ public void uriComponentsContributor() throws Exception {
169177
@Test
170178
public void handlerExceptionResolver() throws Exception {
171179
HandlerExceptionResolverComposite compositeResolver =
172-
this.wac.getBean("handlerExceptionResolver", HandlerExceptionResolverComposite.class);
180+
this.wac.getBean("handlerExceptionResolver", HandlerExceptionResolverComposite.class);
173181

174182
assertEquals(0, compositeResolver.getOrder());
175-
176183
List<HandlerExceptionResolver> expectedResolvers = compositeResolver.getExceptionResolvers();
177184

178185
assertEquals(ExceptionHandlerExceptionResolver.class, expectedResolvers.get(0).getClass());
@@ -181,6 +188,18 @@ public void handlerExceptionResolver() throws Exception {
181188

182189
ExceptionHandlerExceptionResolver eher = (ExceptionHandlerExceptionResolver) expectedResolvers.get(0);
183190
assertNotNull(eher.getApplicationContext());
191+
192+
LocaleContextHolder.setLocale(Locale.ENGLISH);
193+
try {
194+
ResponseStatusExceptionResolver rser = (ResponseStatusExceptionResolver) expectedResolvers.get(1);
195+
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/");
196+
MockHttpServletResponse response = new MockHttpServletResponse();
197+
rser.resolveException(request, response, this.wac.getBean(TestController.class), new UserAlreadyExistsException());
198+
assertEquals("User already exists!", response.getErrorMessage());
199+
}
200+
finally {
201+
LocaleContextHolder.resetLocaleContext();
202+
}
184203
}
185204

186205

@@ -192,6 +211,13 @@ public static class TestConfig {
192211
public TestController testController() {
193212
return new TestController();
194213
}
214+
215+
@Bean
216+
public MessageSource messageSource() {
217+
StaticMessageSource messageSource = new StaticMessageSource();
218+
messageSource.addMessage("exception.user.exists", Locale.ENGLISH, "User already exists!");
219+
return messageSource;
220+
}
195221
}
196222

197223

@@ -229,4 +255,9 @@ public void handle() {
229255
}
230256
}
231257

258+
259+
@ResponseStatus(value = HttpStatus.BAD_REQUEST, reason = "exception.user.exists")
260+
public static class UserAlreadyExistsException extends RuntimeException {
261+
}
262+
232263
}

0 commit comments

Comments
 (0)