Skip to content

Commit 2977373

Browse files
committed
Polish "Add property to configure Spring Session Redis repository type"
See gh-32205
1 parent 3093380 commit 2977373

File tree

5 files changed

+78
-32
lines changed

5 files changed

+78
-32
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/RedisSessionConfiguration.java

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
2626
import org.springframework.boot.autoconfigure.web.ServerProperties;
2727
import org.springframework.boot.context.properties.EnableConfigurationProperties;
28+
import org.springframework.boot.context.properties.source.InvalidConfigurationPropertyValueException;
2829
import org.springframework.context.annotation.Bean;
2930
import org.springframework.context.annotation.Configuration;
3031
import org.springframework.data.redis.connection.RedisConnectionFactory;
@@ -53,16 +54,23 @@
5354
class RedisSessionConfiguration {
5455

5556
@Configuration(proxyBeanMethods = false)
56-
@ConditionalOnProperty(prefix = "spring.session.redis", name = "repository", havingValue = "default",
57+
@ConditionalOnProperty(prefix = "spring.session.redis", name = "repository-type", havingValue = "default",
5758
matchIfMissing = true)
5859
static class DefaultRedisSessionConfiguration {
5960

6061
@Configuration(proxyBeanMethods = false)
61-
public static class SpringBootRedisHttpSessionConfiguration extends RedisHttpSessionConfiguration {
62+
static class SpringBootRedisHttpSessionConfiguration extends RedisHttpSessionConfiguration {
6263

6364
@Autowired
64-
public void customize(SessionProperties sessionProperties, RedisSessionProperties redisSessionProperties,
65+
void customize(SessionProperties sessionProperties, RedisSessionProperties redisSessionProperties,
6566
ServerProperties serverProperties) {
67+
String cleanupCron = redisSessionProperties.getCleanupCron();
68+
if (cleanupCron != null) {
69+
throw new InvalidConfigurationPropertyValueException("spring.session.redis.cleanup-cron",
70+
cleanupCron,
71+
"Cron-based cleanup is only supported when spring.session.redis.repository-type is set to "
72+
+ "indexed.");
73+
}
6674
Duration timeout = sessionProperties
6775
.determineTimeout(() -> serverProperties.getServlet().getSession().getTimeout());
6876
if (timeout != null) {
@@ -78,7 +86,7 @@ public void customize(SessionProperties sessionProperties, RedisSessionPropertie
7886
}
7987

8088
@Configuration(proxyBeanMethods = false)
81-
@ConditionalOnProperty(prefix = "spring.session.redis", name = "repository", havingValue = "indexed")
89+
@ConditionalOnProperty(prefix = "spring.session.redis", name = "repository-type", havingValue = "indexed")
8290
static class IndexedRedisSessionConfiguration {
8391

8492
@Bean
@@ -91,11 +99,12 @@ ConfigureRedisAction configureRedisAction(RedisSessionProperties redisSessionPro
9199
}
92100

93101
@Configuration(proxyBeanMethods = false)
94-
public static class SpringBootRedisIndexedHttpSessionConfiguration
95-
extends RedisIndexedHttpSessionConfiguration {
102+
static class SpringBootRedisIndexedHttpSessionConfiguration extends RedisIndexedHttpSessionConfiguration {
103+
104+
private static final String DEFAULT_CLEANUP_CRON = "0 * * * * *";
96105

97106
@Autowired
98-
public void customize(SessionProperties sessionProperties, RedisSessionProperties redisSessionProperties,
107+
void customize(SessionProperties sessionProperties, RedisSessionProperties redisSessionProperties,
99108
ServerProperties serverProperties) {
100109
Duration timeout = sessionProperties
101110
.determineTimeout(() -> serverProperties.getServlet().getSession().getTimeout());
@@ -105,7 +114,8 @@ public void customize(SessionProperties sessionProperties, RedisSessionPropertie
105114
setRedisNamespace(redisSessionProperties.getNamespace());
106115
setFlushMode(redisSessionProperties.getFlushMode());
107116
setSaveMode(redisSessionProperties.getSaveMode());
108-
setCleanupCron(redisSessionProperties.getCleanupCron());
117+
String cleanupCron = redisSessionProperties.getCleanupCron();
118+
setCleanupCron((cleanupCron != null) ? cleanupCron : DEFAULT_CLEANUP_CRON);
109119
}
110120

111121
}

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/RedisSessionProperties.java

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2019 the original author or authors.
2+
* Copyright 2012-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -29,8 +29,6 @@
2929
@ConfigurationProperties(prefix = "spring.session.redis")
3030
public class RedisSessionProperties {
3131

32-
private static final String DEFAULT_CLEANUP_CRON = "0 * * * * *";
33-
3432
/**
3533
* Namespace for keys used to store sessions.
3634
*/
@@ -55,9 +53,15 @@ public class RedisSessionProperties {
5553
private ConfigureAction configureAction = ConfigureAction.NOTIFY_KEYSPACE_EVENTS;
5654

5755
/**
58-
* Cron expression for expired session cleanup job.
56+
* Cron expression for expired session cleanup job. Only supported when
57+
* repository-type is set to indexed.
5958
*/
60-
private String cleanupCron = DEFAULT_CLEANUP_CRON;
59+
private String cleanupCron;
60+
61+
/**
62+
* Type of Redis session repository to configure.
63+
*/
64+
private RepositoryType repositoryType = RepositoryType.DEFAULT;
6165

6266
public String getNamespace() {
6367
return this.namespace;
@@ -99,6 +103,14 @@ public void setConfigureAction(ConfigureAction configureAction) {
99103
this.configureAction = configureAction;
100104
}
101105

106+
public RepositoryType getRepositoryType() {
107+
return this.repositoryType;
108+
}
109+
110+
public void setRepositoryType(RepositoryType repositoryType) {
111+
this.repositoryType = repositoryType;
112+
}
113+
102114
/**
103115
* Strategies for configuring and validating Redis.
104116
*/
@@ -117,4 +129,21 @@ public enum ConfigureAction {
117129

118130
}
119131

132+
/**
133+
* Type of Redis session repository to auto-configure.
134+
*/
135+
public enum RepositoryType {
136+
137+
/**
138+
* Auto-configure a RedisSessionRepository.
139+
*/
140+
DEFAULT,
141+
142+
/**
143+
* Auto-configure a RedisIndexedSessionRepository.
144+
*/
145+
INDEXED
146+
147+
}
148+
120149
}

spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2749,6 +2749,10 @@
27492749
"name": "spring.session.jdbc.save-mode",
27502750
"defaultValue": "on-set-attribute"
27512751
},
2752+
{
2753+
"name": "spring.session.redis.cleanup-cron",
2754+
"defaultValue": "0 * * * * *"
2755+
},
27522756
{
27532757
"name": "spring.session.redis.configure-action",
27542758
"defaultValue": "notify-keyspace-events"
@@ -2758,18 +2762,8 @@
27582762
"defaultValue": "on-save"
27592763
},
27602764
{
2761-
"name": "spring.session.redis.repository",
2762-
"description": "Redis session repository implementation to use.",
2763-
"values": [
2764-
{
2765-
"value": "default",
2766-
"description": "Use default Redis session repository."
2767-
},
2768-
{
2769-
"value": "indexed",
2770-
"description": "Use indexed Redis session repository."
2771-
}
2772-
]
2765+
"name": "spring.session.redis.repository-type",
2766+
"defaultValue": "default"
27732767
},
27742768
{
27752769
"name": "spring.session.redis.save-mode",

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/SessionAutoConfigurationRedisTests.java

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
2828
import org.springframework.boot.autoconfigure.session.RedisSessionConfiguration.IndexedRedisSessionConfiguration.SpringBootRedisIndexedHttpSessionConfiguration;
2929
import org.springframework.boot.autoconfigure.web.ServerProperties;
30+
import org.springframework.boot.context.properties.source.InvalidConfigurationPropertyValueException;
3031
import org.springframework.boot.test.context.FilteredClassLoader;
3132
import org.springframework.boot.test.context.assertj.AssertableWebApplicationContext;
3233
import org.springframework.boot.test.context.runner.ContextConsumer;
@@ -75,6 +76,17 @@ void defaultConfig() {
7576
SaveMode.ON_SET_ATTRIBUTE));
7677
}
7778

79+
@Test
80+
void invalidConfigurationPropertyValueWhenDefaultConfigIsUsedWithCustomCronCleanup() {
81+
this.contextRunner.withPropertyValues("spring.data.redis.host=" + redis.getHost(),
82+
"spring.data.redis.port=" + redis.getFirstMappedPort(), "spring.session.redis.cleanup-cron=0 0 * * * *")
83+
.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class)).run((context) -> {
84+
assertThat(context).hasFailed();
85+
assertThat(context.getStartupFailure())
86+
.hasRootCauseExactlyInstanceOf(InvalidConfigurationPropertyValueException.class);
87+
});
88+
}
89+
7890
@Test
7991
void redisTakesPrecedenceMultipleImplementations() {
8092
this.contextRunner.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
@@ -108,7 +120,7 @@ void defaultRedisSessionStoreWithCustomizations() {
108120

109121
@Test
110122
void indexedRedisSessionDefaultConfig() {
111-
this.contextRunner.withPropertyValues("spring.session.redis.repository=indexed",
123+
this.contextRunner.withPropertyValues("spring.session.redis.repository-type=indexed",
112124
"spring.data.redis.host=" + redis.getHost(), "spring.data.redis.port=" + redis.getFirstMappedPort())
113125
.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
114126
.run(validateSpringSessionUsesIndexedRedis("spring:session:", FlushMode.ON_SAVE,
@@ -118,8 +130,9 @@ void indexedRedisSessionDefaultConfig() {
118130
@Test
119131
void indexedRedisSessionStoreWithCustomizations() {
120132
this.contextRunner.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
121-
.withPropertyValues("spring.session.redis.repository=indexed", "spring.session.redis.namespace=foo",
122-
"spring.session.redis.flush-mode=immediate", "spring.session.redis.save-mode=on-get-attribute",
133+
.withPropertyValues("spring.session.redis.repository-type=indexed",
134+
"spring.session.redis.namespace=foo", "spring.session.redis.flush-mode=immediate",
135+
"spring.session.redis.save-mode=on-get-attribute",
123136
"spring.session.redis.cleanup-cron=0 0 12 * * *", "spring.data.redis.host=" + redis.getHost(),
124137
"spring.data.redis.port=" + redis.getFirstMappedPort())
125138
.run(validateSpringSessionUsesIndexedRedis("foo:", FlushMode.IMMEDIATE, SaveMode.ON_GET_ATTRIBUTE,
@@ -129,7 +142,7 @@ void indexedRedisSessionStoreWithCustomizations() {
129142
@Test
130143
void indexedRedisSessionWithConfigureActionNone() {
131144
this.contextRunner.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
132-
.withPropertyValues("spring.session.redis.repository=indexed",
145+
.withPropertyValues("spring.session.redis.repository-type=indexed",
133146
"spring.session.redis.configure-action=none", "spring.data.redis.host=" + redis.getHost(),
134147
"spring.data.redis.port=" + redis.getFirstMappedPort())
135148
.run(validateStrategy(ConfigureRedisAction.NO_OP.getClass()));
@@ -138,7 +151,7 @@ void indexedRedisSessionWithConfigureActionNone() {
138151
@Test
139152
void indexedRedisSessionWithDefaultConfigureActionNone() {
140153
this.contextRunner.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
141-
.withPropertyValues("spring.session.redis.repository=indexed",
154+
.withPropertyValues("spring.session.redis.repository-type=indexed",
142155
"spring.data.redis.host=" + redis.getHost(),
143156
"spring.data.redis.port=" + redis.getFirstMappedPort())
144157
.run(validateStrategy(ConfigureNotifyKeyspaceEventsAction.class,
@@ -149,7 +162,7 @@ void indexedRedisSessionWithDefaultConfigureActionNone() {
149162
void indexedRedisSessionWithCustomConfigureRedisActionBean() {
150163
this.contextRunner.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
151164
.withUserConfiguration(MaxEntriesRedisAction.class)
152-
.withPropertyValues("spring.session.redis.repository=indexed",
165+
.withPropertyValues("spring.session.redis.repository-type=indexed",
153166
"spring.data.redis.host=" + redis.getHost(),
154167
"spring.data.redis.port=" + redis.getFirstMappedPort())
155168
.run(validateStrategy(MaxEntriesRedisAction.class, entry("set-max-intset-entries", "1024")));
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
management.endpoints.web.exposure.include=*
22
spring.security.user.name=user
33
spring.security.user.password=password
4-
spring.session.redis.repository=indexed
4+
spring.session.redis.repository-type=indexed

0 commit comments

Comments
 (0)