diff --git a/samples/boot/redis-json/src/integration-test/java/sample/RedisSerializerTest.java b/samples/boot/redis-json/src/integration-test/java/sample/RedisSerializerTest.java index a52cc4c6..b8eccda5 100644 --- a/samples/boot/redis-json/src/integration-test/java/sample/RedisSerializerTest.java +++ b/samples/boot/redis-json/src/integration-test/java/sample/RedisSerializerTest.java @@ -21,13 +21,13 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.testcontainers.containers.GenericContainer; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.util.TestPropertyValues; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; +import org.springframework.session.data.redis.config.annotation.web.http.SpringSessionRedisOperations; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; @@ -48,7 +48,7 @@ public class RedisSerializerTest { public static GenericContainer redisContainer = new GenericContainer(DOCKER_IMAGE) .withExposedPorts(6379); - @Autowired + @SpringSessionRedisOperations private RedisTemplate sessionRedisTemplate; @Test diff --git a/spring-session-data-redis/src/integration-test/java/org/springframework/session/data/redis/RedisOperationsSessionRepositoryITests.java b/spring-session-data-redis/src/integration-test/java/org/springframework/session/data/redis/RedisOperationsSessionRepositoryITests.java index 1d9a288d..c2a0fd12 100644 --- a/spring-session-data-redis/src/integration-test/java/org/springframework/session/data/redis/RedisOperationsSessionRepositoryITests.java +++ b/spring-session-data-redis/src/integration-test/java/org/springframework/session/data/redis/RedisOperationsSessionRepositoryITests.java @@ -38,6 +38,7 @@ import org.springframework.session.Session; import org.springframework.session.data.SessionEventRegistry; import org.springframework.session.data.redis.RedisOperationsSessionRepository.RedisSession; import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession; +import org.springframework.session.data.redis.config.annotation.web.http.SpringSessionRedisOperations; import org.springframework.session.events.SessionCreatedEvent; import org.springframework.session.events.SessionDestroyedEvent; import org.springframework.test.context.ContextConfiguration; @@ -61,7 +62,7 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests @Autowired private SessionEventRegistry registry; - @Autowired + @SpringSessionRedisOperations private RedisOperations redis; private SecurityContext context; diff --git a/spring-session-data-redis/src/integration-test/java/org/springframework/session/data/redis/taskexecutor/RedisListenerContainerTaskExecutorITests.java b/spring-session-data-redis/src/integration-test/java/org/springframework/session/data/redis/taskexecutor/RedisListenerContainerTaskExecutorITests.java index 2ccc68d4..d1dea0d5 100644 --- a/spring-session-data-redis/src/integration-test/java/org/springframework/session/data/redis/taskexecutor/RedisListenerContainerTaskExecutorITests.java +++ b/spring-session-data-redis/src/integration-test/java/org/springframework/session/data/redis/taskexecutor/RedisListenerContainerTaskExecutorITests.java @@ -32,6 +32,7 @@ import org.springframework.data.redis.core.BoundSetOperations; import org.springframework.data.redis.core.RedisOperations; import org.springframework.session.data.redis.AbstractRedisITests; import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession; +import org.springframework.session.data.redis.config.annotation.web.http.SpringSessionRedisOperations; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; @@ -49,7 +50,7 @@ public class RedisListenerContainerTaskExecutorITests extends AbstractRedisITest @Autowired private SessionTaskExecutor executor; - @Autowired + @SpringSessionRedisOperations private RedisOperations redis; @Test diff --git a/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/RedisOperationsSessionRepository.java b/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/RedisOperationsSessionRepository.java index 4928ef72..3f78e5d2 100644 --- a/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/RedisOperationsSessionRepository.java +++ b/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/RedisOperationsSessionRepository.java @@ -385,6 +385,10 @@ public class RedisOperationsSessionRepository implements this.redisFlushMode = redisFlushMode; } + public RedisOperations getSessionRedisOperations() { + return this.sessionRedisOperations; + } + public void save(RedisSession session) { session.saveDelta(); if (session.isNew()) { diff --git a/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfiguration.java b/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfiguration.java index c9e8e408..d202aa5a 100644 --- a/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfiguration.java +++ b/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfiguration.java @@ -17,12 +17,14 @@ package org.springframework.session.data.redis.config.annotation.web.http; import java.util.Arrays; +import java.util.Collections; import java.util.Map; import java.util.concurrent.Executor; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.ApplicationEventPublisher; @@ -35,7 +37,6 @@ import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.type.AnnotationMetadata; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.connection.RedisConnectionFactory; -import org.springframework.data.redis.core.RedisOperations; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.listener.PatternTopic; import org.springframework.data.redis.listener.RedisMessageListenerContainer; @@ -59,6 +60,7 @@ import org.springframework.util.StringValueResolver; * * @author Rob Winch * @author Eddú Meléndez + * @author Vedran Pavic * @see EnableRedisHttpSession * @since 1.0 */ @@ -69,12 +71,14 @@ public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguratio private Integer maxInactiveIntervalInSeconds = 1800; - private ConfigureRedisAction configureRedisAction = new ConfigureNotifyKeyspaceEventsAction(); - private String redisNamespace = ""; private RedisFlushMode redisFlushMode = RedisFlushMode.ON_SAVE; + private ConfigureRedisAction configureRedisAction = new ConfigureNotifyKeyspaceEventsAction(); + + private RedisConnectionFactory redisConnectionFactory; + private RedisSerializer defaultRedisSerializer; private Executor redisTaskExecutor; @@ -84,12 +88,31 @@ public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguratio private StringValueResolver embeddedValueResolver; @Bean - public RedisMessageListenerContainer redisMessageListenerContainer( - RedisConnectionFactory connectionFactory, - RedisOperationsSessionRepository messageListener) { + public RedisOperationsSessionRepository sessionRepository( + ApplicationEventPublisher applicationEventPublisher) { + RedisTemplate redisTemplate = createRedisTemplate( + this.redisConnectionFactory, this.defaultRedisSerializer); + RedisOperationsSessionRepository sessionRepository = new RedisOperationsSessionRepository( + redisTemplate); + sessionRepository.setApplicationEventPublisher(applicationEventPublisher); + if (this.defaultRedisSerializer != null) { + sessionRepository.setDefaultSerializer(this.defaultRedisSerializer); + } + sessionRepository + .setDefaultMaxInactiveInterval(this.maxInactiveIntervalInSeconds); + String redisNamespace = getRedisNamespace(); + if (StringUtils.hasText(redisNamespace)) { + sessionRepository.setRedisKeyNamespace(redisNamespace); + } + sessionRepository.setRedisFlushMode(this.redisFlushMode); + return sessionRepository; + } + @Bean + public RedisMessageListenerContainer redisMessageListenerContainer( + RedisOperationsSessionRepository messageListener) { RedisMessageListenerContainer container = new RedisMessageListenerContainer(); - container.setConnectionFactory(connectionFactory); + container.setConnectionFactory(this.redisConnectionFactory); if (this.redisTaskExecutor != null) { container.setTaskExecutor(this.redisTaskExecutor); } @@ -99,44 +122,25 @@ public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguratio container.addMessageListener(messageListener, Arrays.asList(new PatternTopic("__keyevent@*:del"), new PatternTopic("__keyevent@*:expired"))); - container.addMessageListener(messageListener, Arrays.asList(new PatternTopic( - messageListener.getSessionCreatedChannelPrefix() + "*"))); + container.addMessageListener(messageListener, + Collections.singletonList(new PatternTopic( + messageListener.getSessionCreatedChannelPrefix() + "*"))); return container; } @Bean - public RedisTemplate sessionRedisTemplate( - RedisConnectionFactory connectionFactory) { - RedisTemplate template = new RedisTemplate<>(); - template.setKeySerializer(new StringRedisSerializer()); - template.setHashKeySerializer(new StringRedisSerializer()); - if (this.defaultRedisSerializer != null) { - template.setDefaultSerializer(this.defaultRedisSerializer); - } - template.setConnectionFactory(connectionFactory); - return template; + public InitializingBean enableRedisKeyspaceNotificationsInitializer() { + return new EnableRedisKeyspaceNotificationsInitializer( + this.redisConnectionFactory, this.configureRedisAction); } + /** + * Property placeholder to process the @Scheduled annotation. + * @return the {@link PropertySourcesPlaceholderConfigurer} to use + */ @Bean - public RedisOperationsSessionRepository sessionRepository( - @Qualifier("sessionRedisTemplate") RedisOperations sessionRedisTemplate, - ApplicationEventPublisher applicationEventPublisher) { - RedisOperationsSessionRepository sessionRepository = new RedisOperationsSessionRepository( - sessionRedisTemplate); - sessionRepository.setApplicationEventPublisher(applicationEventPublisher); - sessionRepository - .setDefaultMaxInactiveInterval(this.maxInactiveIntervalInSeconds); - if (this.defaultRedisSerializer != null) { - sessionRepository.setDefaultSerializer(this.defaultRedisSerializer); - } - - String redisNamespace = getRedisNamespace(); - if (StringUtils.hasText(redisNamespace)) { - sessionRepository.setRedisKeyNamespace(redisNamespace); - } - - sessionRepository.setRedisFlushMode(this.redisFlushMode); - return sessionRepository; + public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { + return new PropertySourcesPlaceholderConfigurer(); } public void setMaxInactiveIntervalInSeconds(int maxInactiveIntervalInSeconds) { @@ -152,45 +156,29 @@ public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguratio this.redisFlushMode = redisFlushMode; } - private String getRedisNamespace() { - if (StringUtils.hasText(this.redisNamespace)) { - return this.redisNamespace; - } - return System.getProperty("spring.session.redis.namespace", ""); - } - - public void setImportMetadata(AnnotationMetadata importMetadata) { - - Map enableAttrMap = importMetadata - .getAnnotationAttributes(EnableRedisHttpSession.class.getName()); - AnnotationAttributes enableAttrs = AnnotationAttributes.fromMap(enableAttrMap); - this.maxInactiveIntervalInSeconds = enableAttrs - .getNumber("maxInactiveIntervalInSeconds"); - String redisNamespaceValue = enableAttrs.getString("redisNamespace"); - if (StringUtils.hasText(redisNamespaceValue)) { - this.redisNamespace = this.embeddedValueResolver.resolveStringValue(redisNamespaceValue); - } - this.redisFlushMode = enableAttrs.getEnum("redisFlushMode"); - } - - @Bean - public InitializingBean enableRedisKeyspaceNotificationsInitializer( - RedisConnectionFactory connectionFactory) { - return new EnableRedisKeyspaceNotificationsInitializer(connectionFactory, - this.configureRedisAction); - } - /** * Sets the action to perform for configuring Redis. * * @param configureRedisAction the configureRedis to set. The default is - * {@link ConfigureNotifyKeyspaceEventsAction}. + * {@link ConfigureNotifyKeyspaceEventsAction}. */ @Autowired(required = false) public void setConfigureRedisAction(ConfigureRedisAction configureRedisAction) { this.configureRedisAction = configureRedisAction; } + @Autowired + public void setRedisConnectionFactory( + @SpringSessionRedisConnectionFactory ObjectProvider springSessionRedisConnectionFactory, + ObjectProvider redisConnectionFactory) { + RedisConnectionFactory redisConnectionFactoryToUse = springSessionRedisConnectionFactory + .getIfAvailable(); + if (redisConnectionFactoryToUse == null) { + redisConnectionFactoryToUse = redisConnectionFactory.getObject(); + } + this.redisConnectionFactory = redisConnectionFactoryToUse; + } + @Autowired(required = false) @Qualifier("springSessionDefaultRedisSerializer") public void setDefaultRedisSerializer( @@ -214,13 +202,39 @@ public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguratio this.embeddedValueResolver = resolver; } - /** - * Property placeholder to process the @Scheduled annotation. - * @return the {@link PropertySourcesPlaceholderConfigurer} to use - */ - @Bean - public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { - return new PropertySourcesPlaceholderConfigurer(); + public void setImportMetadata(AnnotationMetadata importMetadata) { + Map enableAttrMap = importMetadata + .getAnnotationAttributes(EnableRedisHttpSession.class.getName()); + AnnotationAttributes enableAttrs = AnnotationAttributes.fromMap(enableAttrMap); + this.maxInactiveIntervalInSeconds = enableAttrs + .getNumber("maxInactiveIntervalInSeconds"); + String redisNamespaceValue = enableAttrs.getString("redisNamespace"); + if (StringUtils.hasText(redisNamespaceValue)) { + this.redisNamespace = this.embeddedValueResolver + .resolveStringValue(redisNamespaceValue); + } + this.redisFlushMode = enableAttrs.getEnum("redisFlushMode"); + } + + private static RedisTemplate createRedisTemplate( + RedisConnectionFactory redisConnectionFactory, + RedisSerializer defaultRedisSerializer) { + RedisTemplate redisTemplate = new RedisTemplate<>(); + redisTemplate.setKeySerializer(new StringRedisSerializer()); + redisTemplate.setHashKeySerializer(new StringRedisSerializer()); + if (defaultRedisSerializer != null) { + redisTemplate.setDefaultSerializer(defaultRedisSerializer); + } + redisTemplate.setConnectionFactory(redisConnectionFactory); + redisTemplate.afterPropertiesSet(); + return redisTemplate; + } + + private String getRedisNamespace() { + if (StringUtils.hasText(this.redisNamespace)) { + return this.redisNamespace; + } + return System.getProperty("spring.session.redis.namespace", ""); } /** @@ -231,6 +245,7 @@ public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguratio * up. */ static class EnableRedisKeyspaceNotificationsInitializer implements InitializingBean { + private final RedisConnectionFactory connectionFactory; private ConfigureRedisAction configure; @@ -255,10 +270,12 @@ public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguratio connection.close(); } catch (Exception e) { - LogFactory.getLog(getClass()).error("Error closing RedisConnection", e); + LogFactory.getLog(getClass()).error("Error closing RedisConnection", + e); } } } + } } diff --git a/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/config/annotation/web/http/SpringSessionRedisConnectionFactory.java b/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/config/annotation/web/http/SpringSessionRedisConnectionFactory.java new file mode 100644 index 00000000..20c22b62 --- /dev/null +++ b/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/config/annotation/web/http/SpringSessionRedisConnectionFactory.java @@ -0,0 +1,43 @@ +/* + * Copyright 2014-2017 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 + * + * http://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.session.data.redis.config.annotation.web.http; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.session.data.redis.RedisOperationsSessionRepository; + +/** + * Qualifier annotation for a {@link RedisConnectionFactory} to be injected in + * {@link RedisOperationsSessionRepository}. + * + * @author Vedran Pavic + * @since 2.0.0 + */ +@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, + ElementType.ANNOTATION_TYPE }) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Qualifier +public @interface SpringSessionRedisConnectionFactory { + +} diff --git a/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/config/annotation/web/http/SpringSessionRedisOperations.java b/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/config/annotation/web/http/SpringSessionRedisOperations.java new file mode 100644 index 00000000..5c249a4e --- /dev/null +++ b/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/config/annotation/web/http/SpringSessionRedisOperations.java @@ -0,0 +1,43 @@ +/* + * Copyright 2014-2017 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 + * + * http://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.session.data.redis.config.annotation.web.http; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.RedisOperations; +import org.springframework.session.data.redis.RedisOperationsSessionRepository; + +/** + * Annotation used to inject the {@link RedisOperations} instance used by Spring Session's + * {@link RedisOperationsSessionRepository}. + * + * @author Vedran Pavic + * @since 2.0.0 + */ +@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, + ElementType.ANNOTATION_TYPE }) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Value("#{sessionRepository.sessionRedisOperations}") +public @interface SpringSessionRedisOperations { + +} diff --git a/spring-session-data-redis/src/test/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfigurationOverrideDefaultSerializerTests.java b/spring-session-data-redis/src/test/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfigurationOverrideDefaultSerializerTests.java index 51796840..5e481016 100644 --- a/spring-session-data-redis/src/test/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfigurationOverrideDefaultSerializerTests.java +++ b/spring-session-data-redis/src/test/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfigurationOverrideDefaultSerializerTests.java @@ -47,7 +47,7 @@ import static org.mockito.Mockito.mock; @WebAppConfiguration public class RedisHttpSessionConfigurationOverrideDefaultSerializerTests { - @Autowired + @SpringSessionRedisOperations RedisTemplate template; @Autowired diff --git a/spring-session-data-redis/src/test/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfigurationTests.java b/spring-session-data-redis/src/test/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfigurationTests.java index 869ab422..e7d51d7b 100644 --- a/spring-session-data-redis/src/test/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfigurationTests.java +++ b/spring-session-data-redis/src/test/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfigurationTests.java @@ -20,15 +20,21 @@ import java.util.Properties; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.springframework.beans.factory.BeanCreationException; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisOperations; import org.springframework.mock.env.MockEnvironment; +import org.springframework.session.data.redis.RedisOperationsSessionRepository; import org.springframework.test.util.ReflectionTestUtils; import static org.assertj.core.api.Assertions.assertThat; @@ -37,11 +43,17 @@ import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; /** + * Tests for {@link RedisHttpSessionConfiguration}. + * * @author Eddú Meléndez * @author Mark Paluch + * @author Vedran Pavic */ public class RedisHttpSessionConfigurationTests { + @Rule + public final ExpectedException thrown = ExpectedException.none(); + private AnnotationConfigApplicationContext context; @Before @@ -59,16 +71,101 @@ public class RedisHttpSessionConfigurationTests { @Test public void resolveValue() { registerAndRefresh(RedisConfig.class, CustomRedisHttpSessionConfiguration.class); - RedisHttpSessionConfiguration configuration = this.context.getBean(RedisHttpSessionConfiguration.class); - assertThat(ReflectionTestUtils.getField(configuration, "redisNamespace")).isEqualTo("myRedisNamespace"); + RedisHttpSessionConfiguration configuration = this.context + .getBean(RedisHttpSessionConfiguration.class); + assertThat(ReflectionTestUtils.getField(configuration, "redisNamespace")) + .isEqualTo("myRedisNamespace"); } @Test public void resolveValueByPlaceholder() { - this.context.setEnvironment(new MockEnvironment().withProperty("session.redis.namespace", "customRedisNamespace")); - registerAndRefresh(RedisConfig.class, PropertySourceConfiguration.class, CustomRedisHttpSessionConfiguration2.class); - RedisHttpSessionConfiguration configuration = this.context.getBean(RedisHttpSessionConfiguration.class); - assertThat(ReflectionTestUtils.getField(configuration, "redisNamespace")).isEqualTo("customRedisNamespace"); + this.context.setEnvironment(new MockEnvironment() + .withProperty("session.redis.namespace", "customRedisNamespace")); + registerAndRefresh(RedisConfig.class, PropertySourceConfiguration.class, + CustomRedisHttpSessionConfiguration2.class); + RedisHttpSessionConfiguration configuration = this.context + .getBean(RedisHttpSessionConfiguration.class); + assertThat(ReflectionTestUtils.getField(configuration, "redisNamespace")) + .isEqualTo("customRedisNamespace"); + } + + @Test + public void qualifiedConnectionFactoryRedisConfig() { + registerAndRefresh(RedisConfig.class, + QualifiedConnectionFactoryRedisConfig.class); + + RedisOperationsSessionRepository repository = this.context + .getBean(RedisOperationsSessionRepository.class); + RedisConnectionFactory redisConnectionFactory = this.context + .getBean("qualifiedRedisConnectionFactory", RedisConnectionFactory.class); + assertThat(repository).isNotNull(); + assertThat(redisConnectionFactory).isNotNull(); + RedisOperations redisOperations = (RedisOperations) ReflectionTestUtils + .getField(repository, "sessionRedisOperations"); + assertThat(redisOperations).isNotNull(); + assertThat(ReflectionTestUtils.getField(redisOperations, "connectionFactory")) + .isEqualTo(redisConnectionFactory); + } + + @Test + public void primaryConnectionFactoryRedisConfig() { + registerAndRefresh(RedisConfig.class, PrimaryConnectionFactoryRedisConfig.class); + + RedisOperationsSessionRepository repository = this.context + .getBean(RedisOperationsSessionRepository.class); + RedisConnectionFactory redisConnectionFactory = this.context + .getBean("primaryRedisConnectionFactory", RedisConnectionFactory.class); + assertThat(repository).isNotNull(); + assertThat(redisConnectionFactory).isNotNull(); + RedisOperations redisOperations = (RedisOperations) ReflectionTestUtils + .getField(repository, "sessionRedisOperations"); + assertThat(redisOperations).isNotNull(); + assertThat(ReflectionTestUtils.getField(redisOperations, "connectionFactory")) + .isEqualTo(redisConnectionFactory); + } + + @Test + public void qualifiedAndPrimaryDataSourceConfiguration() { + registerAndRefresh(RedisConfig.class, + QualifiedAndPrimaryConnectionFactoryRedisConfig.class); + + RedisOperationsSessionRepository repository = this.context + .getBean(RedisOperationsSessionRepository.class); + RedisConnectionFactory redisConnectionFactory = this.context + .getBean("qualifiedRedisConnectionFactory", RedisConnectionFactory.class); + assertThat(repository).isNotNull(); + assertThat(redisConnectionFactory).isNotNull(); + RedisOperations redisOperations = (RedisOperations) ReflectionTestUtils + .getField(repository, "sessionRedisOperations"); + assertThat(redisOperations).isNotNull(); + assertThat(ReflectionTestUtils.getField(redisOperations, "connectionFactory")) + .isEqualTo(redisConnectionFactory); + } + + @Test + public void namedDataSourceConfiguration() { + registerAndRefresh(RedisConfig.class, NamedConnectionFactoryRedisConfig.class); + + RedisOperationsSessionRepository repository = this.context + .getBean(RedisOperationsSessionRepository.class); + RedisConnectionFactory redisConnectionFactory = this.context + .getBean("redisConnectionFactory", RedisConnectionFactory.class); + assertThat(repository).isNotNull(); + assertThat(redisConnectionFactory).isNotNull(); + RedisOperations redisOperations = (RedisOperations) ReflectionTestUtils + .getField(repository, "sessionRedisOperations"); + assertThat(redisOperations).isNotNull(); + assertThat(ReflectionTestUtils.getField(redisOperations, "connectionFactory")) + .isEqualTo(redisConnectionFactory); + } + + @Test + public void multipleDataSourceConfiguration() { + this.thrown.expect(BeanCreationException.class); + this.thrown.expectMessage( + "secondaryRedisConnectionFactory,defaultRedisConnectionFactory"); + + registerAndRefresh(MultipleConnectionFactoryRedisConfig.class); } private void registerAndRefresh(Class... annotatedClasses) { @@ -76,6 +173,14 @@ public class RedisHttpSessionConfigurationTests { this.context.refresh(); } + private static RedisConnectionFactory mockRedisConnectionFactory() { + RedisConnectionFactory connectionFactory = mock(RedisConnectionFactory.class); + RedisConnection connection = mock(RedisConnection.class); + given(connectionFactory.getConnection()).willReturn(connection); + given(connection.getConfig(anyString())).willReturn(new Properties()); + return connectionFactory; + } + @Configuration static class PropertySourceConfiguration { @@ -89,13 +194,73 @@ public class RedisHttpSessionConfigurationTests { @Configuration static class RedisConfig { + @Bean + public RedisConnectionFactory defaultRedisConnectionFactory() { + return mockRedisConnectionFactory(); + } + + } + + @Configuration + @EnableRedisHttpSession + static class QualifiedConnectionFactoryRedisConfig extends RedisConfig { + + @Bean + @SpringSessionRedisConnectionFactory + public RedisConnectionFactory qualifiedRedisConnectionFactory() { + return mockRedisConnectionFactory(); + } + + } + + @Configuration + @EnableRedisHttpSession + static class PrimaryConnectionFactoryRedisConfig extends RedisConfig { + + @Bean + @Primary + public RedisConnectionFactory primaryRedisConnectionFactory() { + return mockRedisConnectionFactory(); + } + + } + + @Configuration + @EnableRedisHttpSession + static class QualifiedAndPrimaryConnectionFactoryRedisConfig extends RedisConfig { + + @Bean + @SpringSessionRedisConnectionFactory + public RedisConnectionFactory qualifiedRedisConnectionFactory() { + return mockRedisConnectionFactory(); + } + + @Bean + @Primary + public RedisConnectionFactory primaryRedisConnectionFactory() { + return mockRedisConnectionFactory(); + } + + } + + @Configuration + @EnableRedisHttpSession + static class NamedConnectionFactoryRedisConfig extends RedisConfig { + @Bean public RedisConnectionFactory redisConnectionFactory() { - RedisConnectionFactory connectionFactory = mock(RedisConnectionFactory.class); - RedisConnection connection = mock(RedisConnection.class); - given(connectionFactory.getConnection()).willReturn(connection); - given(connection.getConfig(anyString())).willReturn(new Properties()); - return connectionFactory; + return mockRedisConnectionFactory(); + } + + } + + @Configuration + @EnableRedisHttpSession + static class MultipleConnectionFactoryRedisConfig extends RedisConfig { + + @Bean + public RedisConnectionFactory secondaryRedisConnectionFactory() { + return mockRedisConnectionFactory(); } } diff --git a/spring-session-data-redis/src/test/java/org/springframework/session/data/redis/config/annotation/web/http/gh109/Gh109Tests.java b/spring-session-data-redis/src/test/java/org/springframework/session/data/redis/config/annotation/web/http/gh109/Gh109Tests.java index 58667330..6f584a90 100644 --- a/spring-session-data-redis/src/test/java/org/springframework/session/data/redis/config/annotation/web/http/gh109/Gh109Tests.java +++ b/spring-session-data-redis/src/test/java/org/springframework/session/data/redis/config/annotation/web/http/gh109/Gh109Tests.java @@ -63,7 +63,6 @@ public class Gh109Tests { * override sessionRepository construction to set the custom session-timeout */ @Bean - @Override public RedisOperationsSessionRepository sessionRepository( RedisOperations sessionRedisTemplate, ApplicationEventPublisher applicationEventPublisher) {