Explicit coverage of root vs cause exception matching in MVC ref docs
Issue: SPR-16743
(cherry picked from commit a200df6)
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -25,7 +25,6 @@ import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.config.BeanReference;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
|
||||
@@ -53,13 +52,10 @@ import org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConvert
|
||||
import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter;
|
||||
import org.springframework.http.converter.xml.SourceHttpMessageConverter;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
import org.springframework.web.HttpRequestHandler;
|
||||
import org.springframework.web.accept.ContentNegotiationManager;
|
||||
import org.springframework.web.accept.ContentNegotiationManagerFactoryBean;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
|
||||
import org.springframework.web.bind.support.WebArgumentResolver;
|
||||
import org.springframework.web.method.support.CompositeUriComponentsContributor;
|
||||
@@ -110,10 +106,10 @@ import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolv
|
||||
*
|
||||
* <p>This class registers the following {@link HandlerExceptionResolver}s:
|
||||
* <ul>
|
||||
* <li>{@link ExceptionHandlerExceptionResolver} for handling exceptions
|
||||
* through @{@link ExceptionHandler} methods.
|
||||
* <li>{@link ExceptionHandlerExceptionResolver} for handling exceptions through
|
||||
* {@link org.springframework.web.bind.annotation.ExceptionHandler} methods.
|
||||
* <li>{@link ResponseStatusExceptionResolver} for exceptions annotated
|
||||
* with @{@link ResponseStatus}.
|
||||
* with {@link org.springframework.web.bind.annotation.ResponseStatus}.
|
||||
* <li>{@link DefaultHandlerExceptionResolver} for resolving known Spring
|
||||
* exception types
|
||||
* </ul>
|
||||
@@ -155,6 +151,7 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
public static final String CONTENT_NEGOTIATION_MANAGER_BEAN_NAME = "mvcContentNegotiationManager";
|
||||
|
||||
|
||||
private static final boolean javaxValidationPresent =
|
||||
ClassUtils.isPresent("javax.validation.Validator",
|
||||
AnnotationDrivenBeanDefinitionParser.class.getClassLoader());
|
||||
@@ -210,8 +207,8 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
|
||||
configurePathMatchingProperties(handlerMappingDef, element, parserContext);
|
||||
readerContext.getRegistry().registerBeanDefinition(HANDLER_MAPPING_BEAN_NAME , handlerMappingDef);
|
||||
|
||||
RuntimeBeanReference corsConfigurationsRef = MvcNamespaceUtils.registerCorsConfigurations(null, parserContext, source);
|
||||
handlerMappingDef.getPropertyValues().add("corsConfigurations", corsConfigurationsRef);
|
||||
RuntimeBeanReference corsRef = MvcNamespaceUtils.registerCorsConfigurations(null, parserContext, source);
|
||||
handlerMappingDef.getPropertyValues().add("corsConfigurations", corsRef);
|
||||
|
||||
RuntimeBeanReference conversionService = getConversionService(element, source, parserContext);
|
||||
RuntimeBeanReference validator = getValidator(element, source, parserContext);
|
||||
@@ -285,44 +282,40 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
|
||||
mappedCsInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(1, csInterceptorDef);
|
||||
String mappedInterceptorName = readerContext.registerWithGeneratedName(mappedCsInterceptorDef);
|
||||
|
||||
RootBeanDefinition exceptionHandlerExceptionResolver = new RootBeanDefinition(ExceptionHandlerExceptionResolver.class);
|
||||
exceptionHandlerExceptionResolver.setSource(source);
|
||||
exceptionHandlerExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
exceptionHandlerExceptionResolver.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);
|
||||
exceptionHandlerExceptionResolver.getPropertyValues().add("messageConverters", messageConverters);
|
||||
exceptionHandlerExceptionResolver.getPropertyValues().add("order", 0);
|
||||
addResponseBodyAdvice(exceptionHandlerExceptionResolver);
|
||||
|
||||
RootBeanDefinition methodExceptionResolver = new RootBeanDefinition(ExceptionHandlerExceptionResolver.class);
|
||||
methodExceptionResolver.setSource(source);
|
||||
methodExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
methodExceptionResolver.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);
|
||||
methodExceptionResolver.getPropertyValues().add("messageConverters", messageConverters);
|
||||
methodExceptionResolver.getPropertyValues().add("order", 0);
|
||||
addResponseBodyAdvice(methodExceptionResolver);
|
||||
if (argumentResolvers != null) {
|
||||
exceptionHandlerExceptionResolver.getPropertyValues().add("customArgumentResolvers", argumentResolvers);
|
||||
methodExceptionResolver.getPropertyValues().add("customArgumentResolvers", argumentResolvers);
|
||||
}
|
||||
if (returnValueHandlers != null) {
|
||||
exceptionHandlerExceptionResolver.getPropertyValues().add("customReturnValueHandlers", returnValueHandlers);
|
||||
methodExceptionResolver.getPropertyValues().add("customReturnValueHandlers", returnValueHandlers);
|
||||
}
|
||||
String methodExResolverName = readerContext.registerWithGeneratedName(methodExceptionResolver);
|
||||
|
||||
String methodExceptionResolverName = readerContext.registerWithGeneratedName(exceptionHandlerExceptionResolver);
|
||||
|
||||
RootBeanDefinition responseStatusExceptionResolver = new RootBeanDefinition(ResponseStatusExceptionResolver.class);
|
||||
responseStatusExceptionResolver.setSource(source);
|
||||
responseStatusExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
responseStatusExceptionResolver.getPropertyValues().add("order", 1);
|
||||
String responseStatusExceptionResolverName =
|
||||
readerContext.registerWithGeneratedName(responseStatusExceptionResolver);
|
||||
RootBeanDefinition statusExceptionResolver = new RootBeanDefinition(ResponseStatusExceptionResolver.class);
|
||||
statusExceptionResolver.setSource(source);
|
||||
statusExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
statusExceptionResolver.getPropertyValues().add("order", 1);
|
||||
String statusExResolverName = readerContext.registerWithGeneratedName(statusExceptionResolver);
|
||||
|
||||
RootBeanDefinition defaultExceptionResolver = new RootBeanDefinition(DefaultHandlerExceptionResolver.class);
|
||||
defaultExceptionResolver.setSource(source);
|
||||
defaultExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
defaultExceptionResolver.getPropertyValues().add("order", 2);
|
||||
String defaultExceptionResolverName =
|
||||
readerContext.registerWithGeneratedName(defaultExceptionResolver);
|
||||
String defaultExResolverName = readerContext.registerWithGeneratedName(defaultExceptionResolver);
|
||||
|
||||
parserContext.registerComponent(new BeanComponentDefinition(handlerMappingDef, HANDLER_MAPPING_BEAN_NAME));
|
||||
parserContext.registerComponent(new BeanComponentDefinition(handlerAdapterDef, HANDLER_ADAPTER_BEAN_NAME));
|
||||
parserContext.registerComponent(new BeanComponentDefinition(uriCompContribDef, uriCompContribName));
|
||||
parserContext.registerComponent(new BeanComponentDefinition(exceptionHandlerExceptionResolver, methodExceptionResolverName));
|
||||
parserContext.registerComponent(new BeanComponentDefinition(responseStatusExceptionResolver, responseStatusExceptionResolverName));
|
||||
parserContext.registerComponent(new BeanComponentDefinition(defaultExceptionResolver, defaultExceptionResolverName));
|
||||
parserContext.registerComponent(new BeanComponentDefinition(mappedCsInterceptorDef, mappedInterceptorName));
|
||||
parserContext.registerComponent(new BeanComponentDefinition(uriContributorDef, uriContributorName));
|
||||
parserContext.registerComponent(new BeanComponentDefinition(mappedInterceptorDef, mappedInterceptorName));
|
||||
parserContext.registerComponent(new BeanComponentDefinition(methodExceptionResolver, methodExResolverName));
|
||||
parserContext.registerComponent(new BeanComponentDefinition(statusExceptionResolver, statusExResolverName));
|
||||
parserContext.registerComponent(new BeanComponentDefinition(defaultExceptionResolver, defaultExResolverName));
|
||||
|
||||
// Ensure BeanNameUrlHandlerMapping (SPR-8289) and default HandlerAdapters are not "turned off"
|
||||
MvcNamespaceUtils.registerDefaultComponents(parserContext, source);
|
||||
@@ -380,8 +373,8 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
|
||||
}
|
||||
}
|
||||
|
||||
private RuntimeBeanReference getContentNegotiationManager(Element element, Object source,
|
||||
ParserContext parserContext) {
|
||||
private RuntimeBeanReference getContentNegotiationManager(
|
||||
Element element, Object source, ParserContext parserContext) {
|
||||
|
||||
RuntimeBeanReference beanRef;
|
||||
if (element.hasAttribute("content-negotiation-manager")) {
|
||||
@@ -402,8 +395,8 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
|
||||
return beanRef;
|
||||
}
|
||||
|
||||
private void configurePathMatchingProperties(RootBeanDefinition handlerMappingDef, Element element,
|
||||
ParserContext parserContext) {
|
||||
private void configurePathMatchingProperties(
|
||||
RootBeanDefinition handlerMappingDef, Element element, ParserContext parserContext) {
|
||||
|
||||
Element pathMatchingElement = DomUtils.getChildElementByTagName(element, "path-matching");
|
||||
if (pathMatchingElement != null) {
|
||||
@@ -462,15 +455,13 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
private String getAsyncTimeout(Element element) {
|
||||
Element asyncElement = DomUtils.getChildElementByTagName(element, "async-support");
|
||||
return (asyncElement != null) ? asyncElement.getAttribute("default-timeout") : null;
|
||||
return (asyncElement != null ? asyncElement.getAttribute("default-timeout") : null);
|
||||
}
|
||||
|
||||
private RuntimeBeanReference getAsyncExecutor(Element element) {
|
||||
Element asyncElement = DomUtils.getChildElementByTagName(element, "async-support");
|
||||
if (asyncElement != null) {
|
||||
if (asyncElement.hasAttribute("task-executor")) {
|
||||
return new RuntimeBeanReference(asyncElement.getAttribute("task-executor"));
|
||||
}
|
||||
if (asyncElement != null && asyncElement.hasAttribute("task-executor")) {
|
||||
return new RuntimeBeanReference(asyncElement.getAttribute("task-executor"));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -571,7 +562,8 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
|
||||
}
|
||||
|
||||
if (jackson2XmlPresent) {
|
||||
RootBeanDefinition jacksonConverterDef = createConverterDefinition(MappingJackson2XmlHttpMessageConverter.class, source);
|
||||
Class<?> type = MappingJackson2XmlHttpMessageConverter.class;
|
||||
RootBeanDefinition jacksonConverterDef = createConverterDefinition(type, source);
|
||||
GenericBeanDefinition jacksonFactoryDef = createObjectMapperFactoryDefinition(source);
|
||||
jacksonFactoryDef.getPropertyValues().add("createXmlMapper", true);
|
||||
jacksonConverterDef.getConstructorArgumentValues().addIndexedArgumentValue(0, jacksonFactoryDef);
|
||||
@@ -582,7 +574,8 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
|
||||
}
|
||||
|
||||
if (jackson2Present) {
|
||||
RootBeanDefinition jacksonConverterDef = createConverterDefinition(MappingJackson2HttpMessageConverter.class, source);
|
||||
Class<?> type = MappingJackson2HttpMessageConverter.class;
|
||||
RootBeanDefinition jacksonConverterDef = createConverterDefinition(type, source);
|
||||
GenericBeanDefinition jacksonFactoryDef = createObjectMapperFactoryDefinition(source);
|
||||
jacksonConverterDef.getConstructorArgumentValues().addIndexedArgumentValue(0, jacksonFactoryDef);
|
||||
messageConverters.add(jacksonConverterDef);
|
||||
@@ -609,7 +602,6 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
|
||||
return beanDefinition;
|
||||
}
|
||||
|
||||
|
||||
private ManagedList<Object> extractBeanSubElements(Element parentElement, ParserContext parserContext) {
|
||||
ManagedList<Object> list = new ManagedList<Object>();
|
||||
list.setSource(parserContext.extractSource(parentElement));
|
||||
@@ -620,27 +612,6 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
|
||||
return list;
|
||||
}
|
||||
|
||||
private ManagedList<BeanReference> extractBeanRefSubElements(Element parentElement, ParserContext parserContext){
|
||||
ManagedList<BeanReference> list = new ManagedList<BeanReference>();
|
||||
list.setSource(parserContext.extractSource(parentElement));
|
||||
for (Element refElement : DomUtils.getChildElementsByTagName(parentElement, "ref")) {
|
||||
BeanReference reference;
|
||||
if (StringUtils.hasText("bean")) {
|
||||
reference = new RuntimeBeanReference(refElement.getAttribute("bean"),false);
|
||||
list.add(reference);
|
||||
}
|
||||
else if (StringUtils.hasText("parent")){
|
||||
reference = new RuntimeBeanReference(refElement.getAttribute("parent"),true);
|
||||
list.add(reference);
|
||||
}
|
||||
else {
|
||||
parserContext.getReaderContext().error("'bean' or 'parent' attribute is required for <ref> element",
|
||||
parserContext.extractSource(parentElement));
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A FactoryBean for a CompositeUriComponentsContributor that obtains the
|
||||
@@ -671,7 +642,7 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompositeUriComponentsContributor getObject() throws Exception {
|
||||
public CompositeUriComponentsContributor getObject() {
|
||||
return this.uriComponentsContributor;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -63,8 +63,6 @@ import org.springframework.validation.Validator;
|
||||
import org.springframework.web.HttpRequestHandler;
|
||||
import org.springframework.web.accept.ContentNegotiationManager;
|
||||
import org.springframework.web.bind.WebDataBinder;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
|
||||
import org.springframework.web.context.ServletContextAware;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
@@ -134,10 +132,10 @@ import org.springframework.web.util.UrlPathHelper;
|
||||
* <p>Registers a {@link HandlerExceptionResolverComposite} with this chain of
|
||||
* exception resolvers:
|
||||
* <ul>
|
||||
* <li>{@link ExceptionHandlerExceptionResolver} for handling exceptions
|
||||
* through @{@link ExceptionHandler} methods.
|
||||
* <li>{@link ResponseStatusExceptionResolver} for exceptions annotated
|
||||
* with @{@link ResponseStatus}.
|
||||
* <li>{@link ExceptionHandlerExceptionResolver} for handling exceptions through
|
||||
* {@link org.springframework.web.bind.annotation.ExceptionHandler} methods.
|
||||
* <li>{@link ResponseStatusExceptionResolver} for exceptions annotated with
|
||||
* {@link org.springframework.web.bind.annotation.ResponseStatus}.
|
||||
* <li>{@link DefaultHandlerExceptionResolver} for resolving known Spring
|
||||
* exception types
|
||||
* </ul>
|
||||
@@ -865,12 +863,11 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv
|
||||
* A method available to subclasses for adding default {@link HandlerExceptionResolver}s.
|
||||
* <p>Adds the following exception resolvers:
|
||||
* <ul>
|
||||
* <li>{@link ExceptionHandlerExceptionResolver}
|
||||
* for handling exceptions through @{@link ExceptionHandler} methods.
|
||||
* <li>{@link ResponseStatusExceptionResolver}
|
||||
* for exceptions annotated with @{@link ResponseStatus}.
|
||||
* <li>{@link DefaultHandlerExceptionResolver}
|
||||
* for resolving known Spring exception types
|
||||
* <li>{@link ExceptionHandlerExceptionResolver} for handling exceptions through
|
||||
* {@link org.springframework.web.bind.annotation.ExceptionHandler} methods.
|
||||
* <li>{@link ResponseStatusExceptionResolver} for exceptions annotated with
|
||||
* {@link org.springframework.web.bind.annotation.ResponseStatus}.
|
||||
* <li>{@link DefaultHandlerExceptionResolver} for resolving known Spring exception types
|
||||
* </ul>
|
||||
*/
|
||||
protected final void addDefaultHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
|
||||
|
||||
Reference in New Issue
Block a user