From 0be00e2a6d1575e33e9486a3f2118c8a870298a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edd=C3=BA=20Mel=C3=A9ndez?= Date: Tue, 5 Apr 2016 19:36:42 +1000 Subject: [PATCH] Polish session auto-configuration See gh-5158 --- .../HazelcastSessionConfiguration.java | 13 +- .../session/JdbcSessionConfiguration.java | 59 +++++++++ .../session/MongoSessionConfiguration.java | 58 +++++++++ .../session/RedisSessionConfiguration.java | 15 +-- .../session/SessionAutoConfiguration.java | 12 +- .../session/SessionCondition.java | 2 +- .../session/SessionProperties.java | 6 +- .../session/SessionStoreMappings.java | 34 ++--- .../session/SimpleSessionConfiguration.java | 2 - .../{SessionStoreType.java => StoreType.java} | 15 ++- .../autoconfigure/session/package-info.java | 20 +++ .../session/StoreTypesConfigurationTests.java | 120 ++++++++++++++++++ .../web/FilterOrderingIntegrationTests.java | 3 + .../appendix-application-properties.adoc | 3 + .../main/asciidoc/spring-boot-features.adoc | 16 ++- 15 files changed, 332 insertions(+), 46 deletions(-) create mode 100644 spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/JdbcSessionConfiguration.java create mode 100644 spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/MongoSessionConfiguration.java rename spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/{SessionStoreType.java => StoreType.java} (86%) create mode 100644 spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/package-info.java create mode 100644 spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/StoreTypesConfigurationTests.java diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/HazelcastSessionConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/HazelcastSessionConfiguration.java index a59310fabe..95f2f15587 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/HazelcastSessionConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/HazelcastSessionConfiguration.java @@ -20,32 +20,29 @@ import javax.annotation.PostConstruct; import com.hazelcast.core.HazelcastInstance; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.session.MapSessionRepository; -import org.springframework.session.SessionRepository; import org.springframework.session.hazelcast.config.annotation.web.http.EnableHazelcastHttpSession; -import org.springframework.session.hazelcast.config.annotation.web.http.HazelcastHttpSessionConfiguration; /** * Hazelcast backed session auto-configuration. * * @author Tommy Ludwig + * @author Eddú Meléndez * @since 1.4.0 */ @Configuration -@ConditionalOnClass({ HazelcastInstance.class, HazelcastHttpSessionConfiguration.class }) -@ConditionalOnMissingBean({ SessionRepository.class, HazelcastHttpSessionConfiguration.class }) +@ConditionalOnBean({ HazelcastInstance.class }) @EnableHazelcastHttpSession @Conditional(SessionCondition.class) class HazelcastSessionConfiguration { - private final ServerProperties serverProperties; + private ServerProperties serverProperties; - private final MapSessionRepository sessionRepository; + private MapSessionRepository sessionRepository; HazelcastSessionConfiguration(ServerProperties serverProperties, MapSessionRepository sessionRepository) { this.serverProperties = serverProperties; diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/JdbcSessionConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/JdbcSessionConfiguration.java new file mode 100644 index 0000000000..7a4c8f7fad --- /dev/null +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/JdbcSessionConfiguration.java @@ -0,0 +1,59 @@ +/* + * Copyright 2012-2016 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.boot.autoconfigure.session; + +import javax.annotation.PostConstruct; +import javax.sql.DataSource; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.web.ServerProperties; +import org.springframework.context.annotation.Conditional; +import org.springframework.context.annotation.Configuration; +import org.springframework.session.jdbc.JdbcOperationsSessionRepository; +import org.springframework.session.jdbc.config.annotation.web.http.EnableJdbcHttpSession; + +/** + * JDBC backed session auto-configuration. + * + * @author Eddú Meléndez + * @since 1.4.0 + */ +@Configuration +@ConditionalOnBean(DataSource.class) +@EnableJdbcHttpSession +@Conditional(SessionCondition.class) +class JdbcSessionConfiguration { + + private ServerProperties serverProperties; + + private JdbcOperationsSessionRepository sessionRepository; + + JdbcSessionConfiguration(ServerProperties serverProperties, + JdbcOperationsSessionRepository sessionRepository) { + this.serverProperties = serverProperties; + this.sessionRepository = sessionRepository; + } + + @PostConstruct + public void applyConfigurationProperties() { + Integer timeout = this.serverProperties.getSession().getTimeout(); + if (timeout != null) { + this.sessionRepository.setDefaultMaxInactiveInterval(timeout); + } + } + +} diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/MongoSessionConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/MongoSessionConfiguration.java new file mode 100644 index 0000000000..1eb6f9d86c --- /dev/null +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/MongoSessionConfiguration.java @@ -0,0 +1,58 @@ +/* + * Copyright 2012-2016 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.boot.autoconfigure.session; + +import javax.annotation.PostConstruct; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.web.ServerProperties; +import org.springframework.context.annotation.Conditional; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.mongodb.core.MongoOperations; +import org.springframework.session.data.mongo.MongoOperationsSessionRepository; +import org.springframework.session.data.mongo.config.annotation.web.http.EnableMongoHttpSession; + +/** + * Mongo backed session auto-configuration. + * + * @author Eddú Meléndez + * @since 1.4.0 + */ +@Configuration +@ConditionalOnBean(MongoOperations.class) +@EnableMongoHttpSession +@Conditional(SessionCondition.class) +class MongoSessionConfiguration { + + private ServerProperties serverProperties; + + private MongoOperationsSessionRepository sessionRepository; + + MongoSessionConfiguration(ServerProperties serverProperties, MongoOperationsSessionRepository sessionRepository) { + this.serverProperties = serverProperties; + this.sessionRepository = sessionRepository; + } + + @PostConstruct + public void applyConfigurationProperties() { + Integer timeout = this.serverProperties.getSession().getTimeout(); + if (timeout != null) { + this.sessionRepository.setMaxInactiveIntervalInSeconds(timeout); + } + } + +} diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/RedisSessionConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/RedisSessionConfiguration.java index 402f2ed05e..43ae37ebd4 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/RedisSessionConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/RedisSessionConfiguration.java @@ -18,34 +18,31 @@ package org.springframework.boot.autoconfigure.session; import javax.annotation.PostConstruct; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; -import org.springframework.data.redis.connection.RedisConnectionFactory; -import org.springframework.session.SessionRepository; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.session.data.redis.RedisOperationsSessionRepository; import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession; -import org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration; /** * Redis backed session auto-configuration. * * @author Andy Wilkinson * @author Tommy Ludwig + * @author Eddú Meléndez * @since 1.4.0 */ @Configuration -@ConditionalOnClass(RedisConnectionFactory.class) -@ConditionalOnMissingBean({ SessionRepository.class, RedisHttpSessionConfiguration.class }) +@ConditionalOnBean({RedisTemplate.class}) @EnableRedisHttpSession @Conditional(SessionCondition.class) class RedisSessionConfiguration { - private final ServerProperties serverProperties; + private ServerProperties serverProperties; - private final RedisOperationsSessionRepository sessionRepository; + private RedisOperationsSessionRepository sessionRepository; RedisSessionConfiguration(ServerProperties serverProperties, RedisOperationsSessionRepository sessionRepository) { this.serverProperties = serverProperties; diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/SessionAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/SessionAutoConfiguration.java index a3cb962a98..34635ededb 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/SessionAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/SessionAutoConfiguration.java @@ -24,8 +24,11 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplicat import org.springframework.boot.autoconfigure.condition.SearchStrategy; import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; import org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration; import org.springframework.boot.autoconfigure.session.SessionAutoConfiguration.SessionConfigurationImportSelector; import org.springframework.boot.autoconfigure.web.ServerProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @@ -39,13 +42,16 @@ import org.springframework.session.SessionRepository; * * @author Andy Wilkinson * @author Tommy Ludwig + * @author Eddú Meléndez * @since 1.3.0 */ @Configuration @ConditionalOnClass(Session.class) @ConditionalOnWebApplication @ConditionalOnMissingBean(SessionRepository.class) -@AutoConfigureAfter({ HazelcastAutoConfiguration.class, RedisAutoConfiguration.class }) +@EnableConfigurationProperties(SessionProperties.class) +@AutoConfigureAfter({ DataSourceAutoConfiguration.class, HazelcastAutoConfiguration.class, + MongoAutoConfiguration.class, RedisAutoConfiguration.class }) @Import(SessionConfigurationImportSelector.class) public class SessionAutoConfiguration { @@ -63,13 +69,13 @@ public class SessionAutoConfiguration { } /** - * {@link ImportSelector} to add {@link SessionStoreType} configuration classes. + * {@link ImportSelector} to add {@link StoreType} configuration classes. */ static class SessionConfigurationImportSelector implements ImportSelector { @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { - SessionStoreType[] types = SessionStoreType.values(); + StoreType[] types = StoreType.values(); String[] imports = new String[types.length]; for (int i = 0; i < types.length; i++) { imports[i] = SessionStoreMappings.getConfigurationClass(types[i]); diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/SessionCondition.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/SessionCondition.java index a3a3261a8d..5eee81e6a1 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/SessionCondition.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/SessionCondition.java @@ -38,7 +38,7 @@ class SessionCondition extends SpringBootCondition { if (!resolver.containsProperty("type")) { return ConditionOutcome.match("Automatic session store type"); } - SessionStoreType sessionStoreType = SessionStoreMappings + StoreType sessionStoreType = SessionStoreMappings .getType(((AnnotationMetadata) metadata).getClassName()); String value = resolver.getProperty("type").replace("-", "_").toUpperCase(); if (value.equals(sessionStoreType.name())) { diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/SessionProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/SessionProperties.java index 66b5eea50d..ed2234195e 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/SessionProperties.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/SessionProperties.java @@ -44,13 +44,13 @@ public class SessionProperties { /** * Session data store type, auto-detected according to the environment by default. */ - private SessionStoreType type; + private StoreType type; - public SessionStoreType getType() { + public StoreType getType() { return this.type; } - public void setType(SessionStoreType type) { + public void setType(StoreType type) { this.type = type; } } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/SessionStoreMappings.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/SessionStoreMappings.java index 50078464af..f296e324d1 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/SessionStoreMappings.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/SessionStoreMappings.java @@ -23,35 +23,39 @@ import java.util.Map; import org.springframework.util.Assert; /** - * Mappings between {@link SessionStoreType} and {@code @Configuration}. + * Mappings between {@link StoreType} and {@code @Configuration}. * * @author Tommy Ludwig + * @author Eddú Meléndez + * @since 1.4.0 */ final class SessionStoreMappings { + private static final Map> MAPPINGS; + + static { + Map> mappings = new HashMap>(); + mappings.put(StoreType.JDBC, JdbcSessionConfiguration.class); + mappings.put(StoreType.MONGO, MongoSessionConfiguration.class); + mappings.put(StoreType.REDIS, RedisSessionConfiguration.class); + mappings.put(StoreType.HAZELCAST, HazelcastSessionConfiguration.class); + mappings.put(StoreType.HASH_MAP, SimpleSessionConfiguration.class); + mappings.put(StoreType.NONE, NoOpSessionConfiguration.class); + MAPPINGS = Collections.unmodifiableMap(mappings); + } + private SessionStoreMappings() { } - private static final Map> MAPPINGS; - - static { - Map> mappings = new HashMap>(); - mappings.put(SessionStoreType.REDIS, RedisSessionConfiguration.class); - mappings.put(SessionStoreType.HAZELCAST, HazelcastSessionConfiguration.class); - mappings.put(SessionStoreType.SIMPLE, SimpleSessionConfiguration.class); - mappings.put(SessionStoreType.NONE, NoOpSessionConfiguration.class); - MAPPINGS = Collections.unmodifiableMap(mappings); - } - - public static String getConfigurationClass(SessionStoreType sessionStoreType) { + public static String getConfigurationClass(StoreType sessionStoreType) { Class configurationClass = MAPPINGS.get(sessionStoreType); Assert.state(configurationClass != null, "Unknown session store type " + sessionStoreType); return configurationClass.getName(); } - public static SessionStoreType getType(String configurationClassName) { - for (Map.Entry> entry : MAPPINGS.entrySet()) { + public static StoreType getType(String configurationClassName) { + for (Map.Entry> entry : MAPPINGS.entrySet()) { if (entry.getValue().getName().equals(configurationClassName)) { return entry.getKey(); } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/SimpleSessionConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/SimpleSessionConfiguration.java index 4334782787..d13ca68db6 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/SimpleSessionConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/SimpleSessionConfiguration.java @@ -16,7 +16,6 @@ package org.springframework.boot.autoconfigure.session; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; @@ -33,7 +32,6 @@ import org.springframework.session.config.annotation.web.http.EnableSpringHttpSe * @since 1.4.0 */ @Configuration -@ConditionalOnMissingBean(SessionRepository.class) @EnableSpringHttpSession @Conditional(SessionCondition.class) class SimpleSessionConfiguration { diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/SessionStoreType.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/StoreType.java similarity index 86% rename from spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/SessionStoreType.java rename to spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/StoreType.java index ce508c5896..4a86634029 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/SessionStoreType.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/StoreType.java @@ -20,9 +20,20 @@ package org.springframework.boot.autoconfigure.session; * Supported Spring Session data store types. * * @author Tommy Ludwig + * @author Eddú Meléndez * @since 1.4.0 */ -public enum SessionStoreType { +public enum StoreType { + + /** + * JDBC backed sessions. + */ + JDBC, + + /** + * Mongo backed sessions. + */ + MONGO, /** * Redis backed sessions. @@ -37,7 +48,7 @@ public enum SessionStoreType { /** * Simple in-memory map of sessions. */ - SIMPLE, + HASH_MAP, /** * No session datastore. diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/package-info.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/package-info.java new file mode 100644 index 0000000000..8534bf744d --- /dev/null +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2012-2016 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. + */ + +/** + * Auto-configuration for Spring Session. + */ +package org.springframework.boot.autoconfigure.session; diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/StoreTypesConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/StoreTypesConfigurationTests.java new file mode 100644 index 0000000000..3f4fb87e66 --- /dev/null +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/StoreTypesConfigurationTests.java @@ -0,0 +1,120 @@ +/* + * Copyright 2012-2016 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.boot.autoconfigure.session; + +import java.net.UnknownHostException; + +import com.hazelcast.core.Hazelcast; +import com.hazelcast.core.HazelcastInstance; + +import com.mongodb.MongoClient; +import org.junit.After; +import org.junit.Test; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration; +import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration; +import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration; +import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration; +import org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration; +import org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration; +import org.springframework.boot.test.util.EnvironmentTestUtils; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.session.MapSessionRepository; +import org.springframework.session.data.mongo.MongoOperationsSessionRepository; +import org.springframework.session.jdbc.JdbcOperationsSessionRepository; +import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; + +import static org.assertj.core.api.Assertions.assertThat; + +public class StoreTypesConfigurationTests { + + private AnnotationConfigWebApplicationContext context; + + @After + public void close() { + if (this.context != null) { + this.context.close(); + } + } + + @Test + public void hashMapSessionStore() { + load("spring.session.store.type=hash-map"); + MapSessionRepository sessionRepository = this.context.getBean(MapSessionRepository.class); + assertThat(sessionRepository).isNotNull(); + } + + @Test + public void jdbcSessionStore() { + load(new String[] {"spring.session.store.type=jdbc"}, EmbeddedDataSourceConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class); + assertThat(this.context.getBean(JdbcOperationsSessionRepository.class)).isNotNull(); + } + + @Test + public void hazelcastSessionStore() { + load(new String[] {"spring.session.store.type=hazelcast"}, MockHazelcastInstanceConfiguration.class); + assertThat(this.context.getBean(MapSessionRepository.class)).isNotNull(); + } + + @Test + public void mongoSessionStore() { + load(new String[] {"spring.session.store.type=mongo", "spring.data.mongodb.port=0"}, MockMongoConfiguration.class, MongoDataAutoConfiguration.class, EmbeddedMongoAutoConfiguration.class); + assertThat(this.context.getBean(MongoOperationsSessionRepository.class)).isNotNull(); + } + + private void load(String storeType) { + load(new String[] {storeType}, null); + } + + private void load(String[] storeType, Class... config) { + this.context = new AnnotationConfigWebApplicationContext(); + for (String property : storeType) { + EnvironmentTestUtils.addEnvironment(this.context, storeType); + } + if (config != null) { + this.context.register(config); + } + this.context.register(ServerPropertiesAutoConfiguration.class, + SessionAutoConfiguration.class, + PropertyPlaceholderAutoConfiguration.class); + this.context.refresh(); + } + + @Configuration + static class MockHazelcastInstanceConfiguration { + + @Bean + public HazelcastInstance hazelcastInstance() { + return Hazelcast.newHazelcastInstance(); + } + + } + + @Configuration + static class MockMongoConfiguration { + + @Bean + public MongoClient mongoClient(@Value("${local.mongo.port}") int port) + throws UnknownHostException { + return new MongoClient("localhost", port); + } + + } + +} diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/FilterOrderingIntegrationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/FilterOrderingIntegrationTests.java index cbc9f0c9a7..8763fa4e70 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/FilterOrderingIntegrationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/FilterOrderingIntegrationTests.java @@ -34,6 +34,7 @@ import org.springframework.boot.context.embedded.MockEmbeddedServletContainerFac import org.springframework.boot.context.embedded.MockEmbeddedServletContainerFactory.RegisteredFilter; import org.springframework.boot.web.filter.OrderedCharacterEncodingFilter; import org.springframework.boot.web.filter.OrderedRequestContextFilter; +import org.springframework.boot.test.util.EnvironmentTestUtils; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnection; @@ -49,6 +50,7 @@ import static org.mockito.Mockito.mock; * Integration tests that verify the ordering of various filters that are auto-configured. * * @author Andy Wilkinson + * @author Eddú Meléndez */ public class FilterOrderingIntegrationTests { @@ -82,6 +84,7 @@ public class FilterOrderingIntegrationTests { private void load() { this.context = new AnnotationConfigEmbeddedWebApplicationContext(); + EnvironmentTestUtils.addEnvironment(this.context, "spring.session.store.type=hash-map"); this.context.register(MockEmbeddedServletContainerConfiguration.class, TestRedisConfiguration.class, WebMvcAutoConfiguration.class, SecurityAutoConfiguration.class, SessionAutoConfiguration.class, diff --git a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc index 11888e8804..60a8687f2b 100644 --- a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc +++ b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc @@ -356,6 +356,9 @@ content into your application; rather pick only the properties that you need. spring.resources.chain.strategy.fixed.version= # Version string to use for the Version Strategy. spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/ # Locations of static resources. + # SPRING SESSION ({sc-spring-boot-autoconfigure}/session/SocialWebAutoConfiguration.{sc-ext}[SessionAutoConfiguration]) + spring.session.store.store-type= # Session store type + # SPRING SOCIAL ({sc-spring-boot-autoconfigure}/social/SocialWebAutoConfiguration.{sc-ext}[SocialWebAutoConfiguration]) spring.social.auto-connection-views=false # Enable the connection status view for supported providers. diff --git a/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc b/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc index ea500f111a..ebda36d136 100644 --- a/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc +++ b/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc @@ -4393,11 +4393,21 @@ class for more details. [[boot-features-session]] == Spring Session Spring Session provides support for managing a user's session information. If you are -writing a web application and Spring Session and Spring Data Redis are both on the -classpath, Spring Boot will auto-configure Spring Session through its -`@EnableRedisHttpSession`. Session data will be stored in Redis and the session timeout +writing a web application and Spring Session and one the following providers: + +* JDBC +* Hazelcast +* Spring Data Mongo +* Spring Data Redis + +on the classpath, Spring Boot will auto-configure Spring Session through its +`@EnableJdbcHttpSession`, `@EnableHazelcastHttpSession`, `@EnableMongoHttpSession`, +`@EnableRedisHttpSession`. Session data will be stored in the provider and the session timeout can be configured using the `server.session.timeout` property. +It is also possible to _force_ the session provider to use via the `spring.session.store.type` +property. + [[boot-features-jmx]]