Add support for configuring custom IndexResolver

See: #1467
This commit is contained in:
Vedran Pavic
2019-09-26 22:18:37 +02:00
parent b357a76ce3
commit feaf8780a8
9 changed files with 144 additions and 13 deletions

View File

@@ -280,8 +280,6 @@ public class RedisIndexedSessionRepository
private final RedisSessionExpirationPolicy expirationPolicy; private final RedisSessionExpirationPolicy expirationPolicy;
private final IndexResolver<RedisSession> indexResolver;
private ApplicationEventPublisher eventPublisher = (event) -> { private ApplicationEventPublisher eventPublisher = (event) -> {
}; };
@@ -291,6 +289,8 @@ public class RedisIndexedSessionRepository
*/ */
private Integer defaultMaxInactiveInterval; private Integer defaultMaxInactiveInterval;
private IndexResolver<Session> indexResolver = new DelegatingIndexResolver<>(new PrincipalNameIndexResolver<>());
private RedisSerializer<Object> defaultSerializer = new JdkSerializationRedisSerializer(); private RedisSerializer<Object> defaultSerializer = new JdkSerializationRedisSerializer();
private FlushMode flushMode = FlushMode.ON_SAVE; private FlushMode flushMode = FlushMode.ON_SAVE;
@@ -307,7 +307,6 @@ public class RedisIndexedSessionRepository
this.sessionRedisOperations = sessionRedisOperations; this.sessionRedisOperations = sessionRedisOperations;
this.expirationPolicy = new RedisSessionExpirationPolicy(sessionRedisOperations, this::getExpirationsKey, this.expirationPolicy = new RedisSessionExpirationPolicy(sessionRedisOperations, this::getExpirationsKey,
this::getSessionKey); this::getSessionKey);
this.indexResolver = new DelegatingIndexResolver<>(new PrincipalNameIndexResolver<>());
configureSessionChannels(); configureSessionChannels();
} }
@@ -334,6 +333,15 @@ public class RedisIndexedSessionRepository
this.defaultMaxInactiveInterval = defaultMaxInactiveInterval; this.defaultMaxInactiveInterval = defaultMaxInactiveInterval;
} }
/**
* Set the {@link IndexResolver} to use.
* @param indexResolver the index resolver
*/
public void setIndexResolver(IndexResolver<Session> indexResolver) {
Assert.notNull(indexResolver, "indexResolver cannot be null");
this.indexResolver = indexResolver;
}
/** /**
* Sets the default redis serializer. Replaces default serializer which is based on * Sets the default redis serializer. Replaces default serializer which is based on
* {@link JdkSerializationRedisSerializer}. * {@link JdkSerializationRedisSerializer}.

View File

@@ -51,8 +51,10 @@ import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer; import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar; import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.session.FlushMode; import org.springframework.session.FlushMode;
import org.springframework.session.IndexResolver;
import org.springframework.session.MapSession; import org.springframework.session.MapSession;
import org.springframework.session.SaveMode; import org.springframework.session.SaveMode;
import org.springframework.session.Session;
import org.springframework.session.config.SessionRepositoryCustomizer; import org.springframework.session.config.SessionRepositoryCustomizer;
import org.springframework.session.config.annotation.web.http.SpringHttpSessionConfiguration; import org.springframework.session.config.annotation.web.http.SpringHttpSessionConfiguration;
import org.springframework.session.data.redis.RedisFlushMode; import org.springframework.session.data.redis.RedisFlushMode;
@@ -98,6 +100,8 @@ public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguratio
private RedisConnectionFactory redisConnectionFactory; private RedisConnectionFactory redisConnectionFactory;
private IndexResolver<Session> indexResolver;
private RedisSerializer<Object> defaultRedisSerializer; private RedisSerializer<Object> defaultRedisSerializer;
private ApplicationEventPublisher applicationEventPublisher; private ApplicationEventPublisher applicationEventPublisher;
@@ -117,6 +121,9 @@ public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguratio
RedisTemplate<Object, Object> redisTemplate = createRedisTemplate(); RedisTemplate<Object, Object> redisTemplate = createRedisTemplate();
RedisIndexedSessionRepository sessionRepository = new RedisIndexedSessionRepository(redisTemplate); RedisIndexedSessionRepository sessionRepository = new RedisIndexedSessionRepository(redisTemplate);
sessionRepository.setApplicationEventPublisher(this.applicationEventPublisher); sessionRepository.setApplicationEventPublisher(this.applicationEventPublisher);
if (this.indexResolver != null) {
sessionRepository.setIndexResolver(this.indexResolver);
}
if (this.defaultRedisSerializer != null) { if (this.defaultRedisSerializer != null) {
sessionRepository.setDefaultSerializer(this.defaultRedisSerializer); sessionRepository.setDefaultSerializer(this.defaultRedisSerializer);
} }
@@ -216,6 +223,11 @@ public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguratio
this.applicationEventPublisher = applicationEventPublisher; this.applicationEventPublisher = applicationEventPublisher;
} }
@Autowired(required = false)
public void setIndexResolver(IndexResolver<Session> indexResolver) {
this.indexResolver = indexResolver;
}
@Autowired(required = false) @Autowired(required = false)
@Qualifier("springSessionRedisTaskExecutor") @Qualifier("springSessionRedisTaskExecutor")
public void setRedisTaskExecutor(Executor redisTaskExecutor) { public void setRedisTaskExecutor(Executor redisTaskExecutor) {

View File

@@ -36,7 +36,9 @@ import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.listener.RedisMessageListenerContainer; import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.mock.env.MockEnvironment; import org.springframework.mock.env.MockEnvironment;
import org.springframework.session.FlushMode; import org.springframework.session.FlushMode;
import org.springframework.session.IndexResolver;
import org.springframework.session.SaveMode; import org.springframework.session.SaveMode;
import org.springframework.session.Session;
import org.springframework.session.config.SessionRepositoryCustomizer; import org.springframework.session.config.SessionRepositoryCustomizer;
import org.springframework.session.data.redis.RedisFlushMode; import org.springframework.session.data.redis.RedisFlushMode;
import org.springframework.session.data.redis.RedisIndexedSessionRepository; import org.springframework.session.data.redis.RedisIndexedSessionRepository;
@@ -228,6 +230,17 @@ class RedisHttpSessionConfigurationTests {
.withMessageContaining("expected single matching bean but found 2"); .withMessageContaining("expected single matching bean but found 2");
} }
@Test
void customIndexResolverConfiguration() {
registerAndRefresh(RedisConfig.class, CustomIndexResolverConfiguration.class);
RedisIndexedSessionRepository repository = this.context.getBean(RedisIndexedSessionRepository.class);
@SuppressWarnings("unchecked")
IndexResolver<Session> indexResolver = this.context.getBean(IndexResolver.class);
assertThat(repository).isNotNull();
assertThat(indexResolver).isNotNull();
assertThat(repository).hasFieldOrPropertyWithValue("indexResolver", indexResolver);
}
@Test // gh-1252 @Test // gh-1252
void customRedisMessageListenerContainerConfig() { void customRedisMessageListenerContainerConfig() {
registerAndRefresh(RedisConfig.class, CustomRedisMessageListenerContainerConfig.class); registerAndRefresh(RedisConfig.class, CustomRedisMessageListenerContainerConfig.class);
@@ -414,6 +427,18 @@ class RedisHttpSessionConfigurationTests {
} }
@Configuration
@EnableRedisHttpSession
static class CustomIndexResolverConfiguration {
@Bean
@SuppressWarnings("unchecked")
public IndexResolver<Session> indexResolver() {
return mock(IndexResolver.class);
}
}
@Configuration @Configuration
@EnableRedisHttpSession @EnableRedisHttpSession
static class CustomRedisMessageListenerContainerConfig { static class CustomRedisMessageListenerContainerConfig {

View File

@@ -133,8 +133,6 @@ public class HazelcastIndexedSessionRepository
private final HazelcastInstance hazelcastInstance; private final HazelcastInstance hazelcastInstance;
private final IndexResolver<HazelcastSession> indexResolver;
private ApplicationEventPublisher eventPublisher = (event) -> { private ApplicationEventPublisher eventPublisher = (event) -> {
}; };
@@ -144,6 +142,8 @@ public class HazelcastIndexedSessionRepository
*/ */
private Integer defaultMaxInactiveInterval; private Integer defaultMaxInactiveInterval;
private IndexResolver<Session> indexResolver = new DelegatingIndexResolver<>(new PrincipalNameIndexResolver<>());
private String sessionMapName = DEFAULT_SESSION_MAP_NAME; private String sessionMapName = DEFAULT_SESSION_MAP_NAME;
private FlushMode flushMode = FlushMode.ON_SAVE; private FlushMode flushMode = FlushMode.ON_SAVE;
@@ -161,7 +161,6 @@ public class HazelcastIndexedSessionRepository
public HazelcastIndexedSessionRepository(HazelcastInstance hazelcastInstance) { public HazelcastIndexedSessionRepository(HazelcastInstance hazelcastInstance) {
Assert.notNull(hazelcastInstance, "HazelcastInstance must not be null"); Assert.notNull(hazelcastInstance, "HazelcastInstance must not be null");
this.hazelcastInstance = hazelcastInstance; this.hazelcastInstance = hazelcastInstance;
this.indexResolver = new DelegatingIndexResolver<>(new PrincipalNameIndexResolver<>());
} }
@PostConstruct @PostConstruct
@@ -197,6 +196,15 @@ public class HazelcastIndexedSessionRepository
this.defaultMaxInactiveInterval = defaultMaxInactiveInterval; this.defaultMaxInactiveInterval = defaultMaxInactiveInterval;
} }
/**
* Set the {@link IndexResolver} to use.
* @param indexResolver the index resolver
*/
public void setIndexResolver(IndexResolver<Session> indexResolver) {
Assert.notNull(indexResolver, "indexResolver cannot be null");
this.indexResolver = indexResolver;
}
/** /**
* Set the name of map used to store sessions. * Set the name of map used to store sessions.
* @param sessionMapName the session map name * @param sessionMapName the session map name

View File

@@ -31,8 +31,10 @@ import org.springframework.context.annotation.ImportAware;
import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata; import org.springframework.core.type.AnnotationMetadata;
import org.springframework.session.FlushMode; import org.springframework.session.FlushMode;
import org.springframework.session.IndexResolver;
import org.springframework.session.MapSession; import org.springframework.session.MapSession;
import org.springframework.session.SaveMode; import org.springframework.session.SaveMode;
import org.springframework.session.Session;
import org.springframework.session.config.SessionRepositoryCustomizer; import org.springframework.session.config.SessionRepositoryCustomizer;
import org.springframework.session.config.annotation.web.http.SpringHttpSessionConfiguration; import org.springframework.session.config.annotation.web.http.SpringHttpSessionConfiguration;
import org.springframework.session.hazelcast.HazelcastFlushMode; import org.springframework.session.hazelcast.HazelcastFlushMode;
@@ -66,6 +68,8 @@ public class HazelcastHttpSessionConfiguration extends SpringHttpSessionConfigur
private ApplicationEventPublisher applicationEventPublisher; private ApplicationEventPublisher applicationEventPublisher;
private IndexResolver<Session> indexResolver;
private List<SessionRepositoryCustomizer<HazelcastIndexedSessionRepository>> sessionRepositoryCustomizers; private List<SessionRepositoryCustomizer<HazelcastIndexedSessionRepository>> sessionRepositoryCustomizers;
@Bean @Bean
@@ -73,6 +77,9 @@ public class HazelcastHttpSessionConfiguration extends SpringHttpSessionConfigur
HazelcastIndexedSessionRepository sessionRepository = new HazelcastIndexedSessionRepository( HazelcastIndexedSessionRepository sessionRepository = new HazelcastIndexedSessionRepository(
this.hazelcastInstance); this.hazelcastInstance);
sessionRepository.setApplicationEventPublisher(this.applicationEventPublisher); sessionRepository.setApplicationEventPublisher(this.applicationEventPublisher);
if (this.indexResolver != null) {
sessionRepository.setIndexResolver(this.indexResolver);
}
if (StringUtils.hasText(this.sessionMapName)) { if (StringUtils.hasText(this.sessionMapName)) {
sessionRepository.setSessionMapName(this.sessionMapName); sessionRepository.setSessionMapName(this.sessionMapName);
} }
@@ -121,6 +128,11 @@ public class HazelcastHttpSessionConfiguration extends SpringHttpSessionConfigur
this.applicationEventPublisher = applicationEventPublisher; this.applicationEventPublisher = applicationEventPublisher;
} }
@Autowired(required = false)
public void setIndexResolver(IndexResolver<Session> indexResolver) {
this.indexResolver = indexResolver;
}
@Autowired(required = false) @Autowired(required = false)
public void setSessionRepositoryCustomizer( public void setSessionRepositoryCustomizer(
ObjectProvider<SessionRepositoryCustomizer<HazelcastIndexedSessionRepository>> sessionRepositoryCustomizers) { ObjectProvider<SessionRepositoryCustomizer<HazelcastIndexedSessionRepository>> sessionRepositoryCustomizers) {

View File

@@ -28,7 +28,9 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Primary;
import org.springframework.core.annotation.Order; import org.springframework.core.annotation.Order;
import org.springframework.session.FlushMode; import org.springframework.session.FlushMode;
import org.springframework.session.IndexResolver;
import org.springframework.session.SaveMode; import org.springframework.session.SaveMode;
import org.springframework.session.Session;
import org.springframework.session.config.SessionRepositoryCustomizer; import org.springframework.session.config.SessionRepositoryCustomizer;
import org.springframework.session.hazelcast.HazelcastFlushMode; import org.springframework.session.hazelcast.HazelcastFlushMode;
import org.springframework.session.hazelcast.HazelcastIndexedSessionRepository; import org.springframework.session.hazelcast.HazelcastIndexedSessionRepository;
@@ -223,6 +225,17 @@ class HazelcastHttpSessionConfigurationTests {
.withMessageContaining("expected single matching bean but found 2"); .withMessageContaining("expected single matching bean but found 2");
} }
@Test
void customIndexResolverConfiguration() {
registerAndRefresh(CustomIndexResolverConfiguration.class);
HazelcastIndexedSessionRepository repository = this.context.getBean(HazelcastIndexedSessionRepository.class);
@SuppressWarnings("unchecked")
IndexResolver<Session> indexResolver = this.context.getBean(IndexResolver.class);
assertThat(repository).isNotNull();
assertThat(indexResolver).isNotNull();
assertThat(repository).hasFieldOrPropertyWithValue("indexResolver", indexResolver);
}
@Test @Test
void sessionRepositoryCustomizer() { void sessionRepositoryCustomizer() {
registerAndRefresh(SessionRepositoryCustomizerConfiguration.class); registerAndRefresh(SessionRepositoryCustomizerConfiguration.class);
@@ -433,6 +446,17 @@ class HazelcastHttpSessionConfigurationTests {
} }
@EnableHazelcastHttpSession
static class CustomIndexResolverConfiguration extends BaseConfiguration {
@Bean
@SuppressWarnings("unchecked")
public IndexResolver<Session> indexResolver() {
return mock(IndexResolver.class);
}
}
@EnableHazelcastHttpSession @EnableHazelcastHttpSession
static class SessionRepositoryCustomizerConfiguration extends BaseConfiguration { static class SessionRepositoryCustomizerConfiguration extends BaseConfiguration {

View File

@@ -198,8 +198,6 @@ public class JdbcIndexedSessionRepository
private final ResultSetExtractor<List<JdbcSession>> extractor = new SessionResultSetExtractor(); private final ResultSetExtractor<List<JdbcSession>> extractor = new SessionResultSetExtractor();
private final IndexResolver<JdbcSession> indexResolver;
/** /**
* The name of database table used by Spring Session to store sessions. * The name of database table used by Spring Session to store sessions.
*/ */
@@ -229,9 +227,11 @@ public class JdbcIndexedSessionRepository
*/ */
private Integer defaultMaxInactiveInterval; private Integer defaultMaxInactiveInterval;
private ConversionService conversionService; private IndexResolver<Session> indexResolver = new DelegatingIndexResolver<>(new PrincipalNameIndexResolver<>());
private LobHandler lobHandler; private ConversionService conversionService = createDefaultConversionService();
private LobHandler lobHandler = new DefaultLobHandler();
private FlushMode flushMode = FlushMode.ON_SAVE; private FlushMode flushMode = FlushMode.ON_SAVE;
@@ -248,9 +248,6 @@ public class JdbcIndexedSessionRepository
Assert.notNull(transactionOperations, "transactionOperations must not be null"); Assert.notNull(transactionOperations, "transactionOperations must not be null");
this.jdbcOperations = jdbcOperations; this.jdbcOperations = jdbcOperations;
this.transactionOperations = transactionOperations; this.transactionOperations = transactionOperations;
this.indexResolver = new DelegatingIndexResolver<>(new PrincipalNameIndexResolver<>());
this.conversionService = createDefaultConversionService();
this.lobHandler = new DefaultLobHandler();
prepareQueries(); prepareQueries();
} }
@@ -355,6 +352,15 @@ public class JdbcIndexedSessionRepository
this.defaultMaxInactiveInterval = defaultMaxInactiveInterval; this.defaultMaxInactiveInterval = defaultMaxInactiveInterval;
} }
/**
* Set the {@link IndexResolver} to use.
* @param indexResolver the index resolver
*/
public void setIndexResolver(IndexResolver<Session> indexResolver) {
Assert.notNull(indexResolver, "indexResolver cannot be null");
this.indexResolver = indexResolver;
}
public void setLobHandler(LobHandler lobHandler) { public void setLobHandler(LobHandler lobHandler) {
Assert.notNull(lobHandler, "LobHandler must not be null"); Assert.notNull(lobHandler, "LobHandler must not be null");
this.lobHandler = lobHandler; this.lobHandler = lobHandler;

View File

@@ -45,8 +45,10 @@ import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer; import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar; import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.session.FlushMode; import org.springframework.session.FlushMode;
import org.springframework.session.IndexResolver;
import org.springframework.session.MapSession; import org.springframework.session.MapSession;
import org.springframework.session.SaveMode; import org.springframework.session.SaveMode;
import org.springframework.session.Session;
import org.springframework.session.config.SessionRepositoryCustomizer; import org.springframework.session.config.SessionRepositoryCustomizer;
import org.springframework.session.config.annotation.web.http.SpringHttpSessionConfiguration; import org.springframework.session.config.annotation.web.http.SpringHttpSessionConfiguration;
import org.springframework.session.jdbc.JdbcIndexedSessionRepository; import org.springframework.session.jdbc.JdbcIndexedSessionRepository;
@@ -95,6 +97,8 @@ public class JdbcHttpSessionConfiguration extends SpringHttpSessionConfiguration
private TransactionOperations transactionOperations; private TransactionOperations transactionOperations;
private IndexResolver<Session> indexResolver;
private LobHandler lobHandler; private LobHandler lobHandler;
private ConversionService springSessionConversionService; private ConversionService springSessionConversionService;
@@ -121,6 +125,9 @@ public class JdbcHttpSessionConfiguration extends SpringHttpSessionConfiguration
sessionRepository.setDefaultMaxInactiveInterval(this.maxInactiveIntervalInSeconds); sessionRepository.setDefaultMaxInactiveInterval(this.maxInactiveIntervalInSeconds);
sessionRepository.setFlushMode(this.flushMode); sessionRepository.setFlushMode(this.flushMode);
sessionRepository.setSaveMode(this.saveMode); sessionRepository.setSaveMode(this.saveMode);
if (this.indexResolver != null) {
sessionRepository.setIndexResolver(this.indexResolver);
}
if (this.lobHandler != null) { if (this.lobHandler != null) {
sessionRepository.setLobHandler(this.lobHandler); sessionRepository.setLobHandler(this.lobHandler);
} }
@@ -194,6 +201,11 @@ public class JdbcHttpSessionConfiguration extends SpringHttpSessionConfiguration
this.transactionOperations = transactionOperations; this.transactionOperations = transactionOperations;
} }
@Autowired(required = false)
public void setIndexResolver(IndexResolver<Session> indexResolver) {
this.indexResolver = indexResolver;
}
@Autowired(required = false) @Autowired(required = false)
@Qualifier("springSessionLobHandler") @Qualifier("springSessionLobHandler")
public void setLobHandler(LobHandler lobHandler) { public void setLobHandler(LobHandler lobHandler) {

View File

@@ -33,7 +33,9 @@ import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.jdbc.support.lob.LobHandler; import org.springframework.jdbc.support.lob.LobHandler;
import org.springframework.mock.env.MockEnvironment; import org.springframework.mock.env.MockEnvironment;
import org.springframework.session.FlushMode; import org.springframework.session.FlushMode;
import org.springframework.session.IndexResolver;
import org.springframework.session.SaveMode; import org.springframework.session.SaveMode;
import org.springframework.session.Session;
import org.springframework.session.config.SessionRepositoryCustomizer; import org.springframework.session.config.SessionRepositoryCustomizer;
import org.springframework.session.jdbc.JdbcIndexedSessionRepository; import org.springframework.session.jdbc.JdbcIndexedSessionRepository;
import org.springframework.session.jdbc.config.annotation.SpringSessionDataSource; import org.springframework.session.jdbc.config.annotation.SpringSessionDataSource;
@@ -242,6 +244,17 @@ class JdbcHttpSessionConfigurationTests {
assertThat(repository).hasFieldOrPropertyWithValue("transactionOperations", transactionOperations); assertThat(repository).hasFieldOrPropertyWithValue("transactionOperations", transactionOperations);
} }
@Test
void customIndexResolverConfiguration() {
registerAndRefresh(DataSourceConfiguration.class, CustomIndexResolverConfiguration.class);
JdbcIndexedSessionRepository repository = this.context.getBean(JdbcIndexedSessionRepository.class);
@SuppressWarnings("unchecked")
IndexResolver<Session> indexResolver = this.context.getBean(IndexResolver.class);
assertThat(repository).isNotNull();
assertThat(indexResolver).isNotNull();
assertThat(repository).hasFieldOrPropertyWithValue("indexResolver", indexResolver);
}
@Test @Test
void customLobHandlerConfiguration() { void customLobHandlerConfiguration() {
registerAndRefresh(DataSourceConfiguration.class, CustomLobHandlerConfiguration.class); registerAndRefresh(DataSourceConfiguration.class, CustomLobHandlerConfiguration.class);
@@ -452,6 +465,17 @@ class JdbcHttpSessionConfigurationTests {
} }
@EnableJdbcHttpSession
static class CustomIndexResolverConfiguration {
@Bean
@SuppressWarnings("unchecked")
public IndexResolver<Session> indexResolver() {
return mock(IndexResolver.class);
}
}
@EnableJdbcHttpSession @EnableJdbcHttpSession
static class CustomLobHandlerConfiguration { static class CustomLobHandlerConfiguration {