Closed tonny1983 closed 1 year ago
Hi, @tonny1983. Properties is a feature from Spring Boot, so unfortunately there is nothing we can do related to that on Spring Session side.
If you want Spring Boot to back off and you want to have control over Spring Session configuration, you can use @Enable*HttpSession
as mentioned in Spring Boot docs:
You can take control over Spring Session’s configuration using @Enable*HttpSession (servlet) or @Enable*WebSession (reactive).
This will cause the auto-configuration to back off.
Spring Session can then be configured using the annotation’s attributes rather than the previously described configuration properties.
You can use the annotation in combination with @ConditionalOnProperty
annotation from Spring Boot.
Another solution is to use the Testcontainers support or Docker Compose support so you have the same setup in both dev/prod.
But is there some sort of shortcut to fully disable Spring Session based on the application properties file? The original question was about whether there was a way to actually disable it entirely instead of take over the manual configuration. Why would I annotate with @Enable*HttpSession
if I don't want it to run at all? For example, if I want to revert to regular Tomcat HttpSession when developing locally, I shouldn't annotate @EnableRedisHttpSession
or any of the @Enable*
methods right? Or is there a way that I can use @EnableRedisHttpSession
and functionally make it not use Redis at all?
Having the same question and issue, from my current understanding Spring session now go through a list of implementation and check if its in classpath and auto config if it detected a implementation and the only way to explicitly specify which store type to use is with @Enable*HttpSession
. The issue is that currently with our codebases this results in two behaviour, 1. specify using Redis store type by using @EnableRedisHttpSession
, or 2. not specifying it and since the redis implementation is in the classpath, forced to use Redis store type
Unless there is a @DisableHttpSession
or similar annotation I can no longer replicate the behaviour of spring.session.store-type=none
without removing the redis implementation from my classpath or to outright implement my own SessionRepository.
Is there a way that I can selectively at run time disable spring session entirely? Almost as if it weren't in pom.xml at all? For situations where redis isn't available? Some devs don't run redis locally and I'd prefer not to make them install it as part of their dev environment if they can revert back to regular HttpSession when the spring profile selected is for local development.
Hi there, my solution for this problem was this setup:
@SpringBootApplication
@EnableAutoConfiguration(exclude = { RedisAutoConfiguration.class})
public class Application {
/**
* clone of private class:
* org.springframework.boot.autoconfigure.session.RedisSessionConfiguration
*/
@Configuration
@ConditionalOnProperty(prefix = "application", name = "session.store", havingValue = "redis")
@EnableConfigurationProperties(RedisSessionProperties.class)
@Import({ RedisAutoConfiguration.class })
public class RedisSessionConfig {
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(prefix = "spring.session.redis", name = "repository-type", havingValue = "default", matchIfMissing = true)
@Import(RedisHttpSessionConfiguration.class)
@EnableRedisHttpSession
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(prefix = "spring.session.redis", name = "repository-type", havingValue = "indexed")
@Import(RedisIndexedHttpSessionConfiguration.class)
@EnableRedisIndexedHttpSession
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);
};
}
}
}
Afterwards I was able to enable RedisSession Store with: application.session.store = redis
. Configuration of redis as usual.
# Sessions
##########
# *|redis
#application.session.store = redis
# *|indexed
spring.session.redis.repository-type = indexed
spring.session.redis.namespace = redis:sessions
spring.data.redis.host = localhost
spring.data.redis.password =
spring.data.redis.port = 6379
Hope this help you.
Expected Behavior
A new configuration property, maybe
spring.session.enabled
, might be introduced in order to disable the session management funtion in some circumstances.Current Behavior There seems be no such configuration properties which could disable the session management fucntion.
Context Before version 3.0, according to the documenet there was a property,
spring.session.store-type
, which could be set tonone
in order to disable it.Meanwhile, from version 3.0, according to the issue and document, the property has been removed because the persistence implementation order was defined when multiple were available.
Actually, there might be some situations, especially in testing, in which the users prefer to disable the session management, because it is disigned for the use case where clustered sessions are required, but for some business logic testing in a single node.
There may be an alternative solution. The
spring-session-jdbc
dependency can be introduced in testing environment and then uses@EnableJdbcHttpSession
annotation to configurate a JDBC connection to an in-memory (might beH2
) which often occurs in testing. Therefore, in production environment, the applcation may connect to redis cluster for high performance and, in testing, connect to in-memory DB for the requirement of spring session.However, the alternative might not work for reactive application due to only
Redis
andMongoDB
are supported.