diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/config/AbstractMessageBrokerConfiguration.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/config/AbstractMessageBrokerConfiguration.java index 98f00a7418d..5a8907742b0 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/simp/config/AbstractMessageBrokerConfiguration.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/config/AbstractMessageBrokerConfiguration.java @@ -433,7 +433,7 @@ public abstract class AbstractMessageBrokerConfiguration implements ApplicationC catch (Throwable ex) { throw new BeanInitializationException("Could not find default validator class", ex); } - validator = (Validator) BeanUtils.instantiate(clazz); + validator = (Validator) BeanUtils.instantiateClass(clazz); } else { validator = new Validator() { diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.java index 084acd90c6f..eacb79cb6e9 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -22,6 +22,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.format.FormatterRegistry; import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.util.CollectionUtils; import org.springframework.validation.MessageCodesResolver; import org.springframework.validation.Validator; import org.springframework.web.method.support.HandlerMethodArgumentResolver; @@ -29,7 +30,7 @@ import org.springframework.web.method.support.HandlerMethodReturnValueHandler; import org.springframework.web.servlet.HandlerExceptionResolver; /** - * A sub-class of {@code WebMvcConfigurationSupport} that detects and delegates + * A subclass of {@code WebMvcConfigurationSupport} that detects and delegates * to all beans of type {@link WebMvcConfigurer} allowing them to customize the * configuration provided by {@code WebMvcConfigurationSupport}. This is the * class actually imported by {@link EnableWebMvc @EnableWebMvc}. @@ -45,10 +46,9 @@ public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport { @Autowired(required = false) public void setConfigurers(List configurers) { - if (configurers == null || configurers.isEmpty()) { - return; + if (!CollectionUtils.isEmpty(configurers)) { + this.configurers.addWebMvcConfigurers(configurers); } - this.configurers.addWebMvcConfigurers(configurers); } @@ -117,16 +117,6 @@ public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport { this.configurers.addFormatters(registry); } - @Override - protected Validator getValidator() { - return this.configurers.getValidator(); - } - - @Override - protected MessageCodesResolver getMessageCodesResolver() { - return this.configurers.getMessageCodesResolver(); - } - @Override protected void configureHandlerExceptionResolvers(List exceptionResolvers) { this.configurers.configureHandlerExceptionResolvers(exceptionResolvers); @@ -137,4 +127,14 @@ public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport { this.configurers.addCorsMappings(registry); } + @Override + protected Validator getValidator() { + return this.configurers.getValidator(); + } + + @Override + protected MessageCodesResolver getMessageCodesResolver() { + return this.configurers.getMessageCodesResolver(); + } + } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java index 37976905161..dd061d0abc4 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -17,6 +17,7 @@ package org.springframework.web.servlet.config.annotation; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Locale; @@ -229,6 +230,7 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv return this.servletContext; } + /** * Return a {@link RequestMappingHandlerMapping} ordered at 0 for mapping * requests to annotated controllers. @@ -251,18 +253,20 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv if (configurer.isUseTrailingSlashMatch() != null) { handlerMapping.setUseTrailingSlashMatch(configurer.isUseTrailingSlashMatch()); } - if (configurer.getPathMatcher() != null) { - handlerMapping.setPathMatcher(configurer.getPathMatcher()); + UrlPathHelper pathHelper = configurer.getUrlPathHelper(); + if (pathHelper != null) { + handlerMapping.setUrlPathHelper(pathHelper); } - if (configurer.getUrlPathHelper() != null) { - handlerMapping.setUrlPathHelper(configurer.getUrlPathHelper()); + PathMatcher pathMatcher = configurer.getPathMatcher(); + if (pathMatcher != null) { + handlerMapping.setPathMatcher(pathMatcher); } return handlerMapping; } /** - * Protected method for plugging in a custom sub-class of + * Protected method for plugging in a custom subclass of * {@link RequestMappingHandlerMapping}. */ protected RequestMappingHandlerMapping createRequestMappingHandlerMapping() { @@ -335,7 +339,7 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv } protected Map getDefaultMediaTypes() { - Map map = new HashMap(); + Map map = new HashMap(4); if (romePresent) { map.put("atom", MediaType.APPLICATION_ATOM_XML); map.put("rss", MediaType.valueOf("application/rss+xml")); @@ -488,18 +492,14 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv adapter.setCustomReturnValueHandlers(returnValueHandlers); if (jackson2Present) { - List requestBodyAdvices = new ArrayList(); - requestBodyAdvices.add(new JsonViewRequestBodyAdvice()); - adapter.setRequestBodyAdvice(requestBodyAdvices); - - List> responseBodyAdvices = new ArrayList>(); - responseBodyAdvices.add(new JsonViewResponseBodyAdvice()); - adapter.setResponseBodyAdvice(responseBodyAdvices); + adapter.setRequestBodyAdvice( + Collections.singletonList(new JsonViewRequestBodyAdvice())); + adapter.setResponseBodyAdvice( + Collections.>singletonList(new JsonViewResponseBodyAdvice())); } AsyncSupportConfigurer configurer = new AsyncSupportConfigurer(); configureAsyncSupport(configurer); - if (configurer.getTaskExecutor() != null) { adapter.setTaskExecutor(configurer.getTaskExecutor()); } @@ -524,6 +524,20 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv return initializer; } + /** + * Override this method to provide a custom {@link MessageCodesResolver}. + */ + protected MessageCodesResolver getMessageCodesResolver() { + return null; + } + + /** + * Override this method to configure asynchronous request processing options. + * @see AsyncSupportConfigurer + */ + protected void configureAsyncSupport(AsyncSupportConfigurer configurer) { + } + /** * Return a {@link FormattingConversionService} for use with annotated * controller methods and the {@code spring:eval} JSP tag. @@ -536,6 +550,12 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv return conversionService; } + /** + * Override this method to add custom {@link Converter}s and {@link Formatter}s. + */ + protected void addFormatters(FormatterRegistry registry) { + } + /** * Return a global {@link Validator} instance for example for validating * {@code @ModelAttribute} and {@code @RequestBody} method arguments. @@ -560,7 +580,7 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv catch (LinkageError ex) { throw new BeanInitializationException("Could not load default validator class", ex); } - validator = (Validator) BeanUtils.instantiate(clazz); + validator = (Validator) BeanUtils.instantiateClass(clazz); } else { validator = new NoOpValidator(); @@ -569,6 +589,13 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv return validator; } + /** + * Override this method to provide a custom {@link Validator}. + */ + protected Validator getValidator() { + return null; + } + /** * Return a global {@link PathMatcher} instance for path matching * patterns in {@link HandlerMapping}s. @@ -595,26 +622,8 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv */ @Bean public UrlPathHelper mvcUrlPathHelper() { - if (getPathMatchConfigurer().getUrlPathHelper() != null) { - return getPathMatchConfigurer().getUrlPathHelper(); - } - else { - return new UrlPathHelper(); - } - } - - /** - * Override this method to provide a custom {@link Validator}. - */ - protected Validator getValidator() { - return null; - } - - /** - * Override this method to provide a custom {@link MessageCodesResolver}. - */ - protected MessageCodesResolver getMessageCodesResolver() { - return null; + UrlPathHelper pathHelper = getPathMatchConfigurer().getUrlPathHelper(); + return (pathHelper != null ? pathHelper : new UrlPathHelper()); } /** @@ -679,6 +688,14 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv protected void configureMessageConverters(List> converters) { } + /** + * Override this method to extend or modify the list of converters after it + * has been configured. This may be useful for example to allow default + * converters to be registered and then insert a custom converter through + * this method. + * @param converters the list of configured converters to extend. + * @since 4.1.3 + */ protected void extendMessageConverters(List> converters) { } @@ -719,19 +736,6 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv } } - /** - * Override this method to add custom {@link Converter}s and {@link Formatter}s. - */ - protected void addFormatters(FormatterRegistry registry) { - } - - /** - * Override this method to configure asynchronous request processing options. - * @see AsyncSupportConfigurer - */ - public void configureAsyncSupport(AsyncSupportConfigurer configurer) { - } - /** * Return an instance of {@link CompositeUriComponentsContributor} for use with * {@link org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder}. @@ -774,11 +778,9 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv public HandlerExceptionResolver handlerExceptionResolver() { List exceptionResolvers = new ArrayList(); configureHandlerExceptionResolvers(exceptionResolvers); - if (exceptionResolvers.isEmpty()) { addDefaultHandlerExceptionResolvers(exceptionResolvers); } - HandlerExceptionResolverComposite composite = new HandlerExceptionResolverComposite(); composite.setOrder(0); composite.setExceptionResolvers(exceptionResolvers); diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurer.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurer.java index 3e9c509f7e9..cdb28fc37db 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurer.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2016 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. @@ -73,14 +73,6 @@ public interface WebMvcConfigurer { */ void extendMessageConverters(List> converters); - /** - * Provide a custom {@link Validator} instead of the one created by default. - * The default implementation, assuming JSR-303 is on the classpath, is: - * {@link org.springframework.validation.beanvalidation.OptionalValidatorFactoryBean}. - * Leave the return value as {@code null} to keep the default. - */ - Validator getValidator(); - /** * Configure content negotiation options. */ @@ -144,13 +136,6 @@ public interface WebMvcConfigurer { */ void addInterceptors(InterceptorRegistry registry); - /** - * Provide a custom {@link MessageCodesResolver} for building message codes - * from data binding and validation error codes. Leave the return value as - * {@code null} to keep the default. - */ - MessageCodesResolver getMessageCodesResolver(); - /** * Configure simple automated controllers pre-configured with the response * status code and/or a view to render the response body. This is useful in @@ -188,4 +173,19 @@ public interface WebMvcConfigurer { */ void addCorsMappings(CorsRegistry registry); + /** + * Provide a custom {@link Validator} instead of the one created by default. + * The default implementation, assuming JSR-303 is on the classpath, is: + * {@link org.springframework.validation.beanvalidation.OptionalValidatorFactoryBean}. + * Leave the return value as {@code null} to keep the default. + */ + Validator getValidator(); + + /** + * Provide a custom {@link MessageCodesResolver} for building message codes + * from data binding and validation error codes. Leave the return value as + * {@code null} to keep the default. + */ + MessageCodesResolver getMessageCodesResolver(); + } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerAdapter.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerAdapter.java index 90d4b6aefe1..afa81fab80c 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerAdapter.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2016 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. @@ -28,7 +28,7 @@ import org.springframework.web.servlet.HandlerExceptionResolver; /** * An implementation of {@link WebMvcConfigurer} with empty methods allowing - * sub-classes to override only the methods they're interested in. + * subclasses to override only the methods they're interested in. * * @author Rossen Stoyanchev * @since 3.1 @@ -59,15 +59,6 @@ public abstract class WebMvcConfigurerAdapter implements WebMvcConfigurer { public void extendMessageConverters(List> converters) { } - /** - * {@inheritDoc} - *

This implementation returns {@code null} - */ - @Override - public Validator getValidator() { - return null; - } - /** * {@inheritDoc} *

This implementation is empty. @@ -116,15 +107,6 @@ public abstract class WebMvcConfigurerAdapter implements WebMvcConfigurer { public void configureHandlerExceptionResolvers(List exceptionResolvers) { } - /** - * {@inheritDoc} - *

This implementation is empty. - */ - @Override - public MessageCodesResolver getMessageCodesResolver() { - return null; - } - /** * {@inheritDoc} *

This implementation is empty. @@ -173,4 +155,22 @@ public abstract class WebMvcConfigurerAdapter implements WebMvcConfigurer { public void addCorsMappings(CorsRegistry registry) { } + /** + * {@inheritDoc} + *

This implementation returns {@code null}. + */ + @Override + public Validator getValidator() { + return null; + } + + /** + * {@inheritDoc} + *

This implementation returns {@code null}. + */ + @Override + public MessageCodesResolver getMessageCodesResolver() { + return null; + } + } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerComposite.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerComposite.java index c88ba0ff3b6..03de46c13ba 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerComposite.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerComposite.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2016 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. @@ -21,6 +21,7 @@ import java.util.List; import org.springframework.format.FormatterRegistry; import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.util.CollectionUtils; import org.springframework.validation.MessageCodesResolver; import org.springframework.validation.Validator; import org.springframework.web.method.support.HandlerMethodArgumentResolver; @@ -28,7 +29,7 @@ import org.springframework.web.method.support.HandlerMethodReturnValueHandler; import org.springframework.web.servlet.HandlerExceptionResolver; /** - * An {@link WebMvcConfigurer} implementation that delegates to other {@link WebMvcConfigurer} instances. + * A {@link WebMvcConfigurer} that delegates to one or more others. * * @author Rossen Stoyanchev * @since 3.1 @@ -37,12 +38,14 @@ class WebMvcConfigurerComposite implements WebMvcConfigurer { private final List delegates = new ArrayList(); + public void addWebMvcConfigurers(List configurers) { - if (configurers != null) { + if (!CollectionUtils.isEmpty(configurers)) { this.delegates.addAll(configurers); } } + @Override public void addFormatters(FormatterRegistry registry) { for (WebMvcConfigurer delegate : this.delegates) { @@ -141,6 +144,13 @@ class WebMvcConfigurerComposite implements WebMvcConfigurer { } } + @Override + public void addCorsMappings(CorsRegistry registry) { + for (WebMvcConfigurer delegate : this.delegates) { + delegate.addCorsMappings(registry); + } + } + @Override public Validator getValidator() { List candidates = new ArrayList(); @@ -154,10 +164,15 @@ class WebMvcConfigurerComposite implements WebMvcConfigurer { } @Override - public void addCorsMappings(CorsRegistry registry) { - for (WebMvcConfigurer delegate : this.delegates) { - delegate.addCorsMappings(registry); + public MessageCodesResolver getMessageCodesResolver() { + List candidates = new ArrayList(); + for (WebMvcConfigurer configurer : this.delegates) { + MessageCodesResolver messageCodesResolver = configurer.getMessageCodesResolver(); + if (messageCodesResolver != null) { + candidates.add(messageCodesResolver); + } } + return selectSingleInstance(candidates, MessageCodesResolver.class); } private T selectSingleInstance(List instances, Class instanceType) { @@ -173,16 +188,4 @@ class WebMvcConfigurerComposite implements WebMvcConfigurer { } } - @Override - public MessageCodesResolver getMessageCodesResolver() { - List candidates = new ArrayList(); - for (WebMvcConfigurer configurer : this.delegates) { - MessageCodesResolver messageCodesResolver = configurer.getMessageCodesResolver(); - if (messageCodesResolver != null) { - candidates.add(messageCodesResolver); - } - } - return selectSingleInstance(candidates, MessageCodesResolver.class); - } - } diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfigurationTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfigurationTests.java index 258b67a9a22..d0c58268453 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfigurationTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -17,7 +17,7 @@ package org.springframework.web.servlet.config.annotation; import java.util.ArrayList; -import java.util.Arrays; +import java.util.Collections; import java.util.List; import org.junit.Before; @@ -89,10 +89,10 @@ public class DelegatingWebMvcConfigurationTests { delegatingConfig = new DelegatingWebMvcConfiguration(); } + @Test public void requestMappingHandlerAdapter() throws Exception { - - delegatingConfig.setConfigurers(Arrays.asList(webMvcConfigurer)); + delegatingConfig.setConfigurers(Collections.singletonList(webMvcConfigurer)); RequestMappingHandlerAdapter adapter = delegatingConfig.requestMappingHandlerAdapter(); ConfigurableWebBindingInitializer initializer = (ConfigurableWebBindingInitializer) adapter.getWebBindingInitializer(); @@ -141,7 +141,7 @@ public class DelegatingWebMvcConfigurationTests { public void getCustomValidator() { given(webMvcConfigurer.getValidator()).willReturn(new LocalValidatorFactoryBean()); - delegatingConfig.setConfigurers(Arrays.asList(webMvcConfigurer)); + delegatingConfig.setConfigurers(Collections.singletonList(webMvcConfigurer)); delegatingConfig.mvcValidator(); verify(webMvcConfigurer).getValidator(); @@ -151,7 +151,7 @@ public class DelegatingWebMvcConfigurationTests { public void getCustomMessageCodesResolver() { given(webMvcConfigurer.getMessageCodesResolver()).willReturn(new DefaultMessageCodesResolver()); - delegatingConfig.setConfigurers(Arrays.asList(webMvcConfigurer)); + delegatingConfig.setConfigurers(Collections.singletonList(webMvcConfigurer)); delegatingConfig.getMessageCodesResolver(); verify(webMvcConfigurer).getMessageCodesResolver(); @@ -159,8 +159,7 @@ public class DelegatingWebMvcConfigurationTests { @Test public void handlerExceptionResolver() throws Exception { - - delegatingConfig.setConfigurers(Arrays.asList(webMvcConfigurer)); + delegatingConfig.setConfigurers(Collections.singletonList(webMvcConfigurer)); delegatingConfig.handlerExceptionResolver(); verify(webMvcConfigurer).configureMessageConverters(converters.capture()); @@ -186,7 +185,7 @@ public class DelegatingWebMvcConfigurationTests { delegatingConfig.setConfigurers(configurers); HandlerExceptionResolverComposite composite = - (HandlerExceptionResolverComposite) delegatingConfig.handlerExceptionResolver(); + (HandlerExceptionResolverComposite) delegatingConfig.handlerExceptionResolver(); assertEquals("Only one custom converter is expected", 1, composite.getExceptionResolvers().size()); } @@ -200,9 +199,9 @@ public class DelegatingWebMvcConfigurationTests { @Override public void configurePathMatch(PathMatchConfigurer configurer) { configurer.setUseRegisteredSuffixPatternMatch(true) - .setUseTrailingSlashMatch(false) - .setUrlPathHelper(pathHelper) - .setPathMatcher(pathMatcher); + .setUseTrailingSlashMatch(false) + .setUrlPathHelper(pathHelper) + .setPathMatcher(pathMatcher); } }); delegatingConfig.setConfigurers(configurers);