Skip to content

Commit a0fabc9

Browse files
nosanphilwebb
authored andcommitted
Add session property for ConfigureRedisAction
Add a new property to `RedisSessionProperties` that allows the default `ConfigureRedisAction` to be changed. Users can still also configure the action using a `@Bean`. See gh-17022
1 parent 2888dde commit a0fabc9

File tree

3 files changed

+104
-1
lines changed

3 files changed

+104
-1
lines changed

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,17 @@
2222
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
2323
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
2424
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
25+
import org.springframework.boot.autoconfigure.session.RedisSessionProperties.ConfigurationStrategy;
2526
import org.springframework.boot.context.properties.EnableConfigurationProperties;
27+
import org.springframework.context.annotation.Bean;
2628
import org.springframework.context.annotation.Conditional;
2729
import org.springframework.context.annotation.Configuration;
2830
import org.springframework.data.redis.connection.RedisConnectionFactory;
2931
import org.springframework.data.redis.core.RedisTemplate;
3032
import org.springframework.session.SessionRepository;
3133
import org.springframework.session.data.redis.RedisOperationsSessionRepository;
34+
import org.springframework.session.data.redis.config.ConfigureNotifyKeyspaceEventsAction;
35+
import org.springframework.session.data.redis.config.ConfigureRedisAction;
3236
import org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration;
3337

3438
/**
@@ -62,6 +66,19 @@ public void customize(SessionProperties sessionProperties, RedisSessionPropertie
6266
setCleanupCron(redisSessionProperties.getCleanupCron());
6367
}
6468

69+
@Bean
70+
@ConditionalOnMissingBean
71+
public ConfigureRedisAction configureRedisAction(RedisSessionProperties redisSessionProperties) {
72+
ConfigurationStrategy strategy = redisSessionProperties.getConfigurationStrategy();
73+
if (strategy == ConfigurationStrategy.NOTIFY_KEYSPACE_EVENTS) {
74+
return new ConfigureNotifyKeyspaceEventsAction();
75+
}
76+
if (strategy == ConfigurationStrategy.NO_OP) {
77+
return ConfigureRedisAction.NO_OP;
78+
}
79+
throw new IllegalStateException("Strategy '" + strategy + "' is not supported.");
80+
}
81+
6582
}
6683

6784
}

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

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2017 the original author or authors.
2+
* Copyright 2012-2019 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.
@@ -40,6 +40,11 @@ public class RedisSessionProperties {
4040
*/
4141
private RedisFlushMode flushMode = RedisFlushMode.ON_SAVE;
4242

43+
/**
44+
* Allows specifying a strategy for configuring and validating Redis.
45+
*/
46+
private ConfigurationStrategy configurationStrategy = ConfigurationStrategy.NOTIFY_KEYSPACE_EVENTS;
47+
4348
/**
4449
* Cron expression for expired session cleanup job.
4550
*/
@@ -69,4 +74,29 @@ public void setCleanupCron(String cleanupCron) {
6974
this.cleanupCron = cleanupCron;
7075
}
7176

77+
public ConfigurationStrategy getConfigurationStrategy() {
78+
return this.configurationStrategy;
79+
}
80+
81+
public void setConfigurationStrategy(ConfigurationStrategy configurationStrategy) {
82+
this.configurationStrategy = configurationStrategy;
83+
}
84+
85+
/**
86+
* Allows specifying a strategy for configuring and validating Redis.
87+
*/
88+
public enum ConfigurationStrategy {
89+
90+
/**
91+
* Do nothing.
92+
*/
93+
NO_OP,
94+
/**
95+
* Ensures that Redis Keyspace events for Generic commands and Expired events are
96+
* enabled.
97+
*/
98+
NOTIFY_KEYSPACE_EVENTS
99+
100+
}
101+
72102
}

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

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package org.springframework.boot.autoconfigure.session;
1818

19+
import java.util.Map;
20+
1921
import org.junit.jupiter.api.Test;
2022
import org.testcontainers.junit.jupiter.Container;
2123

@@ -28,13 +30,18 @@
2830
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
2931
import org.springframework.boot.testsupport.testcontainers.DisabledWithoutDockerTestcontainers;
3032
import org.springframework.boot.testsupport.testcontainers.RedisContainer;
33+
import org.springframework.data.redis.connection.RedisConnection;
34+
import org.springframework.data.redis.connection.RedisConnectionFactory;
3135
import org.springframework.session.data.mongo.MongoOperationsSessionRepository;
3236
import org.springframework.session.data.redis.RedisFlushMode;
3337
import org.springframework.session.data.redis.RedisOperationsSessionRepository;
38+
import org.springframework.session.data.redis.config.ConfigureNotifyKeyspaceEventsAction;
39+
import org.springframework.session.data.redis.config.ConfigureRedisAction;
3440
import org.springframework.session.hazelcast.HazelcastSessionRepository;
3541
import org.springframework.session.jdbc.JdbcOperationsSessionRepository;
3642

3743
import static org.assertj.core.api.Assertions.assertThat;
44+
import static org.assertj.core.api.Assertions.entry;
3845

3946
/**
4047
* Redis specific tests for {@link SessionAutoConfiguration}.
@@ -81,6 +88,34 @@ void redisSessionStoreWithCustomizations() {
8188
.run(validateSpringSessionUsesRedis("foo:event:0:created:", RedisFlushMode.IMMEDIATE, "0 0 12 * * *"));
8289
}
8390

91+
@Test
92+
void redisSessionConfigureNoStrategy() {
93+
this.contextRunner.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
94+
.withPropertyValues("spring.session.store-type=redis",
95+
"spring.session.redis.configuration-strategy=no_op",
96+
"spring.redis.port=" + redis.getFirstMappedPort())
97+
.run(validateStrategy(ConfigureRedisAction.NO_OP.getClass()));
98+
}
99+
100+
@Test
101+
void redisSessionConfigureDefaultStrategy() {
102+
this.contextRunner.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
103+
.withPropertyValues("spring.session.store-type=redis",
104+
"spring.redis.port=" + redis.getFirstMappedPort())
105+
.run(validateStrategy(ConfigureNotifyKeyspaceEventsAction.class,
106+
entry("notify-keyspace-events", "gxE")));
107+
}
108+
109+
@Test
110+
void redisSessionConfigureCustomStrategy() {
111+
this.contextRunner.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
112+
.withUserConfiguration(MaxEntriesRedisAction.class)
113+
.withPropertyValues("spring.session.store-type=redis",
114+
"spring.redis.port=" + redis.getFirstMappedPort())
115+
.run(validateStrategy(MaxEntriesRedisAction.class, entry("set-max-intset-entries", "1024")));
116+
117+
}
118+
84119
private ContextConsumer<AssertableWebApplicationContext> validateSpringSessionUsesRedis(
85120
String sessionCreatedChannelPrefix, RedisFlushMode flushMode, String cleanupCron) {
86121
return (context) -> {
@@ -94,4 +129,25 @@ private ContextConsumer<AssertableWebApplicationContext> validateSpringSessionUs
94129
};
95130
}
96131

132+
private ContextConsumer<AssertableWebApplicationContext> validateStrategy(
133+
Class<? extends ConfigureRedisAction> actionClass, Map.Entry... values) {
134+
return (context) -> {
135+
assertThat(context).hasSingleBean(ConfigureRedisAction.class).hasSingleBean(RedisConnectionFactory.class);
136+
assertThat(context.getBean(ConfigureRedisAction.class)).isInstanceOf(actionClass);
137+
RedisConnection connection = context.getBean(RedisConnectionFactory.class).getConnection();
138+
if (values.length > 0) {
139+
assertThat(connection.getConfig("*")).contains(values);
140+
}
141+
};
142+
}
143+
144+
static class MaxEntriesRedisAction implements ConfigureRedisAction {
145+
146+
@Override
147+
public void configure(RedisConnection connection) {
148+
connection.setConfig("set-max-intset-entries", "1024");
149+
}
150+
151+
}
152+
97153
}

0 commit comments

Comments
 (0)