diff --git a/spring-test/src/main/java/org/springframework/test/web/reactive/server/AbstractMockServerSpec.java b/spring-test/src/main/java/org/springframework/test/web/reactive/server/AbstractMockServerSpec.java index 64d6c1c9b55..4982c5b9659 100644 --- a/spring-test/src/main/java/org/springframework/test/web/reactive/server/AbstractMockServerSpec.java +++ b/spring-test/src/main/java/org/springframework/test/web/reactive/server/AbstractMockServerSpec.java @@ -86,7 +86,7 @@ abstract class AbstractMockServerSpec> if (!CollectionUtils.isEmpty(this.filters)) { builder.filters(theFilters -> theFilters.addAll(0, this.filters)); } - if (this.sessionManager != null) { + if (!builder.hasSessionManager() && this.sessionManager != null) { builder.sessionManager(this.sessionManager); } if (!CollectionUtils.isEmpty(this.configurers)) { diff --git a/spring-test/src/test/java/org/springframework/test/web/reactive/server/ApplicationContextSpecTests.java b/spring-test/src/test/java/org/springframework/test/web/reactive/server/ApplicationContextSpecTests.java new file mode 100644 index 00000000000..b946c07d73f --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/web/reactive/server/ApplicationContextSpecTests.java @@ -0,0 +1,84 @@ +/* + * Copyright 2002-2018 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.test.web.reactive.server; + +import org.junit.Test; +import reactor.core.publisher.Mono; + +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.util.ObjectUtils; +import org.springframework.web.reactive.config.EnableWebFlux; +import org.springframework.web.reactive.function.server.RouterFunction; +import org.springframework.web.reactive.function.server.RouterFunctions; +import org.springframework.web.reactive.function.server.ServerResponse; +import org.springframework.web.server.WebSession; +import org.springframework.web.server.session.InMemoryWebSessionStore; +import org.springframework.web.server.session.WebSessionManager; + +import static org.junit.Assert.*; +import static org.springframework.web.reactive.function.server.RequestPredicates.*; + +/** + * Unit tests with {@link ApplicationContextSpec}. + * @author Rossen Stoyanchev + */ +public class ApplicationContextSpecTests { + + + @Test // SPR-17094 + public void sessionManagerBean() { + ApplicationContext context = new AnnotationConfigApplicationContext(WebConfig.class); + ApplicationContextSpec spec = new ApplicationContextSpec(context); + WebTestClient testClient = spec.configureClient().build(); + + WebSessionManager sessionManager = context.getBean("webSessionManager", WebSessionManager.class); + WebSession session = sessionManager.getSession(null).block(); + assertNotNull(session); + String expected = ObjectUtils.getIdentityHexString(session); + + for (int i=0; i < 2; i++) { + testClient.get().uri("/sessionIdentityHex") + .exchange() + .expectStatus().isOk() + .expectBody(String.class).isEqualTo(expected); + } + } + + + @Configuration + @EnableWebFlux + static class WebConfig { + + @Bean + public RouterFunction handler() { + return RouterFunctions.route(GET("/sessionIdentityHex"), + request -> request.session().flatMap(session -> { + String value = ObjectUtils.getIdentityHexString(session); + return ServerResponse.ok().syncBody(value); + })); + } + + @Bean + public WebSessionManager webSessionManager() { + WebSession session = new InMemoryWebSessionStore().createWebSession().block(); + return exchange -> Mono.just(session); + } + } + +} diff --git a/spring-web/src/main/java/org/springframework/web/server/adapter/WebHttpHandlerBuilder.java b/spring-web/src/main/java/org/springframework/web/server/adapter/WebHttpHandlerBuilder.java index ce3648d3b19..5d42d49324c 100644 --- a/spring-web/src/main/java/org/springframework/web/server/adapter/WebHttpHandlerBuilder.java +++ b/spring-web/src/main/java/org/springframework/web/server/adapter/WebHttpHandlerBuilder.java @@ -240,8 +240,17 @@ public class WebHttpHandlerBuilder { } /** - * Configure the {@link ServerCodecConfigurer} to set on the - * {@link ServerWebExchange WebServerExchange}. + * Whether a {@code WebSessionManager} is configured or not, either + * detected from an {@code ApplicationContext} or explicitly configured via + * {@link #sessionManager(WebSessionManager)}. + * @since 5.0.9 + */ + public boolean hasSessionManager() { + return this.sessionManager != null; + } + + /** + * Configure the {@link ServerCodecConfigurer} to set on the {@code WebServerExchange}. * @param codecConfigurer the codec configurer */ public WebHttpHandlerBuilder codecConfigurer(ServerCodecConfigurer codecConfigurer) { @@ -249,6 +258,17 @@ public class WebHttpHandlerBuilder { return this; } + + /** + * Whether a {@code ServerCodecConfigurer} is configured or not, either + * detected from an {@code ApplicationContext} or explicitly configured via + * {@link #codecConfigurer(ServerCodecConfigurer)}. + * @since 5.0.9 + */ + public boolean hasCodecConfigurer() { + return this.codecConfigurer != null; + } + /** * Configure the {@link LocaleContextResolver} to set on the * {@link ServerWebExchange WebServerExchange}. @@ -259,6 +279,16 @@ public class WebHttpHandlerBuilder { return this; } + /** + * Whether a {@code LocaleContextResolver} is configured or not, either + * detected from an {@code ApplicationContext} or explicitly configured via + * {@link #localeContextResolver(LocaleContextResolver)}. + * @since 5.0.9 + */ + public boolean hasLocaleContextResolver() { + return this.localeContextResolver != null; + } + /** * Build the {@link HttpHandler}.