Create spring-boot-session modules
This commit is contained in:
committed by
Phillip Webb
parent
014240d576
commit
e288c81b7b
@@ -107,6 +107,11 @@ include "spring-boot-project:spring-boot-security-oauth2-client"
|
||||
include "spring-boot-project:spring-boot-security-oauth2-resource-server"
|
||||
include "spring-boot-project:spring-boot-security-saml2"
|
||||
include "spring-boot-project:spring-boot-sendgrid"
|
||||
include "spring-boot-project:spring-boot-session"
|
||||
include "spring-boot-project:spring-boot-session-data-mongodb"
|
||||
include "spring-boot-project:spring-boot-session-data-redis"
|
||||
include "spring-boot-project:spring-boot-session-hazelcast"
|
||||
include "spring-boot-project:spring-boot-session-jdbc"
|
||||
include "spring-boot-project:spring-boot-test"
|
||||
include "spring-boot-project:spring-boot-test-autoconfigure"
|
||||
include "spring-boot-project:spring-boot-test-integration-tests"
|
||||
|
||||
@@ -60,6 +60,7 @@ dependencies {
|
||||
optional(project(":spring-boot-project:spring-boot-security-oauth2-client"))
|
||||
optional(project(":spring-boot-project:spring-boot-security-oauth2-resource-server"))
|
||||
optional(project(":spring-boot-project:spring-boot-security-saml2"))
|
||||
optional(project(":spring-boot-project:spring-boot-session"))
|
||||
optional(project(":spring-boot-project:spring-boot-tomcat"))
|
||||
optional(project(":spring-boot-project:spring-boot-undertow"))
|
||||
optional(project(":spring-boot-project:spring-boot-validation"))
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
* Copyright 2012-2025 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.
|
||||
@@ -27,7 +27,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
|
||||
import org.springframework.boot.autoconfigure.session.SessionAutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.session.FindByIndexNameSessionRepository;
|
||||
@@ -42,7 +41,7 @@ import org.springframework.session.SessionRepository;
|
||||
* @author Vedran Pavic
|
||||
* @since 2.0.0
|
||||
*/
|
||||
@AutoConfiguration(after = SessionAutoConfiguration.class)
|
||||
@AutoConfiguration(afterName = "org.springframework.boot.session.autoconfigure.SessionAutoConfiguration")
|
||||
@ConditionalOnClass(Session.class)
|
||||
@ConditionalOnAvailableEndpoint(SessionsEndpoint.class)
|
||||
public class SessionsEndpointAutoConfiguration {
|
||||
|
||||
@@ -3,7 +3,6 @@ plugins {
|
||||
id "org.springframework.boot.auto-configuration"
|
||||
id "org.springframework.boot.configuration-properties"
|
||||
id "org.springframework.boot.deployed"
|
||||
id "org.springframework.boot.docker-test"
|
||||
id "org.springframework.boot.optional-dependencies"
|
||||
}
|
||||
|
||||
@@ -23,20 +22,6 @@ dependencies {
|
||||
api(project(":spring-boot-project:spring-boot-all"))
|
||||
api(project(":spring-boot-project:spring-boot-autoconfigure"))
|
||||
|
||||
dockerTestImplementation(project(":spring-boot-project:spring-boot-test"))
|
||||
dockerTestImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support-docker"))
|
||||
dockerTestImplementation(testFixtures(project(":spring-boot-project:spring-boot")))
|
||||
dockerTestImplementation(testFixtures(project(":spring-boot-project:spring-boot-autoconfigure")))
|
||||
dockerTestImplementation("com.redis:testcontainers-redis")
|
||||
dockerTestImplementation("org.assertj:assertj-core")
|
||||
dockerTestImplementation("org.awaitility:awaitility")
|
||||
dockerTestImplementation("org.junit.jupiter:junit-jupiter")
|
||||
dockerTestImplementation("org.mockito:mockito-core")
|
||||
dockerTestImplementation("org.springframework:spring-test")
|
||||
dockerTestImplementation("org.testcontainers:junit-jupiter")
|
||||
dockerTestImplementation("org.testcontainers:mongodb")
|
||||
dockerTestImplementation("org.testcontainers:testcontainers")
|
||||
|
||||
optional(project(":spring-boot-project:spring-boot-activemq"))
|
||||
optional(project(":spring-boot-project:spring-boot-artemis"))
|
||||
optional(project(":spring-boot-project:spring-boot-data-jpa"))
|
||||
@@ -58,6 +43,7 @@ dependencies {
|
||||
optional(project(":spring-boot-project:spring-boot-rsocket"))
|
||||
optional(project(":spring-boot-project:spring-boot-security"))
|
||||
optional(project(":spring-boot-project:spring-boot-security-oauth2-resource-server"))
|
||||
optional(project(":spring-boot-project:spring-boot-session"))
|
||||
optional(project(":spring-boot-project:spring-boot-tomcat"))
|
||||
optional(project(":spring-boot-project:spring-boot-tx"))
|
||||
optional(project(":spring-boot-project:spring-boot-validation"))
|
||||
@@ -162,11 +148,6 @@ dependencies {
|
||||
exclude group: "org.opensaml", module: "opensaml-saml-impl"
|
||||
}
|
||||
optional("org.springframework.security:spring-security-web")
|
||||
optional("org.springframework.session:spring-session-core")
|
||||
optional("org.springframework.session:spring-session-data-mongodb")
|
||||
optional("org.springframework.session:spring-session-data-redis")
|
||||
optional("org.springframework.session:spring-session-hazelcast")
|
||||
optional("org.springframework.session:spring-session-jdbc")
|
||||
optional("org.springframework.amqp:spring-rabbit")
|
||||
optional("org.springframework.amqp:spring-rabbit-stream")
|
||||
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2023 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
|
||||
*
|
||||
* https://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 org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.PropertyMapper;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.mongodb.core.ReactiveMongoOperations;
|
||||
import org.springframework.session.ReactiveSessionRepository;
|
||||
import org.springframework.session.config.ReactiveSessionRepositoryCustomizer;
|
||||
import org.springframework.session.data.mongo.ReactiveMongoSessionRepository;
|
||||
import org.springframework.session.data.mongo.config.annotation.web.reactive.ReactiveMongoWebSessionConfiguration;
|
||||
|
||||
/**
|
||||
* Mongo-backed reactive session configuration.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @author Weix Sun
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass({ ReactiveMongoOperations.class, ReactiveMongoSessionRepository.class })
|
||||
@ConditionalOnMissingBean(ReactiveSessionRepository.class)
|
||||
@ConditionalOnBean(ReactiveMongoOperations.class)
|
||||
@EnableConfigurationProperties(MongoSessionProperties.class)
|
||||
@Import(ReactiveMongoWebSessionConfiguration.class)
|
||||
class MongoReactiveSessionConfiguration {
|
||||
|
||||
@Bean
|
||||
ReactiveSessionRepositoryCustomizer<ReactiveMongoSessionRepository> springBootSessionRepositoryCustomizer(
|
||||
SessionProperties sessionProperties, MongoSessionProperties mongoSessionProperties,
|
||||
ServerProperties serverProperties) {
|
||||
return (sessionRepository) -> {
|
||||
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
|
||||
map.from(sessionProperties.determineTimeout(() -> serverProperties.getReactive().getSession().getTimeout()))
|
||||
.to(sessionRepository::setDefaultMaxInactiveInterval);
|
||||
map.from(mongoSessionProperties::getCollectionName).to(sessionRepository::setCollectionName);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2023 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
|
||||
*
|
||||
* https://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 org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.PropertyMapper;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.data.mongodb.core.MongoOperations;
|
||||
import org.springframework.session.SessionRepository;
|
||||
import org.springframework.session.config.SessionRepositoryCustomizer;
|
||||
import org.springframework.session.data.mongo.MongoIndexedSessionRepository;
|
||||
import org.springframework.session.data.mongo.config.annotation.web.http.MongoHttpSessionConfiguration;
|
||||
|
||||
/**
|
||||
* Mongo-backed session configuration.
|
||||
*
|
||||
* @author Eddú Meléndez
|
||||
* @author Stephane Nicoll
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass({ MongoOperations.class, MongoIndexedSessionRepository.class })
|
||||
@ConditionalOnMissingBean(SessionRepository.class)
|
||||
@ConditionalOnBean(MongoOperations.class)
|
||||
@EnableConfigurationProperties(MongoSessionProperties.class)
|
||||
@Import(MongoHttpSessionConfiguration.class)
|
||||
class MongoSessionConfiguration {
|
||||
|
||||
@Bean
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
SessionRepositoryCustomizer<MongoIndexedSessionRepository> springBootSessionRepositoryCustomizer(
|
||||
SessionProperties sessionProperties, MongoSessionProperties mongoSessionProperties,
|
||||
ServerProperties serverProperties) {
|
||||
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
|
||||
return (sessionRepository) -> {
|
||||
map.from(sessionProperties.determineTimeout(() -> serverProperties.getServlet().getSession().getTimeout()))
|
||||
.to(sessionRepository::setDefaultMaxInactiveInterval);
|
||||
map.from(mongoSessionProperties::getCollectionName).to(sessionRepository::setCollectionName);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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
|
||||
*
|
||||
* https://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 org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.PropertyMapper;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory;
|
||||
import org.springframework.session.ReactiveSessionRepository;
|
||||
import org.springframework.session.config.ReactiveSessionRepositoryCustomizer;
|
||||
import org.springframework.session.data.redis.ReactiveRedisIndexedSessionRepository;
|
||||
import org.springframework.session.data.redis.ReactiveRedisSessionRepository;
|
||||
import org.springframework.session.data.redis.config.ConfigureReactiveRedisAction;
|
||||
import org.springframework.session.data.redis.config.annotation.ConfigureNotifyKeyspaceEventsReactiveAction;
|
||||
import org.springframework.session.data.redis.config.annotation.web.server.RedisIndexedWebSessionConfiguration;
|
||||
import org.springframework.session.data.redis.config.annotation.web.server.RedisWebSessionConfiguration;
|
||||
|
||||
/**
|
||||
* Redis-backed reactive session configuration.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @author Weix Sun
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass({ ReactiveRedisConnectionFactory.class, ReactiveRedisSessionRepository.class })
|
||||
@ConditionalOnMissingBean(ReactiveSessionRepository.class)
|
||||
@ConditionalOnBean(ReactiveRedisConnectionFactory.class)
|
||||
@EnableConfigurationProperties(RedisSessionProperties.class)
|
||||
class RedisReactiveSessionConfiguration {
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnProperty(name = "spring.session.redis.repository-type", havingValue = "default",
|
||||
matchIfMissing = true)
|
||||
@Import(RedisWebSessionConfiguration.class)
|
||||
static class DefaultRedisSessionConfiguration {
|
||||
|
||||
@Bean
|
||||
ReactiveSessionRepositoryCustomizer<ReactiveRedisSessionRepository> springBootSessionRepositoryCustomizer(
|
||||
SessionProperties sessionProperties, RedisSessionProperties redisSessionProperties,
|
||||
ServerProperties serverProperties) {
|
||||
return (sessionRepository) -> {
|
||||
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
|
||||
map.from(sessionProperties
|
||||
.determineTimeout(() -> serverProperties.getReactive().getSession().getTimeout()))
|
||||
.to(sessionRepository::setDefaultMaxInactiveInterval);
|
||||
map.from(redisSessionProperties::getNamespace).to(sessionRepository::setRedisKeyNamespace);
|
||||
map.from(redisSessionProperties::getSaveMode).to(sessionRepository::setSaveMode);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnProperty(name = "spring.session.redis.repository-type", havingValue = "indexed")
|
||||
@Import(RedisIndexedWebSessionConfiguration.class)
|
||||
static class IndexedRedisSessionConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
ConfigureReactiveRedisAction configureReactiveRedisAction(RedisSessionProperties redisSessionProperties) {
|
||||
return switch (redisSessionProperties.getConfigureAction()) {
|
||||
case NOTIFY_KEYSPACE_EVENTS -> new ConfigureNotifyKeyspaceEventsReactiveAction();
|
||||
case NONE -> ConfigureReactiveRedisAction.NO_OP;
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
ReactiveSessionRepositoryCustomizer<ReactiveRedisIndexedSessionRepository> springBootSessionRepositoryCustomizer(
|
||||
SessionProperties sessionProperties, RedisSessionProperties redisSessionProperties,
|
||||
ServerProperties serverProperties) {
|
||||
return (sessionRepository) -> {
|
||||
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
|
||||
map.from(sessionProperties
|
||||
.determineTimeout(() -> serverProperties.getReactive().getSession().getTimeout()))
|
||||
.to(sessionRepository::setDefaultMaxInactiveInterval);
|
||||
map.from(redisSessionProperties::getNamespace).to(sessionRepository::setRedisKeyNamespace);
|
||||
map.from(redisSessionProperties::getSaveMode).to(sessionRepository::setSaveMode);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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
|
||||
*
|
||||
* https://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 org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.PropertyMapper;
|
||||
import org.springframework.boot.context.properties.source.InvalidConfigurationPropertyValueException;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.session.SessionRepository;
|
||||
import org.springframework.session.config.SessionRepositoryCustomizer;
|
||||
import org.springframework.session.data.redis.RedisIndexedSessionRepository;
|
||||
import org.springframework.session.data.redis.RedisSessionRepository;
|
||||
import org.springframework.session.data.redis.config.ConfigureNotifyKeyspaceEventsAction;
|
||||
import org.springframework.session.data.redis.config.ConfigureRedisAction;
|
||||
import org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration;
|
||||
import org.springframework.session.data.redis.config.annotation.web.http.RedisIndexedHttpSessionConfiguration;
|
||||
|
||||
/**
|
||||
* Redis backed session configuration.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @author Tommy Ludwig
|
||||
* @author Eddú Meléndez
|
||||
* @author Stephane Nicoll
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass({ RedisTemplate.class, RedisIndexedSessionRepository.class })
|
||||
@ConditionalOnMissingBean(SessionRepository.class)
|
||||
@ConditionalOnBean(RedisConnectionFactory.class)
|
||||
@EnableConfigurationProperties(RedisSessionProperties.class)
|
||||
class RedisSessionConfiguration {
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnProperty(name = "spring.session.redis.repository-type", havingValue = "default",
|
||||
matchIfMissing = true)
|
||||
@Import(RedisHttpSessionConfiguration.class)
|
||||
static class DefaultRedisSessionConfiguration {
|
||||
|
||||
@Bean
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
SessionRepositoryCustomizer<RedisSessionRepository> springBootSessionRepositoryCustomizer(
|
||||
SessionProperties sessionProperties, RedisSessionProperties redisSessionProperties,
|
||||
ServerProperties serverProperties) {
|
||||
String cleanupCron = redisSessionProperties.getCleanupCron();
|
||||
if (cleanupCron != null) {
|
||||
throw new InvalidConfigurationPropertyValueException("spring.session.redis.cleanup-cron", cleanupCron,
|
||||
"Cron-based cleanup is only supported when "
|
||||
+ "spring.session.redis.repository-type is set to indexed.");
|
||||
}
|
||||
return (sessionRepository) -> {
|
||||
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
|
||||
map.from(sessionProperties
|
||||
.determineTimeout(() -> serverProperties.getServlet().getSession().getTimeout()))
|
||||
.to(sessionRepository::setDefaultMaxInactiveInterval);
|
||||
map.from(redisSessionProperties::getNamespace).to(sessionRepository::setRedisKeyNamespace);
|
||||
map.from(redisSessionProperties::getFlushMode).to(sessionRepository::setFlushMode);
|
||||
map.from(redisSessionProperties::getSaveMode).to(sessionRepository::setSaveMode);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnProperty(name = "spring.session.redis.repository-type", havingValue = "indexed")
|
||||
@Import(RedisIndexedHttpSessionConfiguration.class)
|
||||
static class IndexedRedisSessionConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
ConfigureRedisAction configureRedisAction(RedisSessionProperties redisSessionProperties) {
|
||||
return switch (redisSessionProperties.getConfigureAction()) {
|
||||
case NOTIFY_KEYSPACE_EVENTS -> new ConfigureNotifyKeyspaceEventsAction();
|
||||
case NONE -> ConfigureRedisAction.NO_OP;
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
SessionRepositoryCustomizer<RedisIndexedSessionRepository> springBootSessionRepositoryCustomizer(
|
||||
SessionProperties sessionProperties, RedisSessionProperties redisSessionProperties,
|
||||
ServerProperties serverProperties) {
|
||||
return (sessionRepository) -> {
|
||||
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
|
||||
map.from(sessionProperties
|
||||
.determineTimeout(() -> serverProperties.getServlet().getSession().getTimeout()))
|
||||
.to(sessionRepository::setDefaultMaxInactiveInterval);
|
||||
map.from(redisSessionProperties::getNamespace).to(sessionRepository::setRedisKeyNamespace);
|
||||
map.from(redisSessionProperties::getFlushMode).to(sessionRepository::setFlushMode);
|
||||
map.from(redisSessionProperties::getSaveMode).to(sessionRepository::setSaveMode);
|
||||
map.from(redisSessionProperties::getCleanupCron).to(sessionRepository::setCleanupCron);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -460,18 +460,6 @@
|
||||
"description": "Whether to enable Servlet HTTP encoding support.",
|
||||
"defaultValue": true
|
||||
},
|
||||
{
|
||||
"name": "spring.session.redis.cleanup-cron",
|
||||
"defaultValue": "0 * * * * *"
|
||||
},
|
||||
{
|
||||
"name": "spring.session.servlet.filter-dispatcher-types",
|
||||
"defaultValue": [
|
||||
"async",
|
||||
"error",
|
||||
"request"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "spring.sql.init.enabled",
|
||||
"type": "java.lang.Boolean",
|
||||
|
||||
@@ -17,7 +17,6 @@ org.springframework.boot.autoconfigure.http.client.reactive.ClientHttpConnectorA
|
||||
org.springframework.boot.autoconfigure.http.client.reactive.service.ReactiveHttpServiceClientAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.netty.NettyAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.reactor.ReactorAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.web.reactive.function.client.ClientHttpConnectorAutoConfiguration
|
||||
|
||||
@@ -24,9 +24,9 @@ import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.session.SessionAutoConfiguration;
|
||||
import org.springframework.boot.http.autoconfigure.HttpMessageConvertersAutoConfiguration;
|
||||
import org.springframework.boot.security.autoconfigure.servlet.SecurityAutoConfiguration;
|
||||
import org.springframework.boot.session.autoconfigure.SessionAutoConfiguration;
|
||||
import org.springframework.boot.test.util.TestPropertyValues;
|
||||
import org.springframework.boot.web.server.WebServerFactoryCustomizerBeanPostProcessor;
|
||||
import org.springframework.boot.web.server.servlet.MockServletWebServer.RegisteredFilter;
|
||||
|
||||
@@ -2043,6 +2043,11 @@ bom {
|
||||
"spring-boot-security-oauth2-client",
|
||||
"spring-boot-security-oauth2-resource-server",
|
||||
"spring-boot-sendgrid",
|
||||
"spring-boot-session",
|
||||
"spring-boot-session-data-mongodb",
|
||||
"spring-boot-session-data-redis",
|
||||
"spring-boot-session-hazelcast",
|
||||
"spring-boot-session-jdbc",
|
||||
"spring-boot-starter",
|
||||
"spring-boot-starter-activemq",
|
||||
"spring-boot-starter-actuator",
|
||||
|
||||
@@ -118,6 +118,11 @@ dependencies {
|
||||
autoConfiguration(project(path: ":spring-boot-project:spring-boot-security-oauth2-resource-server", configuration: "autoConfigurationMetadata"))
|
||||
autoConfiguration(project(path: ":spring-boot-project:spring-boot-security-saml2", configuration: "autoConfigurationMetadata"))
|
||||
autoConfiguration(project(path: ":spring-boot-project:spring-boot-sendgrid", configuration: "autoConfigurationMetadata"))
|
||||
autoConfiguration(project(path: ":spring-boot-project:spring-boot-session", configuration: "autoConfigurationMetadata"))
|
||||
autoConfiguration(project(path: ":spring-boot-project:spring-boot-session-data-mongodb", configuration: "autoConfigurationMetadata"))
|
||||
autoConfiguration(project(path: ":spring-boot-project:spring-boot-session-data-redis", configuration: "autoConfigurationMetadata"))
|
||||
autoConfiguration(project(path: ":spring-boot-project:spring-boot-session-hazelcast", configuration: "autoConfigurationMetadata"))
|
||||
autoConfiguration(project(path: ":spring-boot-project:spring-boot-session-jdbc", configuration: "autoConfigurationMetadata"))
|
||||
autoConfiguration(project(path: ":spring-boot-project:spring-boot-testcontainers", configuration: "autoConfigurationMetadata"))
|
||||
autoConfiguration(project(path: ":spring-boot-project:spring-boot-thymeleaf", configuration: "autoConfigurationMetadata"))
|
||||
autoConfiguration(project(path: ":spring-boot-project:spring-boot-tomcat", configuration: "autoConfigurationMetadata"))
|
||||
@@ -188,6 +193,11 @@ dependencies {
|
||||
configurationProperties(project(path: ":spring-boot-project:spring-boot-security-oauth2-resource-server", configuration: "configurationPropertiesMetadata"))
|
||||
configurationProperties(project(path: ":spring-boot-project:spring-boot-security-saml2", configuration: "configurationPropertiesMetadata"))
|
||||
configurationProperties(project(path: ":spring-boot-project:spring-boot-sendgrid", configuration: "configurationPropertiesMetadata"))
|
||||
configurationProperties(project(path: ":spring-boot-project:spring-boot-session", configuration: "configurationPropertiesMetadata"))
|
||||
configurationProperties(project(path: ":spring-boot-project:spring-boot-session-data-mongodb", configuration: "configurationPropertiesMetadata"))
|
||||
configurationProperties(project(path: ":spring-boot-project:spring-boot-session-data-redis", configuration: "configurationPropertiesMetadata"))
|
||||
configurationProperties(project(path: ":spring-boot-project:spring-boot-session-hazelcast", configuration: "configurationPropertiesMetadata"))
|
||||
configurationProperties(project(path: ":spring-boot-project:spring-boot-session-jdbc", configuration: "configurationPropertiesMetadata"))
|
||||
configurationProperties(project(path: ":spring-boot-project:spring-boot-test-autoconfigure", configuration: "configurationPropertiesMetadata"))
|
||||
configurationProperties(project(path: ":spring-boot-project:spring-boot-testcontainers", configuration: "configurationPropertiesMetadata"))
|
||||
configurationProperties(project(path: ":spring-boot-project:spring-boot-thymeleaf", configuration: "configurationPropertiesMetadata"))
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
plugins {
|
||||
id "java-library"
|
||||
id "org.springframework.boot.auto-configuration"
|
||||
id "org.springframework.boot.configuration-properties"
|
||||
id "org.springframework.boot.deployed"
|
||||
id "org.springframework.boot.docker-test"
|
||||
id "org.springframework.boot.optional-dependencies"
|
||||
}
|
||||
|
||||
description = "Spring Boot Session Data MongoDB"
|
||||
|
||||
dependencies {
|
||||
api(project(":spring-boot-project:spring-boot"))
|
||||
api(project(":spring-boot-project:spring-boot-session"))
|
||||
api("org.springframework.session:spring-session-data-mongodb")
|
||||
|
||||
implementation(project(":spring-boot-project:spring-boot-data-mongodb"))
|
||||
|
||||
optional(project(":spring-boot-project:spring-boot-autoconfigure"))
|
||||
optional(project(":spring-boot-project:spring-boot-webflux"))
|
||||
|
||||
dockerTestImplementation(project(":spring-boot-project:spring-boot-test"))
|
||||
dockerTestImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support-docker"))
|
||||
dockerTestImplementation(testFixtures(project(":spring-boot-project:spring-boot")))
|
||||
dockerTestImplementation(testFixtures(project(":spring-boot-project:spring-boot-session")))
|
||||
dockerTestImplementation("org.mongodb:mongodb-driver-reactivestreams")
|
||||
dockerTestImplementation("org.mongodb:mongodb-driver-sync")
|
||||
dockerTestImplementation("org.testcontainers:junit-jupiter")
|
||||
dockerTestImplementation("org.testcontainers:mongodb")
|
||||
|
||||
dockerTestRuntimeOnly("ch.qos.logback:logback-classic")
|
||||
dockerTestRuntimeOnly("jakarta.servlet:jakarta.servlet-api")
|
||||
}
|
||||
@@ -14,22 +14,22 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.session;
|
||||
package org.springframework.boot.session.data.mongodb.autoconfigure;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.testcontainers.containers.MongoDBContainer;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.data.mongodb.autoconfigure.MongoDataAutoConfiguration;
|
||||
import org.springframework.boot.data.mongodb.autoconfigure.MongoReactiveDataAutoConfiguration;
|
||||
import org.springframework.boot.mongodb.autoconfigure.MongoAutoConfiguration;
|
||||
import org.springframework.boot.mongodb.autoconfigure.MongoReactiveAutoConfiguration;
|
||||
import org.springframework.boot.test.context.FilteredClassLoader;
|
||||
import org.springframework.boot.session.autoconfigure.AbstractReactiveSessionAutoConfigurationTests;
|
||||
import org.springframework.boot.session.autoconfigure.SessionAutoConfiguration;
|
||||
import org.springframework.boot.test.context.assertj.AssertableReactiveWebApplicationContext;
|
||||
import org.springframework.boot.test.context.runner.ContextConsumer;
|
||||
import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner;
|
||||
@@ -38,27 +38,27 @@ import org.springframework.boot.webflux.autoconfigure.WebSessionIdResolverAutoCo
|
||||
import org.springframework.http.ResponseCookie;
|
||||
import org.springframework.session.MapSession;
|
||||
import org.springframework.session.data.mongo.ReactiveMongoSessionRepository;
|
||||
import org.springframework.session.data.redis.ReactiveRedisSessionRepository;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Mongo-specific tests for {@link SessionAutoConfiguration}.
|
||||
* Tests for the reactive support of {@link MongoSessionAutoConfiguration}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @author Weix Sun
|
||||
*/
|
||||
@Testcontainers(disabledWithoutDocker = true)
|
||||
class ReactiveSessionAutoConfigurationMongoTests extends AbstractSessionAutoConfigurationTests {
|
||||
class MongoReactiveSessionAutoConfigurationTests extends AbstractReactiveSessionAutoConfigurationTests {
|
||||
|
||||
@Container
|
||||
static final MongoDBContainer mongoDb = TestImage.container(MongoDBContainer.class);
|
||||
|
||||
private final ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner()
|
||||
.withClassLoader(new FilteredClassLoader(ReactiveRedisSessionRepository.class))
|
||||
.withConfiguration(AutoConfigurations.of(SessionAutoConfiguration.class, MongoAutoConfiguration.class,
|
||||
MongoDataAutoConfiguration.class, MongoReactiveAutoConfiguration.class,
|
||||
MongoReactiveDataAutoConfiguration.class));
|
||||
@BeforeEach
|
||||
void prepareContextRunner() {
|
||||
this.contextRunner = new ReactiveWebApplicationContextRunner().withConfiguration(
|
||||
AutoConfigurations.of(SessionAutoConfiguration.class, MongoSessionAutoConfiguration.class,
|
||||
MongoReactiveAutoConfiguration.class, MongoReactiveDataAutoConfiguration.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void defaultConfig() {
|
||||
@@ -99,12 +99,8 @@ class ReactiveSessionAutoConfigurationMongoTests extends AbstractSessionAutoConf
|
||||
|
||||
@Test
|
||||
void sessionCookieConfigurationIsAppliedToAutoConfiguredWebSessionIdResolver() {
|
||||
AutoConfigurations autoConfigurations = AutoConfigurations.of(SessionAutoConfiguration.class,
|
||||
MongoAutoConfiguration.class, MongoDataAutoConfiguration.class, MongoReactiveAutoConfiguration.class,
|
||||
MongoReactiveDataAutoConfiguration.class, WebSessionIdResolverAutoConfiguration.class);
|
||||
new ReactiveWebApplicationContextRunner().withConfiguration(autoConfigurations)
|
||||
.withUserConfiguration(Config.class)
|
||||
.withClassLoader(new FilteredClassLoader(ReactiveRedisSessionRepository.class))
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(WebSessionIdResolverAutoConfiguration.class))
|
||||
.withUserConfiguration(ReactiveWebServerConfiguration.class)
|
||||
.withPropertyValues("server.reactive.session.cookie.name:JSESSIONID",
|
||||
"server.reactive.session.cookie.domain:.example.com",
|
||||
"server.reactive.session.cookie.path:/example", "server.reactive.session.cookie.max-age:60",
|
||||
@@ -14,10 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.session;
|
||||
package org.springframework.boot.session.data.mongodb.autoconfigure;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.testcontainers.containers.MongoDBContainer;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
@@ -27,7 +28,8 @@ import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.boot.data.mongodb.autoconfigure.MongoDataAutoConfiguration;
|
||||
import org.springframework.boot.mongodb.autoconfigure.MongoAutoConfiguration;
|
||||
import org.springframework.boot.test.context.FilteredClassLoader;
|
||||
import org.springframework.boot.session.autoconfigure.AbstractSessionAutoConfigurationTests;
|
||||
import org.springframework.boot.session.autoconfigure.SessionAutoConfiguration;
|
||||
import org.springframework.boot.test.context.assertj.AssertableWebApplicationContext;
|
||||
import org.springframework.boot.test.context.runner.ContextConsumer;
|
||||
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
|
||||
@@ -36,29 +38,27 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.session.config.SessionRepositoryCustomizer;
|
||||
import org.springframework.session.data.mongo.MongoIndexedSessionRepository;
|
||||
import org.springframework.session.data.redis.RedisIndexedSessionRepository;
|
||||
import org.springframework.session.hazelcast.HazelcastIndexedSessionRepository;
|
||||
import org.springframework.session.jdbc.JdbcIndexedSessionRepository;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Mongo-specific tests for {@link SessionAutoConfiguration}.
|
||||
* Tests for the servlet support of {@link MongoSessionAutoConfiguration}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@Testcontainers(disabledWithoutDocker = true)
|
||||
class SessionAutoConfigurationMongoTests extends AbstractSessionAutoConfigurationTests {
|
||||
class MongoSessionAutoConfigurationTests extends AbstractSessionAutoConfigurationTests {
|
||||
|
||||
@Container
|
||||
static final MongoDBContainer mongoDb = TestImage.container(MongoDBContainer.class);
|
||||
|
||||
private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
|
||||
.withClassLoader(new FilteredClassLoader(HazelcastIndexedSessionRepository.class,
|
||||
JdbcIndexedSessionRepository.class, RedisIndexedSessionRepository.class))
|
||||
.withConfiguration(AutoConfigurations.of(MongoAutoConfiguration.class, MongoDataAutoConfiguration.class,
|
||||
SessionAutoConfiguration.class))
|
||||
.withPropertyValues("spring.data.mongodb.uri=" + mongoDb.getReplicaSetUrl());
|
||||
@BeforeEach
|
||||
void prepareContextRunner() {
|
||||
this.contextRunner = new WebApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(MongoAutoConfiguration.class, MongoDataAutoConfiguration.class,
|
||||
SessionAutoConfiguration.class, MongoSessionAutoConfiguration.class))
|
||||
.withPropertyValues("spring.data.mongodb.uri=" + mongoDb.getReplicaSetUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
void defaultConfig() {
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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
|
||||
*
|
||||
* https://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.session.data.mongodb.autoconfigure;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.PropertyMapper;
|
||||
import org.springframework.boot.data.mongodb.autoconfigure.MongoDataAutoConfiguration;
|
||||
import org.springframework.boot.data.mongodb.autoconfigure.MongoReactiveDataAutoConfiguration;
|
||||
import org.springframework.boot.session.autoconfigure.SessionAutoConfiguration;
|
||||
import org.springframework.boot.session.autoconfigure.SessionProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.data.mongodb.core.MongoOperations;
|
||||
import org.springframework.data.mongodb.core.ReactiveMongoOperations;
|
||||
import org.springframework.session.ReactiveSessionRepository;
|
||||
import org.springframework.session.SessionRepository;
|
||||
import org.springframework.session.config.ReactiveSessionRepositoryCustomizer;
|
||||
import org.springframework.session.config.SessionRepositoryCustomizer;
|
||||
import org.springframework.session.data.mongo.MongoIndexedSessionRepository;
|
||||
import org.springframework.session.data.mongo.ReactiveMongoSessionRepository;
|
||||
import org.springframework.session.data.mongo.config.annotation.web.http.MongoHttpSessionConfiguration;
|
||||
import org.springframework.session.data.mongo.config.annotation.web.reactive.ReactiveMongoWebSessionConfiguration;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for Spring Session Data MongoDB.
|
||||
*
|
||||
* @author Eddú Meléndez
|
||||
* @author Stephane Nicoll
|
||||
* @author Vedran Pavic
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@AutoConfiguration(before = SessionAutoConfiguration.class,
|
||||
beforeName = { "org.springframework.boot.webflux.autoconfigure.HttpHandlerAutoConfiguration",
|
||||
"org.springframework.boot.webflux.autoconfigure.WebFluxAutoConfiguration" },
|
||||
after = { MongoDataAutoConfiguration.class, MongoReactiveDataAutoConfiguration.class },
|
||||
afterName = "org.springframework.boot.webflux.autoconfigure.WebSessionIdResolverAutoConfiguration")
|
||||
@EnableConfigurationProperties(MongoSessionProperties.class)
|
||||
public class MongoSessionAutoConfiguration {
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass({ MongoOperations.class, MongoIndexedSessionRepository.class })
|
||||
@ConditionalOnBean(MongoOperations.class)
|
||||
@ConditionalOnMissingBean(SessionRepository.class)
|
||||
@ConditionalOnWebApplication(type = Type.SERVLET)
|
||||
@Import(MongoHttpSessionConfiguration.class)
|
||||
class ServletMongoSessionConfiguration {
|
||||
|
||||
@Bean
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
SessionRepositoryCustomizer<MongoIndexedSessionRepository> springBootSessionRepositoryCustomizer(
|
||||
SessionProperties sessionProperties, MongoSessionProperties mongoSessionProperties,
|
||||
ServerProperties serverProperties) {
|
||||
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
|
||||
return (sessionRepository) -> {
|
||||
map.from(sessionProperties
|
||||
.determineTimeout(() -> serverProperties.getServlet().getSession().getTimeout()))
|
||||
.to(sessionRepository::setDefaultMaxInactiveInterval);
|
||||
map.from(mongoSessionProperties::getCollectionName).to(sessionRepository::setCollectionName);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass({ ReactiveMongoOperations.class, ReactiveMongoSessionRepository.class })
|
||||
@ConditionalOnMissingBean(ReactiveSessionRepository.class)
|
||||
@ConditionalOnBean(ReactiveMongoOperations.class)
|
||||
@Import(ReactiveMongoWebSessionConfiguration.class)
|
||||
class ReactiveMongoSessionConfiguration {
|
||||
|
||||
@Bean
|
||||
ReactiveSessionRepositoryCustomizer<ReactiveMongoSessionRepository> springBootSessionRepositoryCustomizer(
|
||||
SessionProperties sessionProperties, MongoSessionProperties mongoSessionProperties,
|
||||
ServerProperties serverProperties) {
|
||||
return (sessionRepository) -> {
|
||||
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
|
||||
map.from(sessionProperties
|
||||
.determineTimeout(() -> serverProperties.getReactive().getSession().getTimeout()))
|
||||
.to(sessionRepository::setDefaultMaxInactiveInterval);
|
||||
map.from(mongoSessionProperties::getCollectionName).to(sessionRepository::setCollectionName);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.session;
|
||||
package org.springframework.boot.session.data.mongodb.autoconfigure;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
@@ -22,7 +22,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
* Configuration properties for Mongo-backed Spring Session.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @since 2.0.0
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@ConfigurationProperties("spring.session.mongodb")
|
||||
public class MongoSessionProperties {
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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
|
||||
*
|
||||
* https://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 Data MongoDB.
|
||||
*/
|
||||
package org.springframework.boot.session.data.mongodb.autoconfigure;
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"groups": [],
|
||||
"properties": []
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
org.springframework.boot.session.data.mongodb.autoconfigure.MongoSessionAutoConfiguration
|
||||
@@ -0,0 +1,37 @@
|
||||
plugins {
|
||||
id "java-library"
|
||||
id "org.springframework.boot.auto-configuration"
|
||||
id "org.springframework.boot.configuration-properties"
|
||||
id "org.springframework.boot.deployed"
|
||||
id "org.springframework.boot.docker-test"
|
||||
id "org.springframework.boot.optional-dependencies"
|
||||
}
|
||||
|
||||
description = "Spring Boot Session Data Redis"
|
||||
|
||||
dependencies {
|
||||
api(project(":spring-boot-project:spring-boot"))
|
||||
api(project(":spring-boot-project:spring-boot-session"))
|
||||
api("org.springframework.session:spring-session-data-redis")
|
||||
|
||||
implementation(project(":spring-boot-project:spring-boot-data-redis"))
|
||||
|
||||
optional(project(":spring-boot-project:spring-boot-autoconfigure"))
|
||||
optional(project(":spring-boot-project:spring-boot-webflux"))
|
||||
|
||||
dockerTestImplementation(project(":spring-boot-project:spring-boot-test"))
|
||||
dockerTestImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support-docker"))
|
||||
dockerTestImplementation(testFixtures(project(":spring-boot-project:spring-boot")))
|
||||
dockerTestImplementation(testFixtures(project(":spring-boot-project:spring-boot-session")))
|
||||
dockerTestImplementation("com.redis:testcontainers-redis")
|
||||
dockerTestImplementation("org.testcontainers:junit-jupiter")
|
||||
|
||||
dockerTestRuntimeOnly("jakarta.servlet:jakarta.servlet-api")
|
||||
|
||||
testImplementation(project(":spring-boot-project:spring-boot-test"))
|
||||
testImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support"))
|
||||
testImplementation("jakarta.servlet:jakarta.servlet-api")
|
||||
testImplementation("org.springframework:spring-web")
|
||||
|
||||
testRuntimeOnly("ch.qos.logback:logback-classic")
|
||||
}
|
||||
@@ -14,13 +14,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.session;
|
||||
package org.springframework.boot.session.data.redis.autoconfigure;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.redis.testcontainers.RedisContainer;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
@@ -30,7 +31,8 @@ import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.boot.data.redis.autoconfigure.RedisAutoConfiguration;
|
||||
import org.springframework.boot.data.redis.autoconfigure.RedisReactiveAutoConfiguration;
|
||||
import org.springframework.boot.test.context.FilteredClassLoader;
|
||||
import org.springframework.boot.session.autoconfigure.AbstractReactiveSessionAutoConfigurationTests;
|
||||
import org.springframework.boot.session.autoconfigure.SessionAutoConfiguration;
|
||||
import org.springframework.boot.test.context.assertj.AssertableReactiveWebApplicationContext;
|
||||
import org.springframework.boot.test.context.runner.ContextConsumer;
|
||||
import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner;
|
||||
@@ -42,7 +44,6 @@ import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.http.ResponseCookie;
|
||||
import org.springframework.session.MapSession;
|
||||
import org.springframework.session.SaveMode;
|
||||
import org.springframework.session.data.mongo.ReactiveMongoSessionRepository;
|
||||
import org.springframework.session.data.redis.ReactiveRedisIndexedSessionRepository;
|
||||
import org.springframework.session.data.redis.ReactiveRedisSessionRepository;
|
||||
import org.springframework.session.data.redis.config.ConfigureReactiveRedisAction;
|
||||
@@ -52,7 +53,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.entry;
|
||||
|
||||
/**
|
||||
* Reactive Redis-specific tests for {@link SessionAutoConfiguration}.
|
||||
* Tests for the reactive support of {@link RedisSessionAutoConfiguration}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Andy Wilkinson
|
||||
@@ -60,30 +61,24 @@ import static org.assertj.core.api.Assertions.entry;
|
||||
* @author Weix Sun
|
||||
*/
|
||||
@Testcontainers(disabledWithoutDocker = true)
|
||||
class ReactiveSessionAutoConfigurationRedisTests extends AbstractSessionAutoConfigurationTests {
|
||||
class ReactiveRedisSessionAutoConfigurationTests extends AbstractReactiveSessionAutoConfigurationTests {
|
||||
|
||||
@Container
|
||||
public static RedisContainer redis = TestImage.container(RedisContainer.class);
|
||||
|
||||
protected final ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner()
|
||||
.withClassLoader(new FilteredClassLoader(ReactiveMongoSessionRepository.class))
|
||||
.withConfiguration(
|
||||
AutoConfigurations.of(SessionAutoConfiguration.class, WebSessionIdResolverAutoConfiguration.class,
|
||||
RedisAutoConfiguration.class, RedisReactiveAutoConfiguration.class));
|
||||
@BeforeEach
|
||||
void prepareRunner() {
|
||||
this.contextRunner = new ReactiveWebApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(SessionAutoConfiguration.class,
|
||||
WebSessionIdResolverAutoConfiguration.class, RedisSessionAutoConfiguration.class,
|
||||
RedisAutoConfiguration.class, RedisReactiveAutoConfiguration.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void defaultConfig() {
|
||||
this.contextRunner.run(validateSpringSessionUsesRedis("spring:session:", SaveMode.ON_SET_ATTRIBUTE));
|
||||
}
|
||||
|
||||
@Test
|
||||
void redisTakesPrecedenceMultipleImplementations() {
|
||||
ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner().withConfiguration(
|
||||
AutoConfigurations.of(SessionAutoConfiguration.class, WebSessionIdResolverAutoConfiguration.class,
|
||||
RedisAutoConfiguration.class, RedisReactiveAutoConfiguration.class));
|
||||
contextRunner.run(validateSpringSessionUsesRedis("spring:session:", SaveMode.ON_SET_ATTRIBUTE));
|
||||
}
|
||||
|
||||
@Test
|
||||
void defaultConfigWithCustomTimeout() {
|
||||
this.contextRunner.withPropertyValues("spring.session.timeout=1m").run((context) -> {
|
||||
@@ -111,7 +106,7 @@ class ReactiveSessionAutoConfigurationRedisTests extends AbstractSessionAutoConf
|
||||
|
||||
@Test
|
||||
void sessionCookieConfigurationIsAppliedToAutoConfiguredWebSessionIdResolver() {
|
||||
this.contextRunner.withUserConfiguration(Config.class)
|
||||
this.contextRunner.withUserConfiguration(ReactiveWebServerConfiguration.class)
|
||||
.withPropertyValues("spring.data.redis.host=" + redis.getHost(),
|
||||
"spring.data.redis.port=" + redis.getFirstMappedPort(),
|
||||
"server.reactive.session.cookie.name:JSESSIONID",
|
||||
@@ -136,13 +131,12 @@ class ReactiveSessionAutoConfigurationRedisTests extends AbstractSessionAutoConf
|
||||
this.contextRunner
|
||||
.withPropertyValues("spring.session.redis.repository-type=indexed",
|
||||
"spring.data.redis.host=" + redis.getHost(), "spring.data.redis.port=" + redis.getFirstMappedPort())
|
||||
.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
|
||||
.run(validateSpringSessionUsesIndexedRedis("spring:session:", SaveMode.ON_SET_ATTRIBUTE));
|
||||
}
|
||||
|
||||
@Test
|
||||
void indexedRedisSessionStoreWithCustomizations() {
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
|
||||
this.contextRunner
|
||||
.withPropertyValues("spring.session.redis.repository-type=indexed", "spring.session.redis.namespace=foo",
|
||||
"spring.session.redis.save-mode=on-get-attribute", "spring.data.redis.host=" + redis.getHost(),
|
||||
"spring.data.redis.port=" + redis.getFirstMappedPort())
|
||||
@@ -151,7 +145,7 @@ class ReactiveSessionAutoConfigurationRedisTests extends AbstractSessionAutoConf
|
||||
|
||||
@Test
|
||||
void indexedRedisSessionWithConfigureActionNone() {
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
|
||||
this.contextRunner
|
||||
.withPropertyValues("spring.session.redis.repository-type=indexed",
|
||||
"spring.session.redis.configure-action=none", "spring.data.redis.host=" + redis.getHost(),
|
||||
"spring.data.redis.port=" + redis.getFirstMappedPort())
|
||||
@@ -160,7 +154,7 @@ class ReactiveSessionAutoConfigurationRedisTests extends AbstractSessionAutoConf
|
||||
|
||||
@Test
|
||||
void indexedRedisSessionWithDefaultConfigureActionNone() {
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
|
||||
this.contextRunner
|
||||
.withPropertyValues("spring.session.redis.repository-type=indexed",
|
||||
"spring.data.redis.host=" + redis.getHost(), "spring.data.redis.port=" + redis.getFirstMappedPort())
|
||||
.run(validateStrategy(ConfigureNotifyKeyspaceEventsReactiveAction.class,
|
||||
@@ -169,8 +163,7 @@ class ReactiveSessionAutoConfigurationRedisTests extends AbstractSessionAutoConf
|
||||
|
||||
@Test
|
||||
void indexedRedisSessionWithCustomConfigureReactiveRedisActionBean() {
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
|
||||
.withUserConfiguration(MaxEntriesReactiveRedisAction.class)
|
||||
this.contextRunner.withUserConfiguration(MaxEntriesReactiveRedisAction.class)
|
||||
.withPropertyValues("spring.session.redis.repository-type=indexed",
|
||||
"spring.data.redis.host=" + redis.getHost(), "spring.data.redis.port=" + redis.getFirstMappedPort())
|
||||
.run(validateStrategy(MaxEntriesReactiveRedisAction.class, entry("set-max-intset-entries", "1024")));
|
||||
@@ -14,12 +14,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.session;
|
||||
package org.springframework.boot.session.data.redis.autoconfigure;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Map;
|
||||
|
||||
import com.redis.testcontainers.RedisContainer;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
@@ -28,7 +29,8 @@ import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.boot.context.properties.source.InvalidConfigurationPropertyValueException;
|
||||
import org.springframework.boot.data.redis.autoconfigure.RedisAutoConfiguration;
|
||||
import org.springframework.boot.test.context.FilteredClassLoader;
|
||||
import org.springframework.boot.session.autoconfigure.AbstractSessionAutoConfigurationTests;
|
||||
import org.springframework.boot.session.autoconfigure.SessionAutoConfiguration;
|
||||
import org.springframework.boot.test.context.assertj.AssertableWebApplicationContext;
|
||||
import org.springframework.boot.test.context.runner.ContextConsumer;
|
||||
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
|
||||
@@ -40,33 +42,31 @@ import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.session.FlushMode;
|
||||
import org.springframework.session.SaveMode;
|
||||
import org.springframework.session.config.SessionRepositoryCustomizer;
|
||||
import org.springframework.session.data.mongo.MongoIndexedSessionRepository;
|
||||
import org.springframework.session.data.redis.RedisIndexedSessionRepository;
|
||||
import org.springframework.session.data.redis.RedisSessionRepository;
|
||||
import org.springframework.session.data.redis.config.ConfigureNotifyKeyspaceEventsAction;
|
||||
import org.springframework.session.data.redis.config.ConfigureRedisAction;
|
||||
import org.springframework.session.hazelcast.HazelcastIndexedSessionRepository;
|
||||
import org.springframework.session.jdbc.JdbcIndexedSessionRepository;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.entry;
|
||||
|
||||
/**
|
||||
* Redis specific tests for {@link SessionAutoConfiguration}.
|
||||
* Tests for {@link RedisSessionAutoConfiguration}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
@Testcontainers(disabledWithoutDocker = true)
|
||||
class SessionAutoConfigurationRedisTests extends AbstractSessionAutoConfigurationTests {
|
||||
class RedisSessionAutoConfigurationTests extends AbstractSessionAutoConfigurationTests {
|
||||
|
||||
@Container
|
||||
public static RedisContainer redis = TestImage.container(RedisContainer.class);
|
||||
|
||||
protected final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
|
||||
.withClassLoader(new FilteredClassLoader(HazelcastIndexedSessionRepository.class,
|
||||
JdbcIndexedSessionRepository.class, MongoIndexedSessionRepository.class))
|
||||
.withConfiguration(AutoConfigurations.of(SessionAutoConfiguration.class));
|
||||
@BeforeEach
|
||||
void prepareContextRunner() {
|
||||
this.contextRunner = new WebApplicationContextRunner().withConfiguration(AutoConfigurations
|
||||
.of(SessionAutoConfiguration.class, RedisSessionAutoConfiguration.class, RedisAutoConfiguration.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void defaultConfig() {
|
||||
@@ -90,21 +90,11 @@ class SessionAutoConfigurationRedisTests extends AbstractSessionAutoConfiguratio
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void redisTakesPrecedenceMultipleImplementations() {
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
|
||||
.withPropertyValues("spring.data.redis.host=" + redis.getHost(),
|
||||
"spring.data.redis.port=" + redis.getFirstMappedPort())
|
||||
.run(validateSpringSessionUsesDefaultRedis("spring:session:", FlushMode.ON_SAVE,
|
||||
SaveMode.ON_SET_ATTRIBUTE));
|
||||
}
|
||||
|
||||
@Test
|
||||
void defaultConfigWithCustomTimeout() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("spring.data.redis.host=" + redis.getHost(),
|
||||
"spring.data.redis.port=" + redis.getFirstMappedPort(), "spring.session.timeout=1m")
|
||||
.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
|
||||
.run((context) -> {
|
||||
RedisSessionRepository repository = validateSessionRepository(context, RedisSessionRepository.class);
|
||||
assertThat(repository).hasFieldOrPropertyWithValue("defaultMaxInactiveInterval", Duration.ofMinutes(1));
|
||||
@@ -113,7 +103,7 @@ class SessionAutoConfigurationRedisTests extends AbstractSessionAutoConfiguratio
|
||||
|
||||
@Test
|
||||
void defaultRedisSessionStoreWithCustomizations() {
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
|
||||
this.contextRunner
|
||||
.withPropertyValues("spring.session.redis.namespace=foo", "spring.session.redis.flush-mode=immediate",
|
||||
"spring.session.redis.save-mode=on-get-attribute", "spring.data.redis.host=" + redis.getHost(),
|
||||
"spring.data.redis.port=" + redis.getFirstMappedPort())
|
||||
@@ -132,7 +122,7 @@ class SessionAutoConfigurationRedisTests extends AbstractSessionAutoConfiguratio
|
||||
|
||||
@Test
|
||||
void indexedRedisSessionStoreWithCustomizations() {
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
|
||||
this.contextRunner
|
||||
.withPropertyValues("spring.session.redis.repository-type=indexed", "spring.session.redis.namespace=foo",
|
||||
"spring.session.redis.flush-mode=immediate", "spring.session.redis.save-mode=on-get-attribute",
|
||||
"spring.session.redis.cleanup-cron=0 0 12 * * *", "spring.data.redis.host=" + redis.getHost(),
|
||||
@@ -143,7 +133,7 @@ class SessionAutoConfigurationRedisTests extends AbstractSessionAutoConfiguratio
|
||||
|
||||
@Test
|
||||
void indexedRedisSessionWithConfigureActionNone() {
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
|
||||
this.contextRunner
|
||||
.withPropertyValues("spring.session.redis.repository-type=indexed",
|
||||
"spring.session.redis.configure-action=none", "spring.data.redis.host=" + redis.getHost(),
|
||||
"spring.data.redis.port=" + redis.getFirstMappedPort())
|
||||
@@ -152,7 +142,7 @@ class SessionAutoConfigurationRedisTests extends AbstractSessionAutoConfiguratio
|
||||
|
||||
@Test
|
||||
void indexedRedisSessionWithDefaultConfigureActionNone() {
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
|
||||
this.contextRunner
|
||||
.withPropertyValues("spring.session.redis.repository-type=indexed",
|
||||
"spring.data.redis.host=" + redis.getHost(), "spring.data.redis.port=" + redis.getFirstMappedPort())
|
||||
.run(validateStrategy(ConfigureNotifyKeyspaceEventsAction.class, entry("notify-keyspace-events", "gxE")));
|
||||
@@ -160,8 +150,7 @@ class SessionAutoConfigurationRedisTests extends AbstractSessionAutoConfiguratio
|
||||
|
||||
@Test
|
||||
void indexedRedisSessionWithCustomConfigureRedisActionBean() {
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
|
||||
.withUserConfiguration(MaxEntriesRedisAction.class)
|
||||
this.contextRunner.withUserConfiguration(MaxEntriesRedisAction.class)
|
||||
.withPropertyValues("spring.session.redis.repository-type=indexed",
|
||||
"spring.data.redis.host=" + redis.getHost(), "spring.data.redis.port=" + redis.getFirstMappedPort())
|
||||
.run(validateStrategy(MaxEntriesRedisAction.class, entry("set-max-intset-entries", "1024")));
|
||||
@@ -170,8 +159,7 @@ class SessionAutoConfigurationRedisTests extends AbstractSessionAutoConfiguratio
|
||||
|
||||
@Test
|
||||
void whenTheUserDefinesTheirOwnSessionRepositoryCustomizerThenDefaultConfigurationIsOverwritten() {
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
|
||||
.withUserConfiguration(CustomizerConfiguration.class)
|
||||
this.contextRunner.withUserConfiguration(CustomizerConfiguration.class)
|
||||
.withPropertyValues("spring.session.redis.flush-mode=immediate",
|
||||
"spring.data.redis.host=" + redis.getHost(), "spring.data.redis.port=" + redis.getFirstMappedPort())
|
||||
.run((context) -> {
|
||||
@@ -182,8 +170,7 @@ class SessionAutoConfigurationRedisTests extends AbstractSessionAutoConfiguratio
|
||||
|
||||
@Test
|
||||
void whenIndexedAndTheUserDefinesTheirOwnSessionRepositoryCustomizerThenDefaultConfigurationIsOverwritten() {
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
|
||||
.withUserConfiguration(IndexedCustomizerConfiguration.class)
|
||||
this.contextRunner.withUserConfiguration(IndexedCustomizerConfiguration.class)
|
||||
.withPropertyValues("spring.session.redis.repository-type=indexed",
|
||||
"spring.session.redis.flush-mode=immediate", "spring.data.redis.host=" + redis.getHost(),
|
||||
"spring.data.redis.port=" + redis.getFirstMappedPort())
|
||||
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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
|
||||
*
|
||||
* https://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.session.data.redis.autoconfigure;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.PropertyMapper;
|
||||
import org.springframework.boot.context.properties.source.InvalidConfigurationPropertyValueException;
|
||||
import org.springframework.boot.data.redis.autoconfigure.RedisAutoConfiguration;
|
||||
import org.springframework.boot.data.redis.autoconfigure.RedisReactiveAutoConfiguration;
|
||||
import org.springframework.boot.session.autoconfigure.SessionAutoConfiguration;
|
||||
import org.springframework.boot.session.autoconfigure.SessionProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.session.ReactiveSessionRepository;
|
||||
import org.springframework.session.SessionRepository;
|
||||
import org.springframework.session.config.ReactiveSessionRepositoryCustomizer;
|
||||
import org.springframework.session.config.SessionRepositoryCustomizer;
|
||||
import org.springframework.session.data.redis.ReactiveRedisIndexedSessionRepository;
|
||||
import org.springframework.session.data.redis.ReactiveRedisSessionRepository;
|
||||
import org.springframework.session.data.redis.RedisIndexedSessionRepository;
|
||||
import org.springframework.session.data.redis.RedisSessionRepository;
|
||||
import org.springframework.session.data.redis.config.ConfigureNotifyKeyspaceEventsAction;
|
||||
import org.springframework.session.data.redis.config.ConfigureReactiveRedisAction;
|
||||
import org.springframework.session.data.redis.config.ConfigureRedisAction;
|
||||
import org.springframework.session.data.redis.config.annotation.ConfigureNotifyKeyspaceEventsReactiveAction;
|
||||
import org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration;
|
||||
import org.springframework.session.data.redis.config.annotation.web.http.RedisIndexedHttpSessionConfiguration;
|
||||
import org.springframework.session.data.redis.config.annotation.web.server.RedisIndexedWebSessionConfiguration;
|
||||
import org.springframework.session.data.redis.config.annotation.web.server.RedisWebSessionConfiguration;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for Spring Session Data Redis.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @author Tommy Ludwig
|
||||
* @author Eddú Meléndez
|
||||
* @author Stephane Nicoll
|
||||
* @author Vedran Pavic
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@AutoConfiguration(before = SessionAutoConfiguration.class,
|
||||
beforeName = { "org.springframework.boot.webflux.autoconfigure.HttpHandlerAutoConfiguration",
|
||||
"org.springframework.boot.webflux.autoconfigure.WebFluxAutoConfiguration" },
|
||||
after = { RedisAutoConfiguration.class, RedisReactiveAutoConfiguration.class },
|
||||
afterName = "org.springframework.boot.webflux.autoconfigure.WebSessionIdResolverAutoConfiguration")
|
||||
@EnableConfigurationProperties({ RedisSessionProperties.class, ServerProperties.class, SessionProperties.class })
|
||||
public class RedisSessionAutoConfiguration {
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass({ RedisTemplate.class, RedisIndexedSessionRepository.class })
|
||||
@ConditionalOnMissingBean(SessionRepository.class)
|
||||
@ConditionalOnBean(RedisConnectionFactory.class)
|
||||
@ConditionalOnWebApplication(type = Type.SERVLET)
|
||||
static class ServletRedisSessionConfiguration {
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnProperty(name = "spring.session.redis.repository-type", havingValue = "default",
|
||||
matchIfMissing = true)
|
||||
@Import(RedisHttpSessionConfiguration.class)
|
||||
static class DefaultRedisSessionConfiguration {
|
||||
|
||||
@Bean
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
SessionRepositoryCustomizer<RedisSessionRepository> springBootSessionRepositoryCustomizer(
|
||||
SessionProperties sessionProperties, RedisSessionProperties redisSessionProperties,
|
||||
ServerProperties serverProperties) {
|
||||
String cleanupCron = redisSessionProperties.getCleanupCron();
|
||||
if (cleanupCron != null) {
|
||||
throw new InvalidConfigurationPropertyValueException("spring.session.redis.cleanup-cron",
|
||||
cleanupCron, "Cron-based cleanup is only supported when "
|
||||
+ "spring.session.redis.repository-type is set to indexed.");
|
||||
}
|
||||
return (sessionRepository) -> {
|
||||
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
|
||||
map.from(sessionProperties
|
||||
.determineTimeout(() -> serverProperties.getServlet().getSession().getTimeout()))
|
||||
.to(sessionRepository::setDefaultMaxInactiveInterval);
|
||||
map.from(redisSessionProperties::getNamespace).to(sessionRepository::setRedisKeyNamespace);
|
||||
map.from(redisSessionProperties::getFlushMode).to(sessionRepository::setFlushMode);
|
||||
map.from(redisSessionProperties::getSaveMode).to(sessionRepository::setSaveMode);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnProperty(name = "spring.session.redis.repository-type", havingValue = "indexed")
|
||||
@Import(RedisIndexedHttpSessionConfiguration.class)
|
||||
static class IndexedRedisSessionConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
ConfigureRedisAction configureRedisAction(RedisSessionProperties redisSessionProperties) {
|
||||
return switch (redisSessionProperties.getConfigureAction()) {
|
||||
case NOTIFY_KEYSPACE_EVENTS -> new ConfigureNotifyKeyspaceEventsAction();
|
||||
case NONE -> ConfigureRedisAction.NO_OP;
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
SessionRepositoryCustomizer<RedisIndexedSessionRepository> springBootSessionRepositoryCustomizer(
|
||||
SessionProperties sessionProperties, RedisSessionProperties redisSessionProperties,
|
||||
ServerProperties serverProperties) {
|
||||
return (sessionRepository) -> {
|
||||
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
|
||||
map.from(sessionProperties
|
||||
.determineTimeout(() -> serverProperties.getServlet().getSession().getTimeout()))
|
||||
.to(sessionRepository::setDefaultMaxInactiveInterval);
|
||||
map.from(redisSessionProperties::getNamespace).to(sessionRepository::setRedisKeyNamespace);
|
||||
map.from(redisSessionProperties::getFlushMode).to(sessionRepository::setFlushMode);
|
||||
map.from(redisSessionProperties::getSaveMode).to(sessionRepository::setSaveMode);
|
||||
map.from(redisSessionProperties::getCleanupCron).to(sessionRepository::setCleanupCron);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ConditionalOnWebApplication(type = Type.REACTIVE)
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass({ ReactiveRedisConnectionFactory.class, ReactiveRedisSessionRepository.class })
|
||||
@ConditionalOnMissingBean(ReactiveSessionRepository.class)
|
||||
@ConditionalOnBean(ReactiveRedisConnectionFactory.class)
|
||||
class ReactiveRedisSessionConfiguration {
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnProperty(name = "spring.session.redis.repository-type", havingValue = "default",
|
||||
matchIfMissing = true)
|
||||
@Import(RedisWebSessionConfiguration.class)
|
||||
static class DefaultRedisSessionConfiguration {
|
||||
|
||||
@Bean
|
||||
ReactiveSessionRepositoryCustomizer<ReactiveRedisSessionRepository> springBootSessionRepositoryCustomizer(
|
||||
SessionProperties sessionProperties, RedisSessionProperties redisSessionProperties,
|
||||
ServerProperties serverProperties) {
|
||||
return (sessionRepository) -> {
|
||||
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
|
||||
map.from(sessionProperties
|
||||
.determineTimeout(() -> serverProperties.getReactive().getSession().getTimeout()))
|
||||
.to(sessionRepository::setDefaultMaxInactiveInterval);
|
||||
map.from(redisSessionProperties::getNamespace).to(sessionRepository::setRedisKeyNamespace);
|
||||
map.from(redisSessionProperties::getSaveMode).to(sessionRepository::setSaveMode);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnProperty(name = "spring.session.redis.repository-type", havingValue = "indexed")
|
||||
@Import(RedisIndexedWebSessionConfiguration.class)
|
||||
static class IndexedRedisSessionConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
ConfigureReactiveRedisAction configureReactiveRedisAction(RedisSessionProperties redisSessionProperties) {
|
||||
return switch (redisSessionProperties.getConfigureAction()) {
|
||||
case NOTIFY_KEYSPACE_EVENTS -> new ConfigureNotifyKeyspaceEventsReactiveAction();
|
||||
case NONE -> ConfigureReactiveRedisAction.NO_OP;
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
ReactiveSessionRepositoryCustomizer<ReactiveRedisIndexedSessionRepository> springBootSessionRepositoryCustomizer(
|
||||
SessionProperties sessionProperties, RedisSessionProperties redisSessionProperties,
|
||||
ServerProperties serverProperties) {
|
||||
return (sessionRepository) -> {
|
||||
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
|
||||
map.from(sessionProperties
|
||||
.determineTimeout(() -> serverProperties.getReactive().getSession().getTimeout()))
|
||||
.to(sessionRepository::setDefaultMaxInactiveInterval);
|
||||
map.from(redisSessionProperties::getNamespace).to(sessionRepository::setRedisKeyNamespace);
|
||||
map.from(redisSessionProperties::getSaveMode).to(sessionRepository::setSaveMode);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.session;
|
||||
package org.springframework.boot.session.data.redis.autoconfigure;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.session.FlushMode;
|
||||
@@ -24,7 +24,7 @@ import org.springframework.session.SaveMode;
|
||||
* Configuration properties for Redis backed Spring Session.
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
* @since 2.0.0
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@ConfigurationProperties("spring.session.redis")
|
||||
public class RedisSessionProperties {
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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
|
||||
*
|
||||
* https://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 Data Redis.
|
||||
*/
|
||||
package org.springframework.boot.session.data.redis.autoconfigure;
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"properties": [
|
||||
{
|
||||
"name": "spring.session.redis.cleanup-cron",
|
||||
"defaultValue": "0 * * * * *"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
org.springframework.boot.session.data.redis.autoconfigure.RedisSessionAutoConfiguration
|
||||
@@ -0,0 +1,27 @@
|
||||
plugins {
|
||||
id "java-library"
|
||||
id "org.springframework.boot.auto-configuration"
|
||||
id "org.springframework.boot.configuration-properties"
|
||||
id "org.springframework.boot.deployed"
|
||||
id "org.springframework.boot.optional-dependencies"
|
||||
}
|
||||
|
||||
description = "Spring Boot Session Hazelcast"
|
||||
|
||||
dependencies {
|
||||
api(project(":spring-boot-project:spring-boot"))
|
||||
api(project(":spring-boot-project:spring-boot-session"))
|
||||
api("org.springframework.session:spring-session-hazelcast")
|
||||
|
||||
implementation(project(":spring-boot-project:spring-boot-hazelcast"))
|
||||
|
||||
optional(project(":spring-boot-project:spring-boot-autoconfigure"))
|
||||
|
||||
testImplementation(project(":spring-boot-project:spring-boot-test"))
|
||||
testImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support"))
|
||||
testImplementation(testFixtures(project(":spring-boot-project:spring-boot-session")))
|
||||
testImplementation("jakarta.servlet:jakarta.servlet-api")
|
||||
testImplementation("org.springframework:spring-web")
|
||||
|
||||
testRuntimeOnly("ch.qos.logback:logback-classic")
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2023 the original author or authors.
|
||||
* Copyright 2012-2025 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.
|
||||
@@ -14,18 +14,23 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.session;
|
||||
package org.springframework.boot.session.hazelcast.autoconfigure;
|
||||
|
||||
import com.hazelcast.core.HazelcastInstance;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.PropertyMapper;
|
||||
import org.springframework.boot.session.autoconfigure.SessionAutoConfiguration;
|
||||
import org.springframework.boot.session.autoconfigure.SessionProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
@@ -35,20 +40,22 @@ import org.springframework.session.hazelcast.HazelcastIndexedSessionRepository;
|
||||
import org.springframework.session.hazelcast.config.annotation.web.http.HazelcastHttpSessionConfiguration;
|
||||
|
||||
/**
|
||||
* Hazelcast backed session configuration.
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for Spring Session Hazelcast.
|
||||
*
|
||||
* @author Tommy Ludwig
|
||||
* @author Eddú Meléndez
|
||||
* @author Stephane Nicoll
|
||||
* @author Vedran Pavic
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@AutoConfiguration(before = SessionAutoConfiguration.class)
|
||||
@ConditionalOnWebApplication(type = Type.SERVLET)
|
||||
@ConditionalOnClass(HazelcastIndexedSessionRepository.class)
|
||||
@ConditionalOnMissingBean(SessionRepository.class)
|
||||
@ConditionalOnBean(HazelcastInstance.class)
|
||||
@EnableConfigurationProperties(HazelcastSessionProperties.class)
|
||||
@EnableConfigurationProperties({ HazelcastSessionProperties.class, ServerProperties.class, SessionProperties.class })
|
||||
@Import(HazelcastHttpSessionConfiguration.class)
|
||||
class HazelcastSessionConfiguration {
|
||||
public class HazelcastSessionAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.session;
|
||||
package org.springframework.boot.session.hazelcast.autoconfigure;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.session.FlushMode;
|
||||
@@ -24,7 +24,7 @@ import org.springframework.session.SaveMode;
|
||||
* Configuration properties for Hazelcast backed Spring Session.
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
* @since 2.0.0
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@ConfigurationProperties("spring.session.hazelcast")
|
||||
public class HazelcastSessionProperties {
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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
|
||||
*
|
||||
* https://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 Hazelcast.
|
||||
*/
|
||||
package org.springframework.boot.session.hazelcast.autoconfigure;
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"groups": [],
|
||||
"properties": []
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
org.springframework.boot.session.hazelcast.autoconfigure.HazelcastSessionAutoConfiguration
|
||||
@@ -14,28 +14,26 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.session;
|
||||
package org.springframework.boot.session.hazelcast.autoconfigure;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import com.hazelcast.core.HazelcastInstance;
|
||||
import com.hazelcast.map.IMap;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.boot.test.context.FilteredClassLoader;
|
||||
import org.springframework.boot.test.context.assertj.AssertableWebApplicationContext;
|
||||
import org.springframework.boot.session.autoconfigure.AbstractSessionAutoConfigurationTests;
|
||||
import org.springframework.boot.session.autoconfigure.SessionAutoConfiguration;
|
||||
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.session.FlushMode;
|
||||
import org.springframework.session.SaveMode;
|
||||
import org.springframework.session.config.SessionRepositoryCustomizer;
|
||||
import org.springframework.session.data.mongo.MongoIndexedSessionRepository;
|
||||
import org.springframework.session.data.redis.RedisIndexedSessionRepository;
|
||||
import org.springframework.session.hazelcast.HazelcastIndexedSessionRepository;
|
||||
import org.springframework.session.jdbc.JdbcIndexedSessionRepository;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
@@ -43,29 +41,30 @@ import static org.mockito.BDDMockito.then;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Hazelcast specific tests for {@link SessionAutoConfiguration}.
|
||||
* Tests for {@link HazelcastSessionAutoConfiguration}.
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
class SessionAutoConfigurationHazelcastTests extends AbstractSessionAutoConfigurationTests {
|
||||
class HazelcastSessionAutoConfigurationTests extends AbstractSessionAutoConfigurationTests {
|
||||
|
||||
private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
|
||||
.withClassLoader(new FilteredClassLoader(JdbcIndexedSessionRepository.class,
|
||||
RedisIndexedSessionRepository.class, MongoIndexedSessionRepository.class))
|
||||
.withConfiguration(AutoConfigurations.of(SessionAutoConfiguration.class))
|
||||
.withUserConfiguration(HazelcastConfiguration.class);
|
||||
|
||||
@Test
|
||||
void defaultConfig() {
|
||||
this.contextRunner.run(this::validateDefaultConfig);
|
||||
@BeforeEach
|
||||
void prepareContextRunner() {
|
||||
this.contextRunner = new WebApplicationContextRunner()
|
||||
.withConfiguration(
|
||||
AutoConfigurations.of(SessionAutoConfiguration.class, HazelcastSessionAutoConfiguration.class))
|
||||
.withUserConfiguration(HazelcastConfiguration.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void hazelcastTakesPrecedenceOverMongo() {
|
||||
this.contextRunner
|
||||
.withClassLoader(
|
||||
new FilteredClassLoader(RedisIndexedSessionRepository.class, JdbcIndexedSessionRepository.class))
|
||||
.run(this::validateDefaultConfig);
|
||||
void defaultConfig() {
|
||||
this.contextRunner.run((context) -> {
|
||||
HazelcastIndexedSessionRepository repository = validateSessionRepository(context,
|
||||
HazelcastIndexedSessionRepository.class);
|
||||
assertThat(repository).hasFieldOrPropertyWithValue("defaultMaxInactiveInterval",
|
||||
new ServerProperties().getServlet().getSession().getTimeout());
|
||||
HazelcastInstance hazelcastInstance = context.getBean(HazelcastInstance.class);
|
||||
then(hazelcastInstance).should().getMap("spring:session:sessions");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -77,15 +76,6 @@ class SessionAutoConfigurationHazelcastTests extends AbstractSessionAutoConfigur
|
||||
});
|
||||
}
|
||||
|
||||
private void validateDefaultConfig(AssertableWebApplicationContext context) {
|
||||
HazelcastIndexedSessionRepository repository = validateSessionRepository(context,
|
||||
HazelcastIndexedSessionRepository.class);
|
||||
assertThat(repository).hasFieldOrPropertyWithValue("defaultMaxInactiveInterval",
|
||||
new ServerProperties().getServlet().getSession().getTimeout());
|
||||
HazelcastInstance hazelcastInstance = context.getBean(HazelcastInstance.class);
|
||||
then(hazelcastInstance).should().getMap("spring:session:sessions");
|
||||
}
|
||||
|
||||
@Test
|
||||
void customMapName() {
|
||||
this.contextRunner.withPropertyValues("spring.session.hazelcast.map-name=foo:bar:biz").run((context) -> {
|
||||
32
spring-boot-project/spring-boot-session-jdbc/build.gradle
Normal file
32
spring-boot-project/spring-boot-session-jdbc/build.gradle
Normal file
@@ -0,0 +1,32 @@
|
||||
plugins {
|
||||
id "java-library"
|
||||
id "org.springframework.boot.auto-configuration"
|
||||
id "org.springframework.boot.configuration-properties"
|
||||
id "org.springframework.boot.deployed"
|
||||
id "org.springframework.boot.optional-dependencies"
|
||||
}
|
||||
|
||||
description = "Spring Boot Session JDBC"
|
||||
|
||||
dependencies {
|
||||
api(project(":spring-boot-project:spring-boot"))
|
||||
api(project(":spring-boot-project:spring-boot-session"))
|
||||
api("org.springframework.session:spring-session-jdbc")
|
||||
|
||||
implementation(project(":spring-boot-project:spring-boot-jdbc"))
|
||||
|
||||
optional(project(":spring-boot-project:spring-boot-autoconfigure"))
|
||||
|
||||
testImplementation(project(":spring-boot-project:spring-boot-test"))
|
||||
testImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support"))
|
||||
testImplementation(project(":spring-boot-project:spring-boot-flyway"))
|
||||
testImplementation(project(":spring-boot-project:spring-boot-liquibase"))
|
||||
testImplementation(testFixtures(project(":spring-boot-project:spring-boot-session")))
|
||||
testImplementation("jakarta.servlet:jakarta.servlet-api")
|
||||
testImplementation("org.apache.commons:commons-dbcp2")
|
||||
testImplementation("org.springframework:spring-web")
|
||||
|
||||
testRuntimeOnly("ch.qos.logback:logback-classic")
|
||||
testRuntimeOnly("org.flywaydb:flyway-database-hsqldb")
|
||||
testRuntimeOnly("org.hsqldb:hsqldb")
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.session;
|
||||
package org.springframework.boot.session.jdbc.autoconfigure;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
* Copyright 2012-2025 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.
|
||||
@@ -14,22 +14,27 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.session;
|
||||
package org.springframework.boot.session.jdbc.autoconfigure;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
|
||||
import org.springframework.boot.autoconfigure.sql.init.OnDatabaseInitializationCondition;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.PropertyMapper;
|
||||
import org.springframework.boot.session.autoconfigure.SessionAutoConfiguration;
|
||||
import org.springframework.boot.session.autoconfigure.SessionProperties;
|
||||
import org.springframework.boot.sql.init.dependency.DatabaseInitializationDependencyConfigurer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
@@ -41,19 +46,21 @@ import org.springframework.session.jdbc.config.annotation.SpringSessionDataSourc
|
||||
import org.springframework.session.jdbc.config.annotation.web.http.JdbcHttpSessionConfiguration;
|
||||
|
||||
/**
|
||||
* JDBC backed session configuration.
|
||||
* {@link EnableAutoConfiguration Auto-configuraion} for Spring Session JDBC.
|
||||
*
|
||||
* @author Eddú Meléndez
|
||||
* @author Stephane Nicoll
|
||||
* @author Vedran Pavic
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@AutoConfiguration(before = SessionAutoConfiguration.class)
|
||||
@ConditionalOnWebApplication(type = Type.SERVLET)
|
||||
@ConditionalOnClass({ JdbcTemplate.class, JdbcIndexedSessionRepository.class })
|
||||
@ConditionalOnMissingBean(SessionRepository.class)
|
||||
@ConditionalOnBean(DataSource.class)
|
||||
@EnableConfigurationProperties(JdbcSessionProperties.class)
|
||||
@EnableConfigurationProperties({ JdbcSessionProperties.class, SessionProperties.class })
|
||||
@Import({ DatabaseInitializationDependencyConfigurer.class, JdbcHttpSessionConfiguration.class })
|
||||
class JdbcSessionConfiguration {
|
||||
public class JdbcSessionAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.session;
|
||||
package org.springframework.boot.session.jdbc.autoconfigure;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -34,7 +34,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Vedran Pavic
|
||||
* @author Andy Wilkinson
|
||||
* @author Phillip Webb
|
||||
* @since 2.6.0
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public class JdbcSessionDataSourceScriptDatabaseInitializer extends DataSourceScriptDatabaseInitializer {
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.session;
|
||||
package org.springframework.boot.session.jdbc.autoconfigure;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.sql.init.DatabaseInitializationMode;
|
||||
@@ -22,10 +22,10 @@ import org.springframework.session.FlushMode;
|
||||
import org.springframework.session.SaveMode;
|
||||
|
||||
/**
|
||||
* Configuration properties for JDBC backed Spring Session.
|
||||
* Configuration properties for JDBC-backed Spring Session.
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
* @since 2.0.0
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@ConfigurationProperties("spring.session.jdbc")
|
||||
public class JdbcSessionProperties {
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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
|
||||
*
|
||||
* https://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 JDBC.
|
||||
*/
|
||||
package org.springframework.boot.session.jdbc.autoconfigure;
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"groups": [],
|
||||
"properties": []
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
# Depends on Database Initialization Detectors
|
||||
org.springframework.boot.sql.init.dependency.DependsOnDatabaseInitializationDetector=\
|
||||
org.springframework.boot.autoconfigure.session.JdbcIndexedSessionRepositoryDependsOnDatabaseInitializationDetector
|
||||
org.springframework.boot.session.jdbc.autoconfigure.JdbcIndexedSessionRepositoryDependsOnDatabaseInitializationDetector
|
||||
@@ -0,0 +1 @@
|
||||
org.springframework.boot.session.jdbc.autoconfigure.JdbcSessionAutoConfiguration
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.session;
|
||||
package org.springframework.boot.session.jdbc.autoconfigure;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
@@ -33,13 +33,12 @@ import org.springframework.boot.jdbc.autoconfigure.DataSourceTransactionManagerA
|
||||
import org.springframework.boot.jdbc.autoconfigure.JdbcTemplateAutoConfiguration;
|
||||
import org.springframework.boot.jdbc.init.DataSourceScriptDatabaseInitializer;
|
||||
import org.springframework.boot.liquibase.autoconfigure.LiquibaseAutoConfiguration;
|
||||
import org.springframework.boot.session.autoconfigure.AbstractSessionAutoConfigurationTests;
|
||||
import org.springframework.boot.session.autoconfigure.SessionAutoConfiguration;
|
||||
import org.springframework.boot.sql.init.DatabaseInitializationMode;
|
||||
import org.springframework.boot.sql.init.DatabaseInitializationSettings;
|
||||
import org.springframework.boot.test.context.FilteredClassLoader;
|
||||
import org.springframework.boot.test.context.assertj.AssertableWebApplicationContext;
|
||||
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
|
||||
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||
import org.springframework.boot.web.servlet.AbstractFilterRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
@@ -47,9 +46,6 @@ import org.springframework.jdbc.BadSqlGrammarException;
|
||||
import org.springframework.jdbc.core.JdbcOperations;
|
||||
import org.springframework.session.FlushMode;
|
||||
import org.springframework.session.SaveMode;
|
||||
import org.springframework.session.data.mongo.MongoIndexedSessionRepository;
|
||||
import org.springframework.session.data.redis.RedisIndexedSessionRepository;
|
||||
import org.springframework.session.hazelcast.HazelcastIndexedSessionRepository;
|
||||
import org.springframework.session.jdbc.JdbcIndexedSessionRepository;
|
||||
import org.springframework.session.jdbc.PostgreSqlJdbcIndexedSessionRepositoryCustomizer;
|
||||
import org.springframework.session.jdbc.config.annotation.SpringSessionDataSource;
|
||||
@@ -58,55 +54,34 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
/**
|
||||
* JDBC specific tests for {@link SessionAutoConfiguration}.
|
||||
* Tests for {@link JdbcSessionAutoConfiguration}.
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
class SessionAutoConfigurationJdbcTests extends AbstractSessionAutoConfigurationTests {
|
||||
|
||||
private WebApplicationContextRunner contextRunner;
|
||||
class JdbcSessionAutoConfigurationTests extends AbstractSessionAutoConfigurationTests {
|
||||
|
||||
@BeforeEach
|
||||
void prepareRunner() {
|
||||
this.contextRunner = new WebApplicationContextRunner()
|
||||
.withClassLoader(new FilteredClassLoader(Thread.currentThread().getContextClassLoader(),
|
||||
HazelcastIndexedSessionRepository.class, MongoIndexedSessionRepository.class,
|
||||
RedisIndexedSessionRepository.class))
|
||||
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class,
|
||||
DataSourceTransactionManagerAutoConfiguration.class, JdbcTemplateAutoConfiguration.class,
|
||||
SessionAutoConfiguration.class))
|
||||
SessionAutoConfiguration.class, JdbcSessionAutoConfiguration.class))
|
||||
.withPropertyValues("spring.datasource.generate-unique-name=true");
|
||||
}
|
||||
|
||||
@Test
|
||||
void defaultConfig() {
|
||||
this.contextRunner.run(this::validateDefaultConfig);
|
||||
}
|
||||
|
||||
@Test
|
||||
void jdbcTakesPrecedenceOverMongoAndHazelcast() {
|
||||
this.contextRunner.withClassLoader(new FilteredClassLoader(RedisIndexedSessionRepository.class))
|
||||
.run(this::validateDefaultConfig);
|
||||
}
|
||||
|
||||
private void validateDefaultConfig(AssertableWebApplicationContext context) {
|
||||
JdbcIndexedSessionRepository repository = validateSessionRepository(context,
|
||||
JdbcIndexedSessionRepository.class);
|
||||
assertThat(repository).hasFieldOrPropertyWithValue("defaultMaxInactiveInterval",
|
||||
new ServerProperties().getServlet().getSession().getTimeout());
|
||||
assertThat(repository).hasFieldOrPropertyWithValue("tableName", "SPRING_SESSION");
|
||||
assertThat(repository).hasFieldOrPropertyWithValue("cleanupCron", "0 * * * * *");
|
||||
assertThat(context.getBean(JdbcSessionProperties.class).getInitializeSchema())
|
||||
.isEqualTo(DatabaseInitializationMode.EMBEDDED);
|
||||
assertThat(context.getBean(JdbcOperations.class).queryForList("select * from SPRING_SESSION")).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void filterOrderCanBeCustomized() {
|
||||
this.contextRunner.withPropertyValues("spring.session.servlet.filter-order=123").run((context) -> {
|
||||
AbstractFilterRegistrationBean<?> registration = context.getBean(AbstractFilterRegistrationBean.class);
|
||||
assertThat(registration.getOrder()).isEqualTo(123);
|
||||
this.contextRunner.run((context) -> {
|
||||
JdbcIndexedSessionRepository repository = validateSessionRepository(context,
|
||||
JdbcIndexedSessionRepository.class);
|
||||
assertThat(repository).hasFieldOrPropertyWithValue("defaultMaxInactiveInterval",
|
||||
new ServerProperties().getServlet().getSession().getTimeout());
|
||||
assertThat(repository).hasFieldOrPropertyWithValue("tableName", "SPRING_SESSION");
|
||||
assertThat(repository).hasFieldOrPropertyWithValue("cleanupCron", "0 * * * * *");
|
||||
assertThat(context.getBean(JdbcSessionProperties.class).getInitializeSchema())
|
||||
.isEqualTo(DatabaseInitializationMode.EMBEDDED);
|
||||
assertThat(context.getBean(JdbcOperations.class).queryForList("select * from SPRING_SESSION")).isEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -136,7 +111,7 @@ class SessionAutoConfigurationJdbcTests extends AbstractSessionAutoConfiguration
|
||||
@Test
|
||||
void customTableName() {
|
||||
this.contextRunner.withPropertyValues("spring.session.jdbc.table-name=FOO_BAR",
|
||||
"spring.session.jdbc.schema=classpath:org/springframework/boot/autoconfigure/session/custom-schema-h2.sql")
|
||||
"spring.session.jdbc.schema=classpath:org/springframework/boot/session/jdbc/autoconfigure/custom-schema-h2.sql")
|
||||
.run((context) -> {
|
||||
JdbcIndexedSessionRepository repository = validateSessionRepository(context,
|
||||
JdbcIndexedSessionRepository.class);
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.session;
|
||||
package org.springframework.boot.session.jdbc.autoconfigure;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
32
spring-boot-project/spring-boot-session/build.gradle
Normal file
32
spring-boot-project/spring-boot-session/build.gradle
Normal file
@@ -0,0 +1,32 @@
|
||||
plugins {
|
||||
id "java-library"
|
||||
id "java-test-fixtures"
|
||||
id "org.springframework.boot.auto-configuration"
|
||||
id "org.springframework.boot.configuration-properties"
|
||||
id "org.springframework.boot.deployed"
|
||||
id "org.springframework.boot.optional-dependencies"
|
||||
}
|
||||
|
||||
description = "Spring Boot Session"
|
||||
|
||||
dependencies {
|
||||
api(project(":spring-boot-project:spring-boot"))
|
||||
api("org.springframework.session:spring-session-core")
|
||||
|
||||
optional(project(":spring-boot-project:spring-boot-autoconfigure"))
|
||||
optional("jakarta.servlet:jakarta.servlet-api")
|
||||
optional("org.springframework.security:spring-security-web")
|
||||
|
||||
testFixturesImplementation(project(":spring-boot-project:spring-boot-test"))
|
||||
testFixturesImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support"))
|
||||
testFixturesImplementation(testFixtures(project(":spring-boot-project:spring-boot")))
|
||||
testFixturesImplementation("io.projectreactor:reactor-core")
|
||||
|
||||
testImplementation(project(":spring-boot-project:spring-boot-test"))
|
||||
testImplementation(project(":spring-boot-project:spring-boot-tomcat"))
|
||||
testImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support"))
|
||||
testImplementation(project(":spring-boot-project:spring-boot-webflux"))
|
||||
testImplementation(testFixtures(project(":spring-boot-project:spring-boot")))
|
||||
|
||||
testRuntimeOnly("ch.qos.logback:logback-classic")
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.session;
|
||||
package org.springframework.boot.session.autoconfigure;
|
||||
|
||||
import org.springframework.session.web.http.DefaultCookieSerializer;
|
||||
|
||||
@@ -23,7 +23,7 @@ import org.springframework.session.web.http.DefaultCookieSerializer;
|
||||
* {@link DefaultCookieSerializer} configuration.
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
* @since 2.3.0
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface DefaultCookieSerializerCustomizer {
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.session;
|
||||
package org.springframework.boot.session.autoconfigure;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
@@ -37,9 +37,7 @@ import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.security.web.authentication.RememberMeServices;
|
||||
import org.springframework.session.ReactiveSessionRepository;
|
||||
import org.springframework.session.Session;
|
||||
import org.springframework.session.SessionRepository;
|
||||
import org.springframework.session.security.web.authentication.SpringSessionRememberMeServices;
|
||||
import org.springframework.session.web.http.CookieHttpSessionIdResolver;
|
||||
import org.springframework.session.web.http.CookieSerializer;
|
||||
@@ -55,19 +53,9 @@ import org.springframework.session.web.http.HttpSessionIdResolver;
|
||||
* @author Stephane Nicoll
|
||||
* @author Vedran Pavic
|
||||
* @author Weix Sun
|
||||
* @since 1.4.0
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@AutoConfiguration(
|
||||
beforeName = { "org.springframework.boot.webflux.autoconfigure.HttpHandlerAutoConfiguration",
|
||||
"org.springframework.boot.webflux.autoconfigure.WebFluxAutoConfiguration" },
|
||||
afterName = { "org.springframework.boot.hazelcast.autoconfigure.HazelcastAutoConfiguration",
|
||||
"org.springframework.boot.jdbc.autoconfigure.DataSourceAutoConfiguration",
|
||||
"org.springframework.boot.jdbc.autoconfigure.JdbcTemplateAutoConfiguration",
|
||||
"org.springframework.boot.data.mongodb.autoconfigure.MongoDataAutoConfiguration",
|
||||
"org.springframework.boot.data.mongodb.autoconfigure.MongoReactiveDataAutoConfiguration",
|
||||
"org.springframework.boot.data.redis.autoconfigure.RedisAutoConfiguration",
|
||||
"org.springframework.boot.data.redis.autoconfigure.RedisReactiveAutoConfiguration",
|
||||
"org.springframework.boot.autoconfigure.session.WebSessionIdResolverAutoConfiguration" })
|
||||
@AutoConfiguration
|
||||
@ConditionalOnClass(Session.class)
|
||||
@ConditionalOnWebApplication
|
||||
@EnableConfigurationProperties({ ServerProperties.class, SessionProperties.class })
|
||||
@@ -109,22 +97,6 @@ public class SessionAutoConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnMissingBean(SessionRepository.class)
|
||||
@Import({ RedisSessionConfiguration.class, JdbcSessionConfiguration.class, HazelcastSessionConfiguration.class,
|
||||
MongoSessionConfiguration.class })
|
||||
static class ServletSessionRepositoryConfiguration {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnWebApplication(type = Type.REACTIVE)
|
||||
@ConditionalOnMissingBean(ReactiveSessionRepository.class)
|
||||
@Import({ RedisReactiveSessionConfiguration.class, MongoReactiveSessionConfiguration.class })
|
||||
static class ReactiveSessionConfiguration {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.session;
|
||||
package org.springframework.boot.session.autoconfigure;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
@@ -34,7 +34,7 @@ import org.springframework.session.web.http.SessionRepositoryFilter;
|
||||
* @author Tommy Ludwig
|
||||
* @author Stephane Nicoll
|
||||
* @author Vedran Pavic
|
||||
* @since 1.4.0
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@ConfigurationProperties("spring.session")
|
||||
public class SessionProperties {
|
||||
@@ -68,7 +68,6 @@ public class SessionProperties {
|
||||
* {@code fallbackTimeout} is used.
|
||||
* @param fallbackTimeout a fallback timeout value if the timeout isn't configured
|
||||
* @return the session timeout
|
||||
* @since 2.4.0
|
||||
*/
|
||||
public Duration determineTimeout(Supplier<Duration> fallbackTimeout) {
|
||||
return (this.timeout != null) ? this.timeout : fallbackTimeout.get();
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.session;
|
||||
package org.springframework.boot.session.autoconfigure;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -17,4 +17,4 @@
|
||||
/**
|
||||
* Auto-configuration for Spring Session.
|
||||
*/
|
||||
package org.springframework.boot.autoconfigure.session;
|
||||
package org.springframework.boot.session.autoconfigure;
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"properties": [
|
||||
{
|
||||
"name": "spring.session.servlet.filter-dispatcher-types",
|
||||
"defaultValue": [
|
||||
"async",
|
||||
"error",
|
||||
"request"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
org.springframework.boot.session.autoconfigure.SessionAutoConfiguration
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.session;
|
||||
package org.springframework.boot.session.autoconfigure;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.session;
|
||||
package org.springframework.boot.session.autoconfigure;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
@@ -26,22 +26,13 @@ import org.mockito.InOrder;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.test.context.FilteredClassLoader;
|
||||
import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner;
|
||||
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
|
||||
import org.springframework.boot.web.servlet.AbstractFilterRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.session.MapSessionRepository;
|
||||
import org.springframework.session.ReactiveMapSessionRepository;
|
||||
import org.springframework.session.SessionRepository;
|
||||
import org.springframework.session.config.annotation.web.http.EnableSpringHttpSession;
|
||||
import org.springframework.session.config.annotation.web.server.EnableSpringWebSession;
|
||||
import org.springframework.session.data.mongo.MongoIndexedSessionRepository;
|
||||
import org.springframework.session.data.redis.RedisIndexedSessionRepository;
|
||||
import org.springframework.session.hazelcast.HazelcastIndexedSessionRepository;
|
||||
import org.springframework.session.jdbc.JdbcIndexedSessionRepository;
|
||||
import org.springframework.session.security.web.authentication.SpringSessionRememberMeServices;
|
||||
import org.springframework.session.web.http.CookieHttpSessionIdResolver;
|
||||
import org.springframework.session.web.http.DefaultCookieSerializer;
|
||||
@@ -63,39 +54,11 @@ import static org.mockito.Mockito.mock;
|
||||
* @author Stephane Nicoll
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
class SessionAutoConfigurationTests extends AbstractSessionAutoConfigurationTests {
|
||||
class SessionAutoConfigurationTests {
|
||||
|
||||
private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(SessionAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void autoConfigurationDisabledIfNoImplementationMatches() {
|
||||
this.contextRunner
|
||||
.withClassLoader(new FilteredClassLoader(RedisIndexedSessionRepository.class,
|
||||
HazelcastIndexedSessionRepository.class, JdbcIndexedSessionRepository.class,
|
||||
MongoIndexedSessionRepository.class))
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(SessionRepository.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void backOffIfSessionRepositoryIsPresent() {
|
||||
this.contextRunner.withUserConfiguration(SessionRepositoryConfiguration.class).run((context) -> {
|
||||
MapSessionRepository repository = validateSessionRepository(context, MapSessionRepository.class);
|
||||
assertThat(context).getBean("mySessionRepository").isSameAs(repository);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void backOffIfReactiveSessionRepositoryIsPresent() {
|
||||
ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(SessionAutoConfiguration.class));
|
||||
contextRunner.withUserConfiguration(ReactiveSessionRepositoryConfiguration.class).run((context) -> {
|
||||
ReactiveMapSessionRepository repository = validateSessionRepository(context,
|
||||
ReactiveMapSessionRepository.class);
|
||||
assertThat(context).getBean("mySessionRepository").isSameAs(repository);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void filterIsRegisteredWithAsyncErrorAndRequestDispatcherTypes() {
|
||||
this.contextRunner.withUserConfiguration(SessionRepositoryConfiguration.class).run((context) -> {
|
||||
@@ -247,17 +210,6 @@ class SessionAutoConfigurationTests extends AbstractSessionAutoConfigurationTest
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableSpringWebSession
|
||||
static class ReactiveSessionRepositoryConfiguration {
|
||||
|
||||
@Bean
|
||||
ReactiveMapSessionRepository mySessionRepository() {
|
||||
return new ReactiveMapSessionRepository(Collections.emptyMap());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableConfigurationProperties(ServerProperties.class)
|
||||
static class ServerPropertiesConfiguration {
|
||||
|
||||
@@ -14,13 +14,19 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.session;
|
||||
package org.springframework.boot.session.autoconfigure;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
|
||||
import org.springframework.boot.testsupport.classpath.ClassPathExclusions;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.session.MapSessionRepository;
|
||||
import org.springframework.session.config.annotation.web.http.EnableSpringHttpSession;
|
||||
import org.springframework.session.web.http.DefaultCookieSerializer;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -32,7 +38,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
@ClassPathExclusions("spring-security-*")
|
||||
class SessionAutoConfigurationWithoutSecurityTests extends AbstractSessionAutoConfigurationTests {
|
||||
class SessionAutoConfigurationWithoutSecurityTests {
|
||||
|
||||
private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(SessionAutoConfiguration.class));
|
||||
@@ -45,4 +51,15 @@ class SessionAutoConfigurationWithoutSecurityTests extends AbstractSessionAutoCo
|
||||
});
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableSpringHttpSession
|
||||
static class SessionRepositoryConfiguration {
|
||||
|
||||
@Bean
|
||||
MapSessionRepository mySessionRepository() {
|
||||
return new MapSessionRepository(Collections.emptyMap());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.session;
|
||||
package org.springframework.boot.session.autoconfigure;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.function.Supplier;
|
||||
@@ -14,40 +14,51 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.session;
|
||||
package org.springframework.boot.session.autoconfigure;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.test.context.assertj.AssertableReactiveWebApplicationContext;
|
||||
import org.springframework.boot.test.context.assertj.AssertableWebApplicationContext;
|
||||
import org.springframework.boot.test.context.runner.ContextConsumer;
|
||||
import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner;
|
||||
import org.springframework.boot.web.reactive.context.ReactiveWebApplicationContext;
|
||||
import org.springframework.boot.web.server.reactive.MockReactiveWebServerFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
|
||||
import org.springframework.mock.web.server.MockServerWebExchange;
|
||||
import org.springframework.session.MapSessionRepository;
|
||||
import org.springframework.session.ReactiveMapSessionRepository;
|
||||
import org.springframework.session.ReactiveSessionRepository;
|
||||
import org.springframework.session.SessionRepository;
|
||||
import org.springframework.session.config.annotation.web.http.EnableSpringHttpSession;
|
||||
import org.springframework.session.web.http.SessionRepositoryFilter;
|
||||
import org.springframework.session.config.annotation.web.server.EnableSpringWebSession;
|
||||
import org.springframework.web.server.WebSession;
|
||||
import org.springframework.web.server.session.WebSessionManager;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Shared test utilities for {@link SessionAutoConfiguration} tests.
|
||||
* Base class for Spring Session auto-configuration tests when the backing store is
|
||||
* reactive.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Weix Sun
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public abstract class AbstractSessionAutoConfigurationTests {
|
||||
public abstract class AbstractReactiveSessionAutoConfigurationTests {
|
||||
|
||||
private static final MockReactiveWebServerFactory mockReactiveWebServerFactory = new MockReactiveWebServerFactory();
|
||||
|
||||
protected ReactiveWebApplicationContextRunner contextRunner;
|
||||
|
||||
@Test
|
||||
void backOffIfReactiveSessionRepositoryIsPresent() {
|
||||
this.contextRunner.withUserConfiguration(ReactiveSessionRepositoryConfiguration.class).run((context) -> {
|
||||
ReactiveMapSessionRepository repository = validateSessionRepository(context,
|
||||
ReactiveMapSessionRepository.class);
|
||||
assertThat(context).getBean("mySessionRepository").isSameAs(repository);
|
||||
});
|
||||
}
|
||||
|
||||
protected ContextConsumer<ReactiveWebApplicationContext> assertExchangeWithSession(
|
||||
Consumer<MockServerWebExchange> exchange) {
|
||||
return (context) -> {
|
||||
@@ -61,15 +72,6 @@ public abstract class AbstractSessionAutoConfigurationTests {
|
||||
};
|
||||
}
|
||||
|
||||
protected <T extends SessionRepository<?>> T validateSessionRepository(AssertableWebApplicationContext context,
|
||||
Class<T> type) {
|
||||
assertThat(context).hasSingleBean(SessionRepositoryFilter.class);
|
||||
assertThat(context).hasSingleBean(SessionRepository.class);
|
||||
SessionRepository<?> repository = context.getBean(SessionRepository.class);
|
||||
assertThat(repository).as("Wrong session repository type").isInstanceOf(type);
|
||||
return type.cast(repository);
|
||||
}
|
||||
|
||||
protected <T extends ReactiveSessionRepository<?>> T validateSessionRepository(
|
||||
AssertableReactiveWebApplicationContext context, Class<T> type) {
|
||||
assertThat(context).hasSingleBean(WebSessionManager.class);
|
||||
@@ -79,19 +81,8 @@ public abstract class AbstractSessionAutoConfigurationTests {
|
||||
return type.cast(repository);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableSpringHttpSession
|
||||
static class SessionRepositoryConfiguration {
|
||||
|
||||
@Bean
|
||||
MapSessionRepository mySessionRepository() {
|
||||
return new MapSessionRepository(Collections.emptyMap());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class Config {
|
||||
protected static class ReactiveWebServerConfiguration {
|
||||
|
||||
@Bean
|
||||
MockReactiveWebServerFactory mockReactiveWebServerFactory() {
|
||||
@@ -100,4 +91,15 @@ public abstract class AbstractSessionAutoConfigurationTests {
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableSpringWebSession
|
||||
static class ReactiveSessionRepositoryConfiguration {
|
||||
|
||||
@Bean
|
||||
ReactiveMapSessionRepository mySessionRepository() {
|
||||
return new ReactiveMapSessionRepository(Collections.emptyMap());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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
|
||||
*
|
||||
* https://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.session.autoconfigure;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.test.context.assertj.AssertableWebApplicationContext;
|
||||
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.session.MapSessionRepository;
|
||||
import org.springframework.session.SessionRepository;
|
||||
import org.springframework.session.config.annotation.web.http.EnableSpringHttpSession;
|
||||
import org.springframework.session.web.http.SessionRepositoryFilter;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Base class for Spring Session auto-configuration tests when the backing store cannot be
|
||||
* reactive.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Weix Sun
|
||||
* @see AbstractReactiveSessionAutoConfigurationTests
|
||||
*/
|
||||
public abstract class AbstractSessionAutoConfigurationTests {
|
||||
|
||||
protected WebApplicationContextRunner contextRunner;
|
||||
|
||||
@Test
|
||||
void backOffIfSessionRepositoryIsPresent() {
|
||||
this.contextRunner.withUserConfiguration(SessionRepositoryConfiguration.class).run((context) -> {
|
||||
MapSessionRepository repository = validateSessionRepository(context, MapSessionRepository.class);
|
||||
assertThat(context).getBean("mySessionRepository").isSameAs(repository);
|
||||
});
|
||||
}
|
||||
|
||||
protected <T extends SessionRepository<?>> T validateSessionRepository(AssertableWebApplicationContext context,
|
||||
Class<T> type) {
|
||||
assertThat(context).hasSingleBean(SessionRepositoryFilter.class);
|
||||
assertThat(context).hasSingleBean(SessionRepository.class);
|
||||
SessionRepository<?> repository = context.getBean(SessionRepository.class);
|
||||
assertThat(repository).as("Wrong session repository type").isInstanceOf(type);
|
||||
return type.cast(repository);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableSpringHttpSession
|
||||
static class SessionRepositoryConfiguration {
|
||||
|
||||
@Bean
|
||||
MapSessionRepository mySessionRepository() {
|
||||
return new MapSessionRepository(Collections.emptyMap());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,13 +5,10 @@ plugins {
|
||||
description = "Spring Boot Session smoke test"
|
||||
|
||||
dependencies {
|
||||
implementation(project(":spring-boot-project:spring-boot-hazelcast"))
|
||||
implementation(project(":spring-boot-project:spring-boot-session-hazelcast"))
|
||||
implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-actuator"))
|
||||
implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-security"))
|
||||
implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-web"))
|
||||
implementation("org.springframework.session:spring-session-hazelcast") {
|
||||
exclude group: "javax.annotation", module: "javax.annotation-api"
|
||||
}
|
||||
|
||||
testImplementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-test"))
|
||||
}
|
||||
|
||||
@@ -5,11 +5,11 @@ plugins {
|
||||
description = "Spring Boot Session JDBC smoke test"
|
||||
|
||||
dependencies {
|
||||
implementation(project(":spring-boot-project:spring-boot-session-jdbc"))
|
||||
implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-actuator"))
|
||||
implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-security"))
|
||||
implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-web"))
|
||||
runtimeOnly(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-jdbc"))
|
||||
runtimeOnly("org.springframework.session:spring-session-jdbc")
|
||||
runtimeOnly("com.h2database:h2")
|
||||
|
||||
testImplementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-test"))
|
||||
|
||||
@@ -53,7 +53,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author Madhura Bhave
|
||||
*/
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
properties = { "server.servlet.session.timeout:2" })
|
||||
properties = { "server.servlet.session.timeout:2", "debug=true" })
|
||||
class SampleSessionJdbcApplicationTests {
|
||||
|
||||
private static final ClientHttpRequestFactorySettings DONT_FOLLOW_REDIRECTS = ClientHttpRequestFactorySettings
|
||||
|
||||
@@ -12,9 +12,9 @@ dependencies {
|
||||
dockerTestImplementation("org.testcontainers:junit-jupiter")
|
||||
dockerTestImplementation("org.testcontainers:mongodb")
|
||||
|
||||
implementation(project(":spring-boot-project:spring-boot-session-data-mongodb"))
|
||||
implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-actuator"))
|
||||
implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-data-mongodb"))
|
||||
implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-security"))
|
||||
implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-web"))
|
||||
implementation("org.springframework.session:spring-session-data-mongodb")
|
||||
}
|
||||
|
||||
@@ -12,9 +12,9 @@ dependencies {
|
||||
dockerTestImplementation("com.redis:testcontainers-redis")
|
||||
dockerTestImplementation("org.testcontainers:junit-jupiter")
|
||||
|
||||
implementation(project(":spring-boot-project:spring-boot-session-data-redis"))
|
||||
implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-actuator"))
|
||||
implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-data-redis"))
|
||||
implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-security"))
|
||||
implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-web"))
|
||||
implementation("org.springframework.session:spring-session-data-redis")
|
||||
}
|
||||
|
||||
@@ -12,9 +12,9 @@ dependencies {
|
||||
dockerTestImplementation("org.testcontainers:junit-jupiter")
|
||||
dockerTestImplementation("org.testcontainers:mongodb")
|
||||
|
||||
implementation(project(":spring-boot-project:spring-boot-session-data-mongodb"))
|
||||
implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-security"))
|
||||
implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-webflux"))
|
||||
|
||||
runtimeOnly(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-data-mongodb-reactive"))
|
||||
runtimeOnly("org.springframework.session:spring-session-data-mongodb")
|
||||
}
|
||||
|
||||
@@ -12,9 +12,9 @@ dependencies {
|
||||
dockerTestImplementation("com.redis:testcontainers-redis")
|
||||
dockerTestImplementation("org.testcontainers:junit-jupiter")
|
||||
|
||||
implementation(project(":spring-boot-project:spring-boot-session-data-redis"))
|
||||
implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-security"))
|
||||
implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-webflux"))
|
||||
|
||||
runtimeOnly(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-data-redis-reactive"))
|
||||
runtimeOnly("org.springframework.session:spring-session-data-redis")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user