From c905b365e1ccf0c90f49d0552e36851f473d6934 Mon Sep 17 00:00:00 2001 From: John Blum Date: Mon, 22 Oct 2018 21:33:20 -0700 Subject: [PATCH] Add SpringSessionGemFireConfigurer support for configuring custom session expiration policies. Resolve gh-5. --- ...pSessionConfigurationIntegrationTests.java | 20 ++++++++++++-- ...pSessionConfigurationIntegrationTests.java | 12 +++++++++ .../http/GemFireHttpSessionConfiguration.java | 9 +++++-- .../SpringSessionGemFireConfigurer.java | 26 ++++++++++++++++++- .../GemFireHttpSessionConfigurationTests.java | 3 +++ 5 files changed, 65 insertions(+), 5 deletions(-) diff --git a/spring-session-data-geode/src/integration-test/java/org/springframework/session/data/gemfire/config/annotation/web/http/ConfigurerBasedGemFireHttpSessionConfigurationIntegrationTests.java b/spring-session-data-geode/src/integration-test/java/org/springframework/session/data/gemfire/config/annotation/web/http/ConfigurerBasedGemFireHttpSessionConfigurationIntegrationTests.java index 6778433..92b4e42 100644 --- a/spring-session-data-geode/src/integration-test/java/org/springframework/session/data/gemfire/config/annotation/web/http/ConfigurerBasedGemFireHttpSessionConfigurationIntegrationTests.java +++ b/spring-session-data-geode/src/integration-test/java/org/springframework/session/data/gemfire/config/annotation/web/http/ConfigurerBasedGemFireHttpSessionConfigurationIntegrationTests.java @@ -41,6 +41,7 @@ import org.springframework.data.gemfire.tests.mock.annotation.EnableGemFireMockO import org.springframework.mock.env.MockPropertySource; import org.springframework.session.Session; import org.springframework.session.data.gemfire.config.annotation.web.http.support.SpringSessionGemFireConfigurer; +import org.springframework.session.data.gemfire.expiration.SessionExpirationPolicy; import org.springframework.session.data.gemfire.serialization.SessionSerializer; /** @@ -73,7 +74,7 @@ public class ConfigurerBasedGemFireHttpSessionConfigurationIntegrationTests { } private ConfigurableApplicationContext newApplicationContext(PropertySource testPropertySource, - Class... annotatedClasses) { + Class... annotatedClasses) { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); @@ -86,7 +87,7 @@ public class ConfigurerBasedGemFireHttpSessionConfigurationIntegrationTests { } @Test - public void springSessionGemFireConfigurerOverridesAnnotationAttributeAndPropertyConfiguration() { + public void springSessionGemFireConfigurerOverridesAnnotationAttributesAndPropertyConfiguration() { MockPropertySource testPropertySource = new MockPropertySource("TestProperties") .withProperty("spring.session.data.gemfire.cache.client.pool.name", "Car") @@ -95,6 +96,7 @@ public class ConfigurerBasedGemFireHttpSessionConfigurationIntegrationTests { .withProperty("spring.session.data.gemfire.session.attributes.indexable", "firstName, lastName") .withProperty("spring.session.data.gemfire.session.expiration.max-inactive-interval-seconds", "600") .withProperty("spring.session.data.gemfire.session.region.name", "PropertyRegionName") + .withProperty("spring.session.data.gemfire.session.expiration.bean-name", "MockSessionExpirationPolicy") .withProperty("spring.session.data.gemfire.session.serializer.bean-name", "MockSessionSerializer"); this.applicationContext = newApplicationContext(testPropertySource, TestConfiguration.class); @@ -109,6 +111,7 @@ public class ConfigurerBasedGemFireHttpSessionConfigurationIntegrationTests { assertThat(sessionConfiguration.getPoolName()).isEqualTo("Dead"); assertThat(sessionConfiguration.getServerRegionShortcut()).isEqualTo(RegionShortcut.PARTITION); assertThat(sessionConfiguration.getSessionRegionName()).isEqualTo("ConfigurerRegionName"); + assertThat(sessionConfiguration.getSessionExpirationPolicyBeanName().orElse(null)).isEqualTo("ConfigurerSessionExpirationPolicy"); assertThat(sessionConfiguration.getSessionSerializerBeanName()).isEqualTo("SessionPdxSerializer"); } @@ -140,6 +143,7 @@ public class ConfigurerBasedGemFireHttpSessionConfigurationIntegrationTests { assertThat(sessionConfiguration.getPoolName()).isEqualTo("Car"); assertThat(sessionConfiguration.getServerRegionShortcut()).isEqualTo(RegionShortcut.PARTITION_PERSISTENT); assertThat(sessionConfiguration.getSessionRegionName()).isEqualTo("TestSessionRegionName"); + assertThat(sessionConfiguration.getSessionExpirationPolicyBeanName().orElse(null)).isNull(); assertThat(sessionConfiguration.getSessionSerializerBeanName()).isEqualTo("SessionPdxSerializer"); } @@ -158,6 +162,7 @@ public class ConfigurerBasedGemFireHttpSessionConfigurationIntegrationTests { assertThat(sessionConfiguration.getPoolName()).isEqualTo("Dead"); assertThat(sessionConfiguration.getServerRegionShortcut()).isEqualTo(RegionShortcut.PARTITION); assertThat(sessionConfiguration.getSessionRegionName()).isEqualTo("ConfigurerRegionName"); + assertThat(sessionConfiguration.getSessionExpirationPolicyBeanName().orElse(null)).isEqualTo("ConfigurerSessionExpirationPolicy"); assertThat(sessionConfiguration.getSessionSerializerBeanName()).isEqualTo("SessionPdxSerializer"); } @@ -170,6 +175,7 @@ public class ConfigurerBasedGemFireHttpSessionConfigurationIntegrationTests { poolName = "Swimming", regionName = "AnnotationAttributeRegionName", serverRegionShortcut = RegionShortcut.REPLICATE, + sessionExpirationPolicyBeanName = "TestSessionExpirationPolicy", sessionSerializerBeanName = "TestSessionSerializer" ) static class TestConfiguration { @@ -184,6 +190,11 @@ public class ConfigurerBasedGemFireHttpSessionConfigurationIntegrationTests { return mock(Pool.class); } + @Bean("TestSessionExpirationPolicy") + SessionExpirationPolicy testSessionExpirationPolicy() { + return mock(SessionExpirationPolicy.class); + } + @Bean("TestSessionSerializer") Object testSessionSerializer() { return mock(SessionSerializer.class); @@ -218,6 +229,11 @@ public class ConfigurerBasedGemFireHttpSessionConfigurationIntegrationTests { public String getRegionName() { return "ConfigurerRegionName"; } + + @Override + public String getSessionExpirationPolicyBeanName() { + return "ConfigurerSessionExpirationPolicy"; + } }; } } diff --git a/spring-session-data-geode/src/integration-test/java/org/springframework/session/data/gemfire/config/annotation/web/http/PropertyBasedGemFireHttpSessionConfigurationIntegrationTests.java b/spring-session-data-geode/src/integration-test/java/org/springframework/session/data/gemfire/config/annotation/web/http/PropertyBasedGemFireHttpSessionConfigurationIntegrationTests.java index f35ca94..26832c7 100644 --- a/spring-session-data-geode/src/integration-test/java/org/springframework/session/data/gemfire/config/annotation/web/http/PropertyBasedGemFireHttpSessionConfigurationIntegrationTests.java +++ b/spring-session-data-geode/src/integration-test/java/org/springframework/session/data/gemfire/config/annotation/web/http/PropertyBasedGemFireHttpSessionConfigurationIntegrationTests.java @@ -36,6 +36,7 @@ import org.springframework.data.gemfire.config.annotation.ClientCacheApplication import org.springframework.data.gemfire.tests.mock.annotation.EnableGemFireMockObjects; import org.springframework.mock.env.MockPropertySource; import org.springframework.session.Session; +import org.springframework.session.data.gemfire.expiration.SessionExpirationPolicy; import org.springframework.session.data.gemfire.serialization.SessionSerializer; /** @@ -93,6 +94,7 @@ public class PropertyBasedGemFireHttpSessionConfigurationIntegrationTests { assertThat(sessionConfiguration.getMaxInactiveIntervalInSeconds()).isEqualTo(900); assertThat(sessionConfiguration.getPoolName()).isEqualTo("Swimming"); assertThat(sessionConfiguration.getServerRegionShortcut()).isEqualTo(RegionShortcut.LOCAL); + assertThat(sessionConfiguration.getSessionExpirationPolicyBeanName().orElse(null)).isEqualTo("TestSessionExpirationPolicy"); assertThat(sessionConfiguration.getSessionRegionName()).isEqualTo("AnnotationAttributeRegionName"); assertThat(sessionConfiguration.getSessionSerializerBeanName()).isEqualTo("TestSessionSerializer"); } @@ -103,6 +105,7 @@ public class PropertyBasedGemFireHttpSessionConfigurationIntegrationTests { MockPropertySource testPropertySource = new MockPropertySource("TestProperties") .withProperty("spring.session.data.gemfire.cache.client.pool.name", "Dead") .withProperty("spring.session.data.gemfire.session.attributes.indexable", "two, four") + .withProperty("spring.session.data.gemfire.session.expiration.bean-name", "MockSessionExpirationPolicy") .withProperty("spring.session.data.gemfire.session.region.name", "TestRegionName"); this.applicationContext = newApplicationContext(testPropertySource, TestConfiguration.class); @@ -116,6 +119,7 @@ public class PropertyBasedGemFireHttpSessionConfigurationIntegrationTests { assertThat(sessionConfiguration.getMaxInactiveIntervalInSeconds()).isEqualTo(900); assertThat(sessionConfiguration.getPoolName()).isEqualTo("Dead"); assertThat(sessionConfiguration.getServerRegionShortcut()).isEqualTo(RegionShortcut.LOCAL); + assertThat(sessionConfiguration.getSessionExpirationPolicyBeanName().orElse(null)).isEqualTo("MockSessionExpirationPolicy"); assertThat(sessionConfiguration.getSessionRegionName()).isEqualTo("TestRegionName"); assertThat(sessionConfiguration.getSessionSerializerBeanName()).isEqualTo("TestSessionSerializer"); } @@ -128,6 +132,7 @@ public class PropertyBasedGemFireHttpSessionConfigurationIntegrationTests { .withProperty("spring.session.data.gemfire.cache.client.region.shortcut", ClientRegionShortcut.CACHING_PROXY.name()) .withProperty("spring.session.data.gemfire.cache.server.region.shortcut", RegionShortcut.REPLICATE_PERSISTENT_OVERFLOW.name()) .withProperty("spring.session.data.gemfire.session.attributes.indexable", "firstName, lastName") + .withProperty("spring.session.data.gemfire.session.expiration.bean-name", "MockSessionExpirationPolicy") .withProperty("spring.session.data.gemfire.session.expiration.max-inactive-interval-seconds", "3600") .withProperty("spring.session.data.gemfire.session.region.name", "PropertyRegionName") .withProperty("spring.session.data.gemfire.session.serializer.bean-name", "MockSessionSerializer"); @@ -143,6 +148,7 @@ public class PropertyBasedGemFireHttpSessionConfigurationIntegrationTests { assertThat(sessionConfiguration.getMaxInactiveIntervalInSeconds()).isEqualTo(3600); assertThat(sessionConfiguration.getPoolName()).isEqualTo("Dead"); assertThat(sessionConfiguration.getServerRegionShortcut()).isEqualTo(RegionShortcut.REPLICATE_PERSISTENT_OVERFLOW); + assertThat(sessionConfiguration.getSessionExpirationPolicyBeanName().orElse(null)).isEqualTo("MockSessionExpirationPolicy"); assertThat(sessionConfiguration.getSessionRegionName()).isEqualTo("PropertyRegionName"); assertThat(sessionConfiguration.getSessionSerializerBeanName()).isEqualTo("MockSessionSerializer"); } @@ -156,6 +162,7 @@ public class PropertyBasedGemFireHttpSessionConfigurationIntegrationTests { poolName = "Swimming", regionName = "AnnotationAttributeRegionName", serverRegionShortcut = RegionShortcut.LOCAL, + sessionExpirationPolicyBeanName = "TestSessionExpirationPolicy", sessionSerializerBeanName = "TestSessionSerializer" ) static class TestConfiguration { @@ -175,6 +182,11 @@ public class PropertyBasedGemFireHttpSessionConfigurationIntegrationTests { return mock(SessionSerializer.class); } + @Bean("TestSessionExpirationPolicy") + SessionExpirationPolicy testSessionExpirationPolicy() { + return mock(SessionExpirationPolicy.class); + } + @Bean("TestSessionSerializer") Object testSessionSerializer() { return mock(SessionSerializer.class); diff --git a/spring-session-data-geode/src/main/java/org/springframework/session/data/gemfire/config/annotation/web/http/GemFireHttpSessionConfiguration.java b/spring-session-data-geode/src/main/java/org/springframework/session/data/gemfire/config/annotation/web/http/GemFireHttpSessionConfiguration.java index dd6a0cc..62d05c6 100644 --- a/spring-session-data-geode/src/main/java/org/springframework/session/data/gemfire/config/annotation/web/http/GemFireHttpSessionConfiguration.java +++ b/spring-session-data-geode/src/main/java/org/springframework/session/data/gemfire/config/annotation/web/http/GemFireHttpSessionConfiguration.java @@ -81,14 +81,16 @@ import org.springframework.util.StringUtils; * {@link javax.servlet.http.HttpSession} provider implementation in Spring {@link Session}. * * @author John Blum + * @see org.apache.geode.cache.Cache * @see org.apache.geode.cache.ExpirationAttributes - * @see org.apache.geode.cache.GemFireCache * @see org.apache.geode.cache.Region * @see org.apache.geode.cache.RegionAttributes * @see org.apache.geode.cache.RegionShortcut + * @see org.apache.geode.cache.client.ClientCache * @see org.apache.geode.cache.client.ClientRegionShortcut * @see org.apache.geode.cache.client.Pool - * @see org.springframework.beans.factory.BeanClassLoaderAware + * @see org.apache.geode.pdx.PdxSerializer + * @see org.springframework.beans.factory.config.BeanPostProcessor * @see org.springframework.context.annotation.Bean * @see org.springframework.context.annotation.Configuration * @see org.springframework.context.annotation.DependsOn @@ -109,8 +111,10 @@ import org.springframework.util.StringUtils; * @see org.springframework.session.data.gemfire.config.annotation.web.http.EnableGemFireHttpSession * @see org.springframework.session.data.gemfire.config.annotation.web.http.support.GemFireCacheTypeAwareRegionFactoryBean * @see org.springframework.session.data.gemfire.config.annotation.web.http.support.SessionAttributesIndexFactoryBean + * @see org.springframework.session.data.gemfire.config.annotation.web.http.support.SpringSessionGemFireConfigurer * @see org.springframework.session.data.gemfire.expiration.SessionExpirationPolicy * @see org.springframework.session.data.gemfire.expiration.config.SessionExpirationTimeoutAwareBeanPostProcessor + * @see org.springframework.session.data.gemfire.expiration.support.SessionExpirationPolicyCustomExpiryAdapter * @see org.springframework.session.data.gemfire.serialization.SessionSerializer * @since 1.1.0 */ @@ -524,6 +528,7 @@ public class GemFireHttpSessionConfiguration extends AbstractGemFireHttpSessionC setPoolName(configurer.getPoolName()); setServerRegionShortcut(configurer.getServerRegionShortcut()); setSessionRegionName(configurer.getRegionName()); + setSessionExpirationPolicyBeanName(configurer.getSessionExpirationPolicyBeanName()); setSessionSerializerBeanName(configurer.getSessionSerializerBeanName()); }); } diff --git a/spring-session-data-geode/src/main/java/org/springframework/session/data/gemfire/config/annotation/web/http/support/SpringSessionGemFireConfigurer.java b/spring-session-data-geode/src/main/java/org/springframework/session/data/gemfire/config/annotation/web/http/support/SpringSessionGemFireConfigurer.java index 0bce6b0..f2ab0be 100644 --- a/spring-session-data-geode/src/main/java/org/springframework/session/data/gemfire/config/annotation/web/http/support/SpringSessionGemFireConfigurer.java +++ b/spring-session-data-geode/src/main/java/org/springframework/session/data/gemfire/config/annotation/web/http/support/SpringSessionGemFireConfigurer.java @@ -25,6 +25,7 @@ import org.apache.geode.cache.client.Pool; import org.springframework.session.Session; import org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration; +import org.springframework.session.data.gemfire.expiration.SessionExpirationPolicy; import org.springframework.session.data.gemfire.serialization.SessionSerializer; /** @@ -33,8 +34,16 @@ import org.springframework.session.data.gemfire.serialization.SessionSerializer; * in Spring Session. * * @author John Blum + * @see org.apache.geode.cache.Cache + * @see org.apache.geode.cache.Region + * @see org.apache.geode.cache.RegionShortcut + * @see org.apache.geode.cache.client.ClientCache + * @see org.apache.geode.cache.client.ClientRegionShortcut + * @see org.apache.geode.cache.client.Pool * @see org.springframework.session.data.gemfire.config.annotation.web.http.EnableGemFireHttpSession * @see org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration + * @see org.springframework.session.data.gemfire.expiration.SessionExpirationPolicy + * @see org.springframework.session.data.gemfire.serialization.SessionSerializer * @since 1.0.0 */ @SuppressWarnings("unused") @@ -124,11 +133,26 @@ public interface SpringSessionGemFireConfigurer { return GemFireHttpSessionConfiguration.DEFAULT_SERVER_REGION_SHORTCUT; } + /** + * Defines the name of the bean referring to the {@link SessionExpirationPolicy} used to configure + * the {@link Session} expiration logic and strategy. + * + * The {@link Object bean} referred to by its {@link String name} must be of type {@link SessionExpirationPolicy}. + * + * Defaults to unset. + + * @return a {@link String} containing the bean name of the configured {@link SessionExpirationPolicy}. + * @see org.springframework.session.data.gemfire.expiration.SessionExpirationPolicy + */ + default String getSessionExpirationPolicyBeanName() { + return GemFireHttpSessionConfiguration.DEFAULT_SESSION_EXPIRATION_POLICY_BEAN_NAME; + } + /** * Defines the bean name of the {@link SessionSerializer} used to serialize {@link Session} state * between client and server or to disk when persisting or overflowing {@link Session} state. * - * The bean referred to by its name must be of type {@link SessionSerializer}. + * The {@link Object bean} referred to by its {@link String name} must be of type {@link SessionSerializer}. * * Defaults to {@literal SessionPdxSerializer}. * diff --git a/spring-session-data-geode/src/test/java/org/springframework/session/data/gemfire/config/annotation/web/http/GemFireHttpSessionConfigurationTests.java b/spring-session-data-geode/src/test/java/org/springframework/session/data/gemfire/config/annotation/web/http/GemFireHttpSessionConfigurationTests.java index 268f3ad..6e28cc3 100644 --- a/spring-session-data-geode/src/test/java/org/springframework/session/data/gemfire/config/annotation/web/http/GemFireHttpSessionConfigurationTests.java +++ b/spring-session-data-geode/src/test/java/org/springframework/session/data/gemfire/config/annotation/web/http/GemFireHttpSessionConfigurationTests.java @@ -66,9 +66,12 @@ import org.springframework.util.ReflectionUtils; * @see org.apache.geode.cache.Cache * @see org.apache.geode.cache.GemFireCache * @see org.apache.geode.cache.Region + * @see org.apache.geode.cache.RegionAttributes + * @see org.apache.geode.cache.RegionShortcut * @see org.apache.geode.cache.ExpirationAttributes * @see org.apache.geode.cache.RegionAttributes * @see org.apache.geode.cache.client.ClientCache + * @see org.apache.geode.cache.client.ClientRegionShortcut * @see org.springframework.beans.factory.config.ConfigurableListableBeanFactory * @see org.springframework.context.ConfigurableApplicationContext * @see org.springframework.core.type.AnnotationMetadata