Skip to content

Commit 318d04c

Browse files
committed
Explicit coverage of root vs cause exception matching in MVC ref docs
Issue: SPR-16743 (cherry picked from commit a200df6)
1 parent d9ff109 commit 318d04c

File tree

3 files changed

+83
-100
lines changed

3 files changed

+83
-100
lines changed

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

Lines changed: 40 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2018 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.
@@ -25,7 +25,6 @@
2525
import org.springframework.beans.factory.InitializingBean;
2626
import org.springframework.beans.factory.config.BeanDefinition;
2727
import org.springframework.beans.factory.config.BeanDefinitionHolder;
28-
import org.springframework.beans.factory.config.BeanReference;
2928
import org.springframework.beans.factory.config.RuntimeBeanReference;
3029
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
3130
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
@@ -53,13 +52,10 @@
5352
import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter;
5453
import org.springframework.http.converter.xml.SourceHttpMessageConverter;
5554
import org.springframework.util.ClassUtils;
56-
import org.springframework.util.StringUtils;
5755
import org.springframework.util.xml.DomUtils;
5856
import org.springframework.web.HttpRequestHandler;
5957
import org.springframework.web.accept.ContentNegotiationManager;
6058
import org.springframework.web.accept.ContentNegotiationManagerFactoryBean;
61-
import org.springframework.web.bind.annotation.ExceptionHandler;
62-
import org.springframework.web.bind.annotation.ResponseStatus;
6359
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
6460
import org.springframework.web.bind.support.WebArgumentResolver;
6561
import org.springframework.web.method.support.CompositeUriComponentsContributor;
@@ -110,10 +106,10 @@
110106
*
111107
* <p>This class registers the following {@link HandlerExceptionResolver}s:
112108
* <ul>
113-
* <li>{@link ExceptionHandlerExceptionResolver} for handling exceptions
114-
* through @{@link ExceptionHandler} methods.
109+
* <li>{@link ExceptionHandlerExceptionResolver} for handling exceptions through
110+
* {@link org.springframework.web.bind.annotation.ExceptionHandler} methods.
115111
* <li>{@link ResponseStatusExceptionResolver} for exceptions annotated
116-
* with @{@link ResponseStatus}.
112+
* with {@link org.springframework.web.bind.annotation.ResponseStatus}.
117113
* <li>{@link DefaultHandlerExceptionResolver} for resolving known Spring
118114
* exception types
119115
* </ul>
@@ -155,6 +151,7 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
155151

156152
public static final String CONTENT_NEGOTIATION_MANAGER_BEAN_NAME = "mvcContentNegotiationManager";
157153

154+
158155
private static final boolean javaxValidationPresent =
159156
ClassUtils.isPresent("javax.validation.Validator",
160157
AnnotationDrivenBeanDefinitionParser.class.getClassLoader());
@@ -210,8 +207,8 @@ else if (element.hasAttribute("enableMatrixVariables")) {
210207
configurePathMatchingProperties(handlerMappingDef, element, parserContext);
211208
readerContext.getRegistry().registerBeanDefinition(HANDLER_MAPPING_BEAN_NAME , handlerMappingDef);
212209

213-
RuntimeBeanReference corsConfigurationsRef = MvcNamespaceUtils.registerCorsConfigurations(null, parserContext, source);
214-
handlerMappingDef.getPropertyValues().add("corsConfigurations", corsConfigurationsRef);
210+
RuntimeBeanReference corsRef = MvcNamespaceUtils.registerCorsConfigurations(null, parserContext, source);
211+
handlerMappingDef.getPropertyValues().add("corsConfigurations", corsRef);
215212

216213
RuntimeBeanReference conversionService = getConversionService(element, source, parserContext);
217214
RuntimeBeanReference validator = getValidator(element, source, parserContext);
@@ -285,44 +282,40 @@ else if (element.hasAttribute("ignoreDefaultModelOnRedirect")) {
285282
mappedCsInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(1, csInterceptorDef);
286283
String mappedInterceptorName = readerContext.registerWithGeneratedName(mappedCsInterceptorDef);
287284

288-
RootBeanDefinition exceptionHandlerExceptionResolver = new RootBeanDefinition(ExceptionHandlerExceptionResolver.class);
289-
exceptionHandlerExceptionResolver.setSource(source);
290-
exceptionHandlerExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
291-
exceptionHandlerExceptionResolver.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);
292-
exceptionHandlerExceptionResolver.getPropertyValues().add("messageConverters", messageConverters);
293-
exceptionHandlerExceptionResolver.getPropertyValues().add("order", 0);
294-
addResponseBodyAdvice(exceptionHandlerExceptionResolver);
295-
285+
RootBeanDefinition methodExceptionResolver = new RootBeanDefinition(ExceptionHandlerExceptionResolver.class);
286+
methodExceptionResolver.setSource(source);
287+
methodExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
288+
methodExceptionResolver.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);
289+
methodExceptionResolver.getPropertyValues().add("messageConverters", messageConverters);
290+
methodExceptionResolver.getPropertyValues().add("order", 0);
291+
addResponseBodyAdvice(methodExceptionResolver);
296292
if (argumentResolvers != null) {
297-
exceptionHandlerExceptionResolver.getPropertyValues().add("customArgumentResolvers", argumentResolvers);
293+
methodExceptionResolver.getPropertyValues().add("customArgumentResolvers", argumentResolvers);
298294
}
299295
if (returnValueHandlers != null) {
300-
exceptionHandlerExceptionResolver.getPropertyValues().add("customReturnValueHandlers", returnValueHandlers);
296+
methodExceptionResolver.getPropertyValues().add("customReturnValueHandlers", returnValueHandlers);
301297
}
298+
String methodExResolverName = readerContext.registerWithGeneratedName(methodExceptionResolver);
302299

303-
String methodExceptionResolverName = readerContext.registerWithGeneratedName(exceptionHandlerExceptionResolver);
304-
305-
RootBeanDefinition responseStatusExceptionResolver = new RootBeanDefinition(ResponseStatusExceptionResolver.class);
306-
responseStatusExceptionResolver.setSource(source);
307-
responseStatusExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
308-
responseStatusExceptionResolver.getPropertyValues().add("order", 1);
309-
String responseStatusExceptionResolverName =
310-
readerContext.registerWithGeneratedName(responseStatusExceptionResolver);
300+
RootBeanDefinition statusExceptionResolver = new RootBeanDefinition(ResponseStatusExceptionResolver.class);
301+
statusExceptionResolver.setSource(source);
302+
statusExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
303+
statusExceptionResolver.getPropertyValues().add("order", 1);
304+
String statusExResolverName = readerContext.registerWithGeneratedName(statusExceptionResolver);
311305

312306
RootBeanDefinition defaultExceptionResolver = new RootBeanDefinition(DefaultHandlerExceptionResolver.class);
313307
defaultExceptionResolver.setSource(source);
314308
defaultExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
315309
defaultExceptionResolver.getPropertyValues().add("order", 2);
316-
String defaultExceptionResolverName =
317-
readerContext.registerWithGeneratedName(defaultExceptionResolver);
310+
String defaultExResolverName = readerContext.registerWithGeneratedName(defaultExceptionResolver);
318311

319312
parserContext.registerComponent(new BeanComponentDefinition(handlerMappingDef, HANDLER_MAPPING_BEAN_NAME));
320313
parserContext.registerComponent(new BeanComponentDefinition(handlerAdapterDef, HANDLER_ADAPTER_BEAN_NAME));
321-
parserContext.registerComponent(new BeanComponentDefinition(uriCompContribDef, uriCompContribName));
322-
parserContext.registerComponent(new BeanComponentDefinition(exceptionHandlerExceptionResolver, methodExceptionResolverName));
323-
parserContext.registerComponent(new BeanComponentDefinition(responseStatusExceptionResolver, responseStatusExceptionResolverName));
324-
parserContext.registerComponent(new BeanComponentDefinition(defaultExceptionResolver, defaultExceptionResolverName));
325-
parserContext.registerComponent(new BeanComponentDefinition(mappedCsInterceptorDef, mappedInterceptorName));
314+
parserContext.registerComponent(new BeanComponentDefinition(uriContributorDef, uriContributorName));
315+
parserContext.registerComponent(new BeanComponentDefinition(mappedInterceptorDef, mappedInterceptorName));
316+
parserContext.registerComponent(new BeanComponentDefinition(methodExceptionResolver, methodExResolverName));
317+
parserContext.registerComponent(new BeanComponentDefinition(statusExceptionResolver, statusExResolverName));
318+
parserContext.registerComponent(new BeanComponentDefinition(defaultExceptionResolver, defaultExResolverName));
326319

327320
// Ensure BeanNameUrlHandlerMapping (SPR-8289) and default HandlerAdapters are not "turned off"
328321
MvcNamespaceUtils.registerDefaultComponents(parserContext, source);
@@ -380,8 +373,8 @@ else if (javaxValidationPresent) {
380373
}
381374
}
382375

383-
private RuntimeBeanReference getContentNegotiationManager(Element element, Object source,
384-
ParserContext parserContext) {
376+
private RuntimeBeanReference getContentNegotiationManager(
377+
Element element, Object source, ParserContext parserContext) {
385378

386379
RuntimeBeanReference beanRef;
387380
if (element.hasAttribute("content-negotiation-manager")) {
@@ -402,8 +395,8 @@ private RuntimeBeanReference getContentNegotiationManager(Element element, Objec
402395
return beanRef;
403396
}
404397

405-
private void configurePathMatchingProperties(RootBeanDefinition handlerMappingDef, Element element,
406-
ParserContext parserContext) {
398+
private void configurePathMatchingProperties(
399+
RootBeanDefinition handlerMappingDef, Element element, ParserContext parserContext) {
407400

408401
Element pathMatchingElement = DomUtils.getChildElementByTagName(element, "path-matching");
409402
if (pathMatchingElement != null) {
@@ -462,15 +455,13 @@ private RuntimeBeanReference getMessageCodesResolver(Element element) {
462455

463456
private String getAsyncTimeout(Element element) {
464457
Element asyncElement = DomUtils.getChildElementByTagName(element, "async-support");
465-
return (asyncElement != null) ? asyncElement.getAttribute("default-timeout") : null;
458+
return (asyncElement != null ? asyncElement.getAttribute("default-timeout") : null);
466459
}
467460

468461
private RuntimeBeanReference getAsyncExecutor(Element element) {
469462
Element asyncElement = DomUtils.getChildElementByTagName(element, "async-support");
470-
if (asyncElement != null) {
471-
if (asyncElement.hasAttribute("task-executor")) {
472-
return new RuntimeBeanReference(asyncElement.getAttribute("task-executor"));
473-
}
463+
if (asyncElement != null && asyncElement.hasAttribute("task-executor")) {
464+
return new RuntimeBeanReference(asyncElement.getAttribute("task-executor"));
474465
}
475466
return null;
476467
}
@@ -571,7 +562,8 @@ private ManagedList<?> getMessageConverters(Element element, Object source, Pars
571562
}
572563

573564
if (jackson2XmlPresent) {
574-
RootBeanDefinition jacksonConverterDef = createConverterDefinition(MappingJackson2XmlHttpMessageConverter.class, source);
565+
Class<?> type = MappingJackson2XmlHttpMessageConverter.class;
566+
RootBeanDefinition jacksonConverterDef = createConverterDefinition(type, source);
575567
GenericBeanDefinition jacksonFactoryDef = createObjectMapperFactoryDefinition(source);
576568
jacksonFactoryDef.getPropertyValues().add("createXmlMapper", true);
577569
jacksonConverterDef.getConstructorArgumentValues().addIndexedArgumentValue(0, jacksonFactoryDef);
@@ -582,7 +574,8 @@ else if (jaxb2Present) {
582574
}
583575

584576
if (jackson2Present) {
585-
RootBeanDefinition jacksonConverterDef = createConverterDefinition(MappingJackson2HttpMessageConverter.class, source);
577+
Class<?> type = MappingJackson2HttpMessageConverter.class;
578+
RootBeanDefinition jacksonConverterDef = createConverterDefinition(type, source);
586579
GenericBeanDefinition jacksonFactoryDef = createObjectMapperFactoryDefinition(source);
587580
jacksonConverterDef.getConstructorArgumentValues().addIndexedArgumentValue(0, jacksonFactoryDef);
588581
messageConverters.add(jacksonConverterDef);
@@ -609,7 +602,6 @@ private RootBeanDefinition createConverterDefinition(Class<?> converterClass, Ob
609602
return beanDefinition;
610603
}
611604

612-
613605
private ManagedList<Object> extractBeanSubElements(Element parentElement, ParserContext parserContext) {
614606
ManagedList<Object> list = new ManagedList<Object>();
615607
list.setSource(parserContext.extractSource(parentElement));
@@ -620,27 +612,6 @@ private ManagedList<Object> extractBeanSubElements(Element parentElement, Parser
620612
return list;
621613
}
622614

623-
private ManagedList<BeanReference> extractBeanRefSubElements(Element parentElement, ParserContext parserContext){
624-
ManagedList<BeanReference> list = new ManagedList<BeanReference>();
625-
list.setSource(parserContext.extractSource(parentElement));
626-
for (Element refElement : DomUtils.getChildElementsByTagName(parentElement, "ref")) {
627-
BeanReference reference;
628-
if (StringUtils.hasText("bean")) {
629-
reference = new RuntimeBeanReference(refElement.getAttribute("bean"),false);
630-
list.add(reference);
631-
}
632-
else if (StringUtils.hasText("parent")){
633-
reference = new RuntimeBeanReference(refElement.getAttribute("parent"),true);
634-
list.add(reference);
635-
}
636-
else {
637-
parserContext.getReaderContext().error("'bean' or 'parent' attribute is required for <ref> element",
638-
parserContext.extractSource(parentElement));
639-
}
640-
}
641-
return list;
642-
}
643-
644615

645616
/**
646617
* A FactoryBean for a CompositeUriComponentsContributor that obtains the
@@ -671,7 +642,7 @@ public void afterPropertiesSet() {
671642
}
672643

673644
@Override
674-
public CompositeUriComponentsContributor getObject() throws Exception {
645+
public CompositeUriComponentsContributor getObject() {
675646
return this.uriComponentsContributor;
676647
}
677648

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

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2018 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.
@@ -63,8 +63,6 @@
6363
import org.springframework.web.HttpRequestHandler;
6464
import org.springframework.web.accept.ContentNegotiationManager;
6565
import org.springframework.web.bind.WebDataBinder;
66-
import org.springframework.web.bind.annotation.ExceptionHandler;
67-
import org.springframework.web.bind.annotation.ResponseStatus;
6866
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
6967
import org.springframework.web.context.ServletContextAware;
7068
import org.springframework.web.cors.CorsConfiguration;
@@ -134,10 +132,10 @@
134132
* <p>Registers a {@link HandlerExceptionResolverComposite} with this chain of
135133
* exception resolvers:
136134
* <ul>
137-
* <li>{@link ExceptionHandlerExceptionResolver} for handling exceptions
138-
* through @{@link ExceptionHandler} methods.
139-
* <li>{@link ResponseStatusExceptionResolver} for exceptions annotated
140-
* with @{@link ResponseStatus}.
135+
* <li>{@link ExceptionHandlerExceptionResolver} for handling exceptions through
136+
* {@link org.springframework.web.bind.annotation.ExceptionHandler} methods.
137+
* <li>{@link ResponseStatusExceptionResolver} for exceptions annotated with
138+
* {@link org.springframework.web.bind.annotation.ResponseStatus}.
141139
* <li>{@link DefaultHandlerExceptionResolver} for resolving known Spring
142140
* exception types
143141
* </ul>
@@ -865,12 +863,11 @@ protected void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> ex
865863
* A method available to subclasses for adding default {@link HandlerExceptionResolver}s.
866864
* <p>Adds the following exception resolvers:
867865
* <ul>
868-
* <li>{@link ExceptionHandlerExceptionResolver}
869-
* for handling exceptions through @{@link ExceptionHandler} methods.
870-
* <li>{@link ResponseStatusExceptionResolver}
871-
* for exceptions annotated with @{@link ResponseStatus}.
872-
* <li>{@link DefaultHandlerExceptionResolver}
873-
* for resolving known Spring exception types
866+
* <li>{@link ExceptionHandlerExceptionResolver} for handling exceptions through
867+
* {@link org.springframework.web.bind.annotation.ExceptionHandler} methods.
868+
* <li>{@link ResponseStatusExceptionResolver} for exceptions annotated with
869+
* {@link org.springframework.web.bind.annotation.ResponseStatus}.
870+
* <li>{@link DefaultHandlerExceptionResolver} for resolving known Spring exception types
874871
* </ul>
875872
*/
876873
protected final void addDefaultHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {

0 commit comments

Comments
 (0)