Skip to content

Commit 37f0e8c

Browse files
committed
Access to ApplicationContext via ServerWebExchange
Issue: SPR-16298
1 parent 93a522f commit 37f0e8c

File tree

6 files changed

+95
-15
lines changed

6 files changed

+95
-15
lines changed

spring-web/src/main/java/org/springframework/web/server/ServerWebExchange.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
import reactor.core.publisher.Mono;
2626

27+
import org.springframework.context.ApplicationContext;
2728
import org.springframework.context.i18n.LocaleContext;
2829
import org.springframework.http.codec.multipart.Part;
2930
import org.springframework.http.server.reactive.ServerHttpRequest;
@@ -136,6 +137,17 @@ default <T> T getAttributeOrDefault(String name, T defaultValue) {
136137
*/
137138
LocaleContext getLocaleContext();
138139

140+
/**
141+
* Return the {@link ApplicationContext} associated with the web application,
142+
* if it was initialized with one via
143+
* {@link org.springframework.web.server.adapter.WebHttpHandlerBuilder#applicationContext
144+
* WebHttpHandlerBuilder#applicationContext}.
145+
* @see org.springframework.web.server.adapter.WebHttpHandlerBuilder#applicationContext(ApplicationContext)
146+
* @since 5.0.3
147+
*/
148+
@Nullable
149+
ApplicationContext getApplicationContext();
150+
139151
/**
140152
* Returns {@code true} if the one of the {@code checkNotModified} methods
141153
* in this contract were used and they returned true.

spring-web/src/main/java/org/springframework/web/server/ServerWebExchangeDecorator.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
import reactor.core.publisher.Mono;
2424

25+
import org.springframework.context.ApplicationContext;
2526
import org.springframework.context.i18n.LocaleContext;
2627
import org.springframework.http.codec.multipart.Part;
2728
import org.springframework.http.server.reactive.ServerHttpRequest;
@@ -91,6 +92,11 @@ public LocaleContext getLocaleContext() {
9192
return getDelegate().getLocaleContext();
9293
}
9394

95+
@Override
96+
public ApplicationContext getApplicationContext() {
97+
return getDelegate().getApplicationContext();
98+
}
99+
94100
@Override
95101
public Mono<MultiValueMap<String, String>> getFormData() {
96102
return getDelegate().getFormData();

spring-web/src/main/java/org/springframework/web/server/adapter/DefaultServerWebExchange.java

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
import reactor.core.publisher.Mono;
3030

31+
import org.springframework.context.ApplicationContext;
3132
import org.springframework.context.i18n.LocaleContext;
3233
import org.springframework.core.ResolvableType;
3334
import org.springframework.http.HttpHeaders;
@@ -90,6 +91,9 @@ public class DefaultServerWebExchange implements ServerWebExchange {
9091

9192
private final Mono<MultiValueMap<String, Part>> multipartDataMono;
9293

94+
@Nullable
95+
private final ApplicationContext applicationContext;
96+
9397
private volatile boolean notModified;
9498

9599
private Function<String, String> urlTransformer = url -> url;
@@ -99,6 +103,13 @@ public DefaultServerWebExchange(ServerHttpRequest request, ServerHttpResponse re
99103
WebSessionManager sessionManager, ServerCodecConfigurer codecConfigurer,
100104
LocaleContextResolver localeContextResolver) {
101105

106+
this(request, response, sessionManager, codecConfigurer, localeContextResolver, null);
107+
}
108+
109+
DefaultServerWebExchange(ServerHttpRequest request, ServerHttpResponse response,
110+
WebSessionManager sessionManager, ServerCodecConfigurer codecConfigurer,
111+
LocaleContextResolver localeContextResolver, @Nullable ApplicationContext applicationContext) {
112+
102113
Assert.notNull(request, "'request' is required");
103114
Assert.notNull(response, "'response' is required");
104115
Assert.notNull(sessionManager, "'sessionManager' is required");
@@ -111,6 +122,7 @@ public DefaultServerWebExchange(ServerHttpRequest request, ServerHttpResponse re
111122
this.localeContextResolver = localeContextResolver;
112123
this.formDataMono = initFormData(request, codecConfigurer);
113124
this.multipartDataMono = initMultipartData(request, codecConfigurer);
125+
this.applicationContext = applicationContext;
114126
}
115127

116128
@SuppressWarnings("unchecked")
@@ -191,11 +203,6 @@ public <T extends Principal> Mono<T> getPrincipal() {
191203
return Mono.empty();
192204
}
193205

194-
@Override
195-
public LocaleContext getLocaleContext() {
196-
return this.localeContextResolver.resolveLocaleContext(this);
197-
}
198-
199206
@Override
200207
public Mono<MultiValueMap<String, String>> getFormData() {
201208
return this.formDataMono;
@@ -206,6 +213,16 @@ public Mono<MultiValueMap<String, Part>> getMultipartData() {
206213
return this.multipartDataMono;
207214
}
208215

216+
@Override
217+
public LocaleContext getLocaleContext() {
218+
return this.localeContextResolver.resolveLocaleContext(this);
219+
}
220+
221+
@Override
222+
public ApplicationContext getApplicationContext() {
223+
return this.applicationContext;
224+
}
225+
209226
@Override
210227
public boolean isNotModified() {
211228
return this.notModified;

spring-web/src/main/java/org/springframework/web/server/adapter/HttpWebHandlerAdapter.java

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.apache.commons.logging.LogFactory;
2525
import reactor.core.publisher.Mono;
2626

27+
import org.springframework.context.ApplicationContext;
2728
import org.springframework.core.NestedExceptionUtils;
2829
import org.springframework.http.HttpStatus;
2930
import org.springframework.http.codec.ServerCodecConfigurer;
@@ -90,6 +91,9 @@ public class HttpWebHandlerAdapter extends WebHandlerDecorator implements HttpHa
9091
@Nullable
9192
private LocaleContextResolver localeContextResolver;
9293

94+
@Nullable
95+
private ApplicationContext applicationContext;
96+
9397

9498
public HttpWebHandlerAdapter(WebHandler delegate) {
9599
super(delegate);
@@ -126,6 +130,13 @@ public void setCodecConfigurer(ServerCodecConfigurer codecConfigurer) {
126130
this.codecConfigurer = codecConfigurer;
127131
}
128132

133+
/**
134+
* Return the configured {@link ServerCodecConfigurer}.
135+
*/
136+
public ServerCodecConfigurer getCodecConfigurer() {
137+
return (this.codecConfigurer != null ? this.codecConfigurer : ServerCodecConfigurer.create());
138+
}
139+
129140
/**
130141
* Configure a custom {@link LocaleContextResolver}. The provided instance is set on
131142
* each created {@link DefaultServerWebExchange}.
@@ -137,13 +148,6 @@ public void setLocaleContextResolver(LocaleContextResolver localeContextResolver
137148
this.localeContextResolver = localeContextResolver;
138149
}
139150

140-
/**
141-
* Return the configured {@link ServerCodecConfigurer}.
142-
*/
143-
public ServerCodecConfigurer getCodecConfigurer() {
144-
return (this.codecConfigurer != null ? this.codecConfigurer : ServerCodecConfigurer.create());
145-
}
146-
147151
/**
148152
* Return the configured {@link LocaleContextResolver}.
149153
*/
@@ -152,6 +156,27 @@ public LocaleContextResolver getLocaleContextResolver() {
152156
this.localeContextResolver : new AcceptHeaderLocaleContextResolver());
153157
}
154158

159+
/**
160+
* Configure the {@code ApplicationContext} associated with the web application,
161+
* if it was initialized with one via
162+
* {@link org.springframework.web.server.adapter.WebHttpHandlerBuilder#applicationContext
163+
* WebHttpHandlerBuilder#applicationContext}.
164+
* @param applicationContext the context
165+
* @since 5.0.3
166+
*/
167+
public void setApplicationContext(ApplicationContext applicationContext) {
168+
this.applicationContext = applicationContext;
169+
}
170+
171+
/**
172+
* Return the configured {@code ApplicationContext}, if any.
173+
* @since 5.0.3
174+
*/
175+
@Nullable
176+
public ApplicationContext getApplicationContext() {
177+
return this.applicationContext;
178+
}
179+
155180

156181
@Override
157182
public Mono<Void> handle(ServerHttpRequest request, ServerHttpResponse response) {
@@ -163,7 +188,7 @@ public Mono<Void> handle(ServerHttpRequest request, ServerHttpResponse response)
163188

164189
protected ServerWebExchange createExchange(ServerHttpRequest request, ServerHttpResponse response) {
165190
return new DefaultServerWebExchange(request, response, this.sessionManager,
166-
getCodecConfigurer(), getLocaleContextResolver());
191+
getCodecConfigurer(), getLocaleContextResolver(), this.applicationContext);
167192
}
168193

169194
private Mono<Void> handleFailure(ServerHttpResponse response, Throwable ex) {

spring-web/src/main/java/org/springframework/web/server/adapter/WebHttpHandlerBuilder.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@ public class WebHttpHandlerBuilder {
9292
@Nullable
9393
private LocaleContextResolver localeContextResolver;
9494

95+
@Nullable
96+
private ApplicationContext applicationContext;
97+
9598

9699
/**
97100
* Private constructor.
@@ -101,6 +104,15 @@ private WebHttpHandlerBuilder(WebHandler webHandler) {
101104
this.webHandler = webHandler;
102105
}
103106

107+
/**
108+
* Private constructor to use when initialized from an ApplicationContext.
109+
*/
110+
private WebHttpHandlerBuilder(WebHandler webHandler, ApplicationContext applicationContext) {
111+
Assert.notNull(webHandler, "WebHandler must not be null");
112+
this.webHandler = webHandler;
113+
this.applicationContext = applicationContext;
114+
}
115+
104116
/**
105117
* Copy constructor.
106118
*/
@@ -144,8 +156,9 @@ public static WebHttpHandlerBuilder webHandler(WebHandler webHandler) {
144156
* @return the prepared builder
145157
*/
146158
public static WebHttpHandlerBuilder applicationContext(ApplicationContext context) {
159+
147160
WebHttpHandlerBuilder builder = new WebHttpHandlerBuilder(
148-
context.getBean(WEB_HANDLER_BEAN_NAME, WebHandler.class));
161+
context.getBean(WEB_HANDLER_BEAN_NAME, WebHandler.class), context);
149162

150163
// Autowire lists for @Bean + @Order
151164

@@ -275,6 +288,9 @@ public HttpHandler build() {
275288
if (this.localeContextResolver != null) {
276289
adapted.setLocaleContextResolver(this.localeContextResolver);
277290
}
291+
if (this.applicationContext != null) {
292+
adapted.setApplicationContext(this.applicationContext);
293+
}
278294

279295
return adapted;
280296
}

spring-web/src/test/java/org/springframework/web/server/adapter/WebHttpHandlerBuilderTests.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,11 @@
3838

3939
import static java.time.Duration.ofMillis;
4040
import static org.junit.Assert.assertEquals;
41+
import static org.junit.Assert.assertSame;
42+
import static org.junit.Assert.assertTrue;
4143

4244
/**
4345
* Unit tests for {@link WebHttpHandlerBuilder}.
44-
*
4546
* @author Rossen Stoyanchev
4647
*/
4748
public class WebHttpHandlerBuilderTests {
@@ -54,6 +55,9 @@ public void orderedWebFilterBeans() throws Exception {
5455

5556
HttpHandler httpHandler = WebHttpHandlerBuilder.applicationContext(context).build();
5657

58+
assertTrue(httpHandler instanceof HttpWebHandlerAdapter);
59+
assertSame(context, ((HttpWebHandlerAdapter) httpHandler).getApplicationContext());
60+
5761
MockServerHttpRequest request = MockServerHttpRequest.get("/").build();
5862
MockServerHttpResponse response = new MockServerHttpResponse();
5963
httpHandler.handle(request, response).block(ofMillis(5000));

0 commit comments

Comments
 (0)