From de7eeb50142fc72b9f276c0e86d221941c6ad6f3 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Mon, 22 Oct 2018 13:55:32 -0700 Subject: [PATCH] Fix ResourceUrlEncodingFilter conditions Fix `ResourceUrlEncodingFilter` conditions which were inadvertently changed in commits 64f04fce and 6cc272ec and would back off if any `FilterRegistrationBean` was found. The updated conditions restores the behavior of Spring Boot 2.0.5 and allows users to directly register their own `ResourceUrlEncodingFilter` beans (as long as they don't use a `FilterRegistrationBean`). Fixes gh-14897 --- .../FreeMarkerServletWebConfiguration.java | 2 +- .../thymeleaf/ThymeleafAutoConfiguration.java | 2 +- ...oConfigurationServletIntegrationTests.java | 58 ++++++++++++++++--- ...hymeleafServletAutoConfigurationTests.java | 30 ++++++++++ 4 files changed, 82 insertions(+), 10 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/freemarker/FreeMarkerServletWebConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/freemarker/FreeMarkerServletWebConfiguration.java index 142fd4cee6b..3cf800e1690 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/freemarker/FreeMarkerServletWebConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/freemarker/FreeMarkerServletWebConfiguration.java @@ -74,7 +74,7 @@ class FreeMarkerServletWebConfiguration extends AbstractFreeMarkerConfiguration } @Bean - @ConditionalOnMissingBean + @ConditionalOnMissingBean(ResourceUrlEncodingFilter.class) @ConditionalOnEnabledResourceChain public FilterRegistrationBean resourceUrlEncodingFilter() { FilterRegistrationBean registration = new FilterRegistrationBean<>( diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafAutoConfiguration.java index a0635401db3..80197b106ad 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafAutoConfiguration.java @@ -167,7 +167,7 @@ public class ThymeleafAutoConfiguration { static class ThymeleafWebMvcConfiguration { @Bean - @ConditionalOnMissingBean + @ConditionalOnMissingBean(ResourceUrlEncodingFilter.class) @ConditionalOnEnabledResourceChain public FilterRegistrationBean resourceUrlEncodingFilter() { FilterRegistrationBean registration = new FilterRegistrationBean<>( diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/freemarker/FreeMarkerAutoConfigurationServletIntegrationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/freemarker/FreeMarkerAutoConfigurationServletIntegrationTests.java index f6dad0c0d24..9670c087f0c 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/freemarker/FreeMarkerAutoConfigurationServletIntegrationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/freemarker/FreeMarkerAutoConfigurationServletIntegrationTests.java @@ -19,16 +19,22 @@ package org.springframework.boot.autoconfigure.freemarker; import java.io.StringWriter; import java.util.EnumSet; import java.util.Locale; +import java.util.Map; import javax.servlet.DispatcherType; import javax.servlet.http.HttpServletRequest; import org.junit.After; -import org.junit.Before; import org.junit.Test; +import org.springframework.boot.autoconfigure.ImportAutoConfiguration; +import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.test.util.TestPropertyValues; import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.boot.web.servlet.filter.OrderedCharacterEncodingFilter; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.mock.web.MockServletContext; @@ -52,12 +58,7 @@ import static org.assertj.core.api.Assertions.assertThat; */ public class FreeMarkerAutoConfigurationServletIntegrationTests { - private AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); - - @Before - public void setupContext() { - this.context.setServletContext(new MockServletContext()); - } + private AnnotationConfigWebApplicationContext context; @After public void close() { @@ -170,9 +171,31 @@ public class FreeMarkerAutoConfigurationServletIntegrationTests { EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR)); } + @Test + @SuppressWarnings("rawtypes") + public void registerResourceHandlingFilterWithOtherRegistrationBean() { + // gh-14897 + registerAndRefreshContext(FilterRegistrationConfiguration.class, + "spring.resources.chain.enabled:true"); + Map beans = this.context + .getBeansOfType(FilterRegistrationBean.class); + assertThat(beans).hasSize(2); + FilterRegistrationBean registration = beans.values().stream() + .filter((r) -> r.getFilter() instanceof ResourceUrlEncodingFilter) + .findFirst().get(); + assertThat(registration).hasFieldOrPropertyWithValue("dispatcherTypes", + EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR)); + } + private void registerAndRefreshContext(String... env) { + registerAndRefreshContext(BaseConfiguration.class, env); + } + + private void registerAndRefreshContext(Class config, String... env) { + this.context = new AnnotationConfigWebApplicationContext(); + this.context.setServletContext(new MockServletContext()); TestPropertyValues.of(env).applyTo(this.context); - this.context.register(FreeMarkerAutoConfiguration.class); + this.context.register(config); this.context.refresh(); } @@ -193,4 +216,23 @@ public class FreeMarkerAutoConfigurationServletIntegrationTests { return response; } + @Configuration + @ImportAutoConfiguration({ FreeMarkerAutoConfiguration.class, + PropertyPlaceholderAutoConfiguration.class }) + static class BaseConfiguration { + + } + + @Configuration + @Import(BaseConfiguration.class) + static class FilterRegistrationConfiguration { + + @Bean + public FilterRegistrationBean filterRegisration() { + return new FilterRegistrationBean( + new OrderedCharacterEncodingFilter()); + } + + } + } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafServletAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafServletAutoConfigurationTests.java index 07720e8823d..5ae47da6160 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafServletAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafServletAutoConfigurationTests.java @@ -20,6 +20,7 @@ import java.io.File; import java.util.Collections; import java.util.EnumSet; import java.util.Locale; +import java.util.Map; import javax.servlet.DispatcherType; @@ -41,6 +42,7 @@ import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoCon import org.springframework.boot.test.rule.OutputCapture; import org.springframework.boot.test.util.TestPropertyValues; import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.boot.web.servlet.filter.OrderedCharacterEncodingFilter; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -224,6 +226,22 @@ public class ThymeleafServletAutoConfigurationTests { EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR)); } + @Test + @SuppressWarnings("rawtypes") + public void registerResourceHandlingFilterWithOtherRegistrationBean() { + // gh-14897 + load(FilterRegistrationConfiguration.class, + "spring.resources.chain.enabled:true"); + Map beans = this.context + .getBeansOfType(FilterRegistrationBean.class); + assertThat(beans).hasSize(2); + FilterRegistrationBean registration = beans.values().stream() + .filter((r) -> r.getFilter() instanceof ResourceUrlEncodingFilter) + .findFirst().get(); + assertThat(registration).hasFieldOrPropertyWithValue("dispatcherTypes", + EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR)); + } + @Test public void layoutDialectCanBeCustomized() { load(LayoutDialectConfiguration.class); @@ -269,4 +287,16 @@ public class ThymeleafServletAutoConfigurationTests { } + @Configuration + @Import(BaseConfiguration.class) + static class FilterRegistrationConfiguration { + + @Bean + public FilterRegistrationBean filterRegisration() { + return new FilterRegistrationBean( + new OrderedCharacterEncodingFilter()); + } + + } + }