diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/DispatcherServletAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/DispatcherServletAutoConfiguration.java index 27bba65407..376c729c94 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/DispatcherServletAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/DispatcherServletAutoConfiguration.java @@ -27,7 +27,9 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionOutcome; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.condition.SpringBootCondition; import org.springframework.boot.context.embedded.ServletRegistrationBean; @@ -39,6 +41,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.core.type.AnnotatedTypeMetadata; +import org.springframework.web.multipart.MultipartResolver; import org.springframework.web.servlet.DispatcherServlet; /** @@ -94,6 +97,14 @@ public class DispatcherServletAutoConfiguration { return registration; } + @Bean + @ConditionalOnBean(MultipartResolver.class) + @ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME) + public MultipartResolver multipartResolver(MultipartResolver resolver) { + // Detect if the user has created a MultipartResolver but named it incorrectly + return resolver; + } + } @Order(Ordered.LOWEST_PRECEDENCE - 10) diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/MultipartAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/MultipartAutoConfiguration.java index ab7b58f78d..ae74f5533d 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/MultipartAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/MultipartAutoConfiguration.java @@ -30,6 +30,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.multipart.MultipartResolver; import org.springframework.web.multipart.support.StandardServletMultipartResolver; +import org.springframework.web.servlet.DispatcherServlet; /** * {@link EnableAutoConfiguration Auto-configuration} for multi-part uploads. Adds a @@ -55,12 +56,13 @@ public class MultipartAutoConfiguration { private MultipartProperties multipartProperties = new MultipartProperties(); @Bean - @ConditionalOnMissingBean + @ConditionalOnMissingBean(value = { MultipartConfigElement.class, + MultipartResolver.class }) public MultipartConfigElement multipartConfigElement() { return this.multipartProperties.createMultipartConfig(); } - @Bean + @Bean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME) @ConditionalOnMissingBean(value = MultipartResolver.class) public StandardServletMultipartResolver multipartResolver() { return new StandardServletMultipartResolver(); diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/DispatcherServletAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/DispatcherServletAutoConfigurationTests.java index 33d77a5d0a..d673ecfcd8 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/DispatcherServletAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/DispatcherServletAutoConfigurationTests.java @@ -17,6 +17,7 @@ package org.springframework.boot.autoconfigure.web; import javax.servlet.MultipartConfigElement; +import javax.servlet.http.HttpServletRequest; import org.junit.Test; import org.springframework.beans.factory.UnsatisfiedDependencyException; @@ -25,13 +26,19 @@ import org.springframework.boot.context.embedded.ServletRegistrationBean; import org.springframework.boot.test.EnvironmentTestUtils; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.mock.web.MockServletContext; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; +import org.springframework.web.multipart.MultipartException; +import org.springframework.web.multipart.MultipartHttpServletRequest; +import org.springframework.web.multipart.MultipartResolver; import org.springframework.web.servlet.DispatcherServlet; +import static org.hamcrest.Matchers.instanceOf; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThat; /** * Tests for {@link DispatcherServletAutoConfiguration}. @@ -115,6 +122,21 @@ public class DispatcherServletAutoConfigurationTests { assertNotNull(registration.getMultipartConfig()); } + @Test + public void renamesMultipartResolver() throws Exception { + this.context = new AnnotationConfigWebApplicationContext(); + this.context.setServletContext(new MockServletContext()); + this.context.register(MultipartResolverConfiguration.class, + ServerPropertiesAutoConfiguration.class, + DispatcherServletAutoConfiguration.class); + this.context.refresh(); + DispatcherServlet dispatcherServlet = this.context + .getBean(DispatcherServlet.class); + dispatcherServlet.onApplicationEvent(new ContextRefreshedEvent(this.context)); + assertThat(dispatcherServlet.getMultipartResolver(), + instanceOf(MockMultipartResolver.class)); + } + @Configuration protected static class MultipartConfiguration { @@ -130,6 +152,7 @@ public class DispatcherServletAutoConfigurationTests { @Configuration protected static class CustomDispatcherRegistration { + @Bean public ServletRegistrationBean dispatcherServletRegistration() { ServletRegistrationBean registration = new ServletRegistrationBean( @@ -137,10 +160,12 @@ public class DispatcherServletAutoConfigurationTests { registration.setName("customDispatcher"); return registration; } + } @Configuration protected static class CustomAutowiredRegistration { + @Bean public ServletRegistrationBean dispatcherServletRegistration( DispatcherServlet dispatcherServlet) { @@ -149,6 +174,36 @@ public class DispatcherServletAutoConfigurationTests { registration.setName("customDispatcher"); return registration; } + + } + + @Configuration + protected static class MultipartResolverConfiguration { + + @Bean + public MultipartResolver getMultipartResolver() { + return new MockMultipartResolver(); + } + + } + + private static class MockMultipartResolver implements MultipartResolver { + + @Override + public boolean isMultipart(HttpServletRequest request) { + return false; + } + + @Override + public MultipartHttpServletRequest resolveMultipart(HttpServletRequest request) + throws MultipartException { + return null; + } + + @Override + public void cleanupMultipart(MultipartHttpServletRequest request) { + } + } }