From 8b233e84ef3aa51bb00d123a5fabea9b6dfd7dac Mon Sep 17 00:00:00 2001 From: Greg Turnquist Date: Wed, 23 Aug 2017 17:01:40 -0500 Subject: [PATCH] Create @EnableSpringWebSession annotation. --- .../session/EnableSpringWebSession.java | 54 ++++++++++++ .../SpringWebSessionConfiguration.java | 45 ++++++++++ .../SpringWebSessionConfigurationTests.java | 86 +++++++++++++++++++ 3 files changed, 185 insertions(+) create mode 100644 spring-session-core/src/main/java/org/springframework/session/EnableSpringWebSession.java create mode 100644 spring-session-core/src/main/java/org/springframework/session/SpringWebSessionConfiguration.java create mode 100644 spring-session-core/src/test/java/org/springframework/session/SpringWebSessionConfigurationTests.java diff --git a/spring-session-core/src/main/java/org/springframework/session/EnableSpringWebSession.java b/spring-session-core/src/main/java/org/springframework/session/EnableSpringWebSession.java new file mode 100644 index 00000000..ede6b0a1 --- /dev/null +++ b/spring-session-core/src/main/java/org/springframework/session/EnableSpringWebSession.java @@ -0,0 +1,54 @@ +/* + * Copyright 2014-2017 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.session; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +/** + * Add this annotation to a {@code @Configuration} class to configure a {@code WebSessionManager} for a WebFlux + * application. This annotation assumes a {@code ReactorSessionRepository} is defined somewhere in the application + * context. If not, it will fail with a clear error messages. For example: + * + *
+ * 
+ * {@literal @Configuration}
+ * {@literal @EnableSpringWebSession}
+ * public class SpringWebFluxConfig {
+ *
+ *     {@literal @Bean}
+ *     public ReactorSessionRepository sessionRepository() {
+ *         return new MapReactorSessionRepository();
+ *     }
+ *
+ * }
+ * 
+ * 
+ * + * @author Greg Turnquist + * @since 2.0 + */ +@Retention(java.lang.annotation.RetentionPolicy.RUNTIME) +@Target({ java.lang.annotation.ElementType.TYPE }) +@Documented +@Import(SpringWebSessionConfiguration.class) +@Configuration +public @interface EnableSpringWebSession { +} diff --git a/spring-session-core/src/main/java/org/springframework/session/SpringWebSessionConfiguration.java b/spring-session-core/src/main/java/org/springframework/session/SpringWebSessionConfiguration.java new file mode 100644 index 00000000..925687b6 --- /dev/null +++ b/spring-session-core/src/main/java/org/springframework/session/SpringWebSessionConfiguration.java @@ -0,0 +1,45 @@ +/* + * Copyright 2014-2017 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.session; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.session.web.server.session.SpringSessionWebSessionManager; +import org.springframework.web.server.adapter.WebHttpHandlerBuilder; +import org.springframework.web.server.session.WebSessionManager; + +/** + * Wire up a {@link WebSessionManager} using a Reactive {@link ReactorSessionRepository} from the application context. + * + * @author Greg Turnquist + * @since 2.0 + * + * @see EnableSpringWebSession + */ +@Configuration +public class SpringWebSessionConfiguration { + + /** + * Configure a {@link WebSessionManager} using a provided {@link ReactorSessionRepository}. + * + * @param repository - a bean that implements {@link ReactorSessionRepository}. + * @return a configured {@link WebSessionManager} registered with a preconfigured name. + */ + @Bean(WebHttpHandlerBuilder.WEB_SESSION_MANAGER_BEAN_NAME) + public WebSessionManager webSessionManager(ReactorSessionRepository repository) { + return new SpringSessionWebSessionManager(repository); + } +} diff --git a/spring-session-core/src/test/java/org/springframework/session/SpringWebSessionConfigurationTests.java b/spring-session-core/src/test/java/org/springframework/session/SpringWebSessionConfigurationTests.java new file mode 100644 index 00000000..aa3b45ff --- /dev/null +++ b/spring-session-core/src/test/java/org/springframework/session/SpringWebSessionConfigurationTests.java @@ -0,0 +1,86 @@ +/* + * Copyright 2014-2017 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.session; + +import org.junit.Test; +import org.springframework.beans.factory.UnsatisfiedDependencyException; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.web.server.adapter.WebHttpHandlerBuilder; +import org.springframework.web.server.session.WebSessionManager; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +/** + * Verify various configurations through {@link EnableSpringWebSession}. + * + * @author Greg Turnquist + */ +public class SpringWebSessionConfigurationTests { + + @Test + public void enableSpringWebSessionConfiguresThings() { + + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + ctx.register(GoodConfig.class); + ctx.refresh(); + + WebSessionManager webSessionManagerFoundByType = ctx.getBean(WebSessionManager.class); + Object webSessionManagerFoundByName = ctx.getBean(WebHttpHandlerBuilder.WEB_SESSION_MANAGER_BEAN_NAME); + + assertThat(webSessionManagerFoundByType).isNotNull(); + assertThat(webSessionManagerFoundByName).isNotNull(); + assertThat(webSessionManagerFoundByType).isEqualTo(webSessionManagerFoundByName); + + assertThat(ctx.getBean(ReactorSessionRepository.class)).isNotNull(); + } + + @Test + public void missingReactorSessionRepositoryBreaksAppContext() { + + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + ctx.register(BadConfig.class); + + assertThatExceptionOfType(UnsatisfiedDependencyException.class) + .isThrownBy(ctx::refresh) + .withMessageContaining("Error creating bean with name 'webSessionManager'") + .withMessageContaining("No qualifying bean of type '" + ReactorSessionRepository.class.getCanonicalName()); + } + + /** + * A configuration with all the right parts. + */ + @EnableSpringWebSession + static class GoodConfig { + + /** + * Use Reactor-friendly, {@link java.util.Map}-backed {@link ReactorSessionRepository} for test purposes. + */ + @Bean + ReactorSessionRepository reactorSessionRepository() { + return new MapReactorSessionRepository(); + } + } + + /** + * A configuration where no {@link ReactorSessionRepository} is defined. It's BAD! + */ + @EnableSpringWebSession + static class BadConfig { + + } +}