Skip to content

Commit 799ac24

Browse files
committed
Reinstate auto-config of RequestContextFilter with Jersey
Previously, the auto-configuration for both Jersey and WebMvc would auto-configure a RequestContextFilter bean. In 2.1.0, this led to a startup failure due to the latter attempting to override the bean defined by the former. In addition to the override there were also problems with the order of the filter as Jersey uses -1 and MVC uses -105. To avoid the above-described problems, the auto-configuration of the RequestContextFilter was removed from JerseyAutoConfiguration in 2.1.1. Unfortunately, the broke request-scoped beans for those using only Jersey. This commit attempts to strike a better balance by reintroducing the auto-configuration of RequestContextFilter in JerseyAutoConfiguration. It will back off if the user defines their own filter or filter registration. WebMvcAutoConfiguration has been updated to back off in the same manner. This leaves the potential for ordering problems, but they are no worse than they were before. Furthermore, the user has the means to correct any problems by using the various filter ordering properties that are provided for Jersey, Spring Session, Spring Security, etc. Closes gh-15376
1 parent cc64398 commit 799ac24

File tree

4 files changed

+170
-1
lines changed

4 files changed

+170
-1
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfiguration.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
5151
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
5252
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
53+
import org.springframework.boot.autoconfigure.web.servlet.ConditionalOnMissingFilterBean;
5354
import org.springframework.boot.autoconfigure.web.servlet.DefaultJerseyApplicationPath;
5455
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration;
5556
import org.springframework.boot.autoconfigure.web.servlet.JerseyApplicationPath;
@@ -64,6 +65,7 @@
6465
import org.springframework.util.ClassUtils;
6566
import org.springframework.web.WebApplicationInitializer;
6667
import org.springframework.web.context.ServletContextAware;
68+
import org.springframework.web.filter.RequestContextFilter;
6769

6870
/**
6971
* {@link EnableAutoConfiguration Auto-configuration} for Jersey.
@@ -109,6 +111,16 @@ private void customize() {
109111
.forEach((customizer) -> customizer.customize(this.config));
110112
}
111113

114+
@Bean
115+
@ConditionalOnMissingFilterBean(RequestContextFilter.class)
116+
public FilterRegistrationBean<RequestContextFilter> requestContextFilter() {
117+
FilterRegistrationBean<RequestContextFilter> registration = new FilterRegistrationBean<>();
118+
registration.setFilter(new RequestContextFilter());
119+
registration.setOrder(this.jersey.getFilter().getOrder() - 1);
120+
registration.setName("requestContextFilter");
121+
return registration;
122+
}
123+
112124
@Bean
113125
@ConditionalOnMissingBean
114126
public JerseyApplicationPath jerseyApplicationPath() {

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2018 the original author or authors.
2+
* Copyright 2012-2019 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.
@@ -401,6 +401,7 @@ private void customizeResourceHandlerRegistration(
401401
@Bean
402402
@ConditionalOnMissingBean({ RequestContextListener.class,
403403
RequestContextFilter.class })
404+
@ConditionalOnMissingFilterBean(RequestContextFilter.class)
404405
public static RequestContextFilter requestContextFilter() {
405406
return new OrderedRequestContextFilter();
406407
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/*
2+
* Copyright 2012-2019 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.autoconfigure.jersey;
18+
19+
import org.glassfish.jersey.server.ResourceConfig;
20+
import org.junit.Test;
21+
22+
import org.springframework.boot.autoconfigure.AutoConfigurations;
23+
import org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener;
24+
import org.springframework.boot.logging.LogLevel;
25+
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
26+
import org.springframework.boot.web.servlet.FilterRegistrationBean;
27+
import org.springframework.context.annotation.Bean;
28+
import org.springframework.context.annotation.Configuration;
29+
import org.springframework.web.filter.RequestContextFilter;
30+
31+
import static org.assertj.core.api.Assertions.assertThat;
32+
33+
/**
34+
* Tests for {@link JerseyAutoConfiguration}.
35+
*
36+
* @author Andy Wilkinson
37+
*/
38+
public class JerseyAutoConfigurationTests {
39+
40+
private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
41+
.withConfiguration(AutoConfigurations.of(JerseyAutoConfiguration.class))
42+
.withInitializer(new ConditionEvaluationReportLoggingListener(LogLevel.INFO))
43+
.withUserConfiguration(ResourceConfig.class);
44+
45+
@Test
46+
public void requestContextFilterRegistrationIsAutoConfigured() {
47+
this.contextRunner.run((context) -> {
48+
assertThat(context).hasSingleBean(FilterRegistrationBean.class);
49+
FilterRegistrationBean<?> registration = context
50+
.getBean(FilterRegistrationBean.class);
51+
assertThat(registration.getFilter()).isInstanceOf(RequestContextFilter.class);
52+
});
53+
}
54+
55+
@Test
56+
public void whenUserDefinesARequestContextFilterTheAutoConfiguredRegistrationBacksOff() {
57+
this.contextRunner.withUserConfiguration(RequestContextFilterConfiguration.class)
58+
.run((context) -> {
59+
assertThat(context).doesNotHaveBean(FilterRegistrationBean.class);
60+
assertThat(context).hasSingleBean(RequestContextFilter.class);
61+
});
62+
}
63+
64+
@Test
65+
public void whenUserDefinesARequestContextFilterRegistrationTheAutoConfiguredRegistrationBacksOff() {
66+
this.contextRunner
67+
.withUserConfiguration(
68+
RequestContextFilterRegistrationConfiguration.class)
69+
.run((context) -> {
70+
assertThat(context).hasSingleBean(FilterRegistrationBean.class);
71+
assertThat(context).hasBean("customRequestContextFilterRegistration");
72+
});
73+
}
74+
75+
@Configuration
76+
static class ResourceConfigConfiguration {
77+
78+
@Bean
79+
public ResourceConfig resourceConfig() {
80+
return new ResourceConfig();
81+
}
82+
83+
}
84+
85+
@Configuration
86+
static class RequestContextFilterConfiguration {
87+
88+
@Bean
89+
public RequestContextFilter requestContextFilter() {
90+
return new RequestContextFilter();
91+
}
92+
93+
}
94+
95+
@Configuration
96+
static class RequestContextFilterRegistrationConfiguration {
97+
98+
@Bean
99+
public FilterRegistrationBean<RequestContextFilter> customRequestContextFilterRegistration() {
100+
return new FilterRegistrationBean<RequestContextFilter>(
101+
new RequestContextFilter());
102+
}
103+
104+
}
105+
106+
}

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfigurationTests.java

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import org.springframework.boot.test.context.runner.ContextConsumer;
4646
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
4747
import org.springframework.boot.web.server.WebServerFactoryCustomizerBeanPostProcessor;
48+
import org.springframework.boot.web.servlet.FilterRegistrationBean;
4849
import org.springframework.boot.web.servlet.filter.OrderedFormContentFilter;
4950
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
5051
import org.springframework.context.ApplicationContext;
@@ -73,6 +74,7 @@
7374
import org.springframework.web.context.request.ServletWebRequest;
7475
import org.springframework.web.filter.FormContentFilter;
7576
import org.springframework.web.filter.HiddenHttpMethodFilter;
77+
import org.springframework.web.filter.RequestContextFilter;
7678
import org.springframework.web.servlet.HandlerAdapter;
7779
import org.springframework.web.servlet.HandlerExceptionResolver;
7880
import org.springframework.web.servlet.HandlerMapping;
@@ -913,6 +915,33 @@ public void contentNegotiationStrategySkipsPathExtension() throws Exception {
913915
assertThat(mediaTypes).containsOnly(MediaType.ALL);
914916
}
915917

918+
@Test
919+
public void requestContextFilterIsAutoConfigured() {
920+
this.contextRunner.run((context) -> assertThat(context)
921+
.hasSingleBean(RequestContextFilter.class));
922+
}
923+
924+
@Test
925+
public void whenUserDefinesARequestContextFilterTheAutoConfiguredRegistrationBacksOff() {
926+
this.contextRunner.withUserConfiguration(RequestContextFilterConfiguration.class)
927+
.run((context) -> {
928+
assertThat(context).hasSingleBean(RequestContextFilter.class);
929+
assertThat(context).hasBean("customRequestContextFilter");
930+
});
931+
}
932+
933+
@Test
934+
public void whenUserDefinesARequestContextFilterRegistrationTheAutoConfiguredFilterBacksOff() {
935+
this.contextRunner
936+
.withUserConfiguration(
937+
RequestContextFilterRegistrationConfiguration.class)
938+
.run((context) -> {
939+
assertThat(context).hasSingleBean(FilterRegistrationBean.class);
940+
assertThat(context).hasBean("customRequestContextFilterRegistration");
941+
assertThat(context).doesNotHaveBean(RequestContextFilter.class);
942+
});
943+
}
944+
916945
private void assertCacheControl(AssertableWebApplicationContext context) {
917946
Map<String, Object> handlerMap = getHandlerMap(
918947
context.getBean("resourceHandlerMapping", HandlerMapping.class));
@@ -1232,4 +1261,25 @@ public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
12321261

12331262
}
12341263

1264+
@Configuration
1265+
static class RequestContextFilterConfiguration {
1266+
1267+
@Bean
1268+
public RequestContextFilter customRequestContextFilter() {
1269+
return new RequestContextFilter();
1270+
}
1271+
1272+
}
1273+
1274+
@Configuration
1275+
static class RequestContextFilterRegistrationConfiguration {
1276+
1277+
@Bean
1278+
public FilterRegistrationBean<RequestContextFilter> customRequestContextFilterRegistration() {
1279+
return new FilterRegistrationBean<RequestContextFilter>(
1280+
new RequestContextFilter());
1281+
}
1282+
1283+
}
1284+
12351285
}

0 commit comments

Comments
 (0)