From bff54fa08ae822de37d79b83eb14e08aa83a0e2a Mon Sep 17 00:00:00 2001 From: John Blum Date: Tue, 23 Oct 2018 14:14:56 -0700 Subject: [PATCH] Refactor GemFireHttpSessionConfiguration to always set a Region Entry Idle Timeout (TTI) Expiration Policy regardless if the user provided her own custom, Region Entry Idle Timeout (TTI) Expiration Policy. Resolves gh-5. --- ...pirationConfigurationIntegrationTests.java | 31 ++++- .../http/GemFireHttpSessionConfiguration.java | 106 ++++++++++-------- 2 files changed, 88 insertions(+), 49 deletions(-) diff --git a/spring-session-data-geode/src/integration-test/java/org/springframework/session/data/gemfire/expiration/CustomSessionExpirationConfigurationIntegrationTests.java b/spring-session-data-geode/src/integration-test/java/org/springframework/session/data/gemfire/expiration/CustomSessionExpirationConfigurationIntegrationTests.java index 2d9ea80..4f08147 100644 --- a/spring-session-data-geode/src/integration-test/java/org/springframework/session/data/gemfire/expiration/CustomSessionExpirationConfigurationIntegrationTests.java +++ b/spring-session-data-geode/src/integration-test/java/org/springframework/session/data/gemfire/expiration/CustomSessionExpirationConfigurationIntegrationTests.java @@ -26,6 +26,8 @@ import javax.annotation.Resource; import org.junit.Test; import org.junit.runner.RunWith; +import org.apache.geode.cache.ExpirationAction; +import org.apache.geode.cache.ExpirationAttributes; import org.apache.geode.cache.Region; import org.apache.geode.cache.RegionAttributes; @@ -47,6 +49,8 @@ import org.springframework.util.ReflectionUtils; * * @author John Blum * @see org.junit.Test + * @see org.apache.geode.cache.ExpirationAction + * @see org.apache.geode.cache.ExpirationAttributes * @see org.apache.geode.cache.Region * @see org.apache.geode.cache.RegionAttributes * @see org.springframework.context.annotation.Bean @@ -90,7 +94,7 @@ public class CustomSessionExpirationConfigurationIntegrationTests { } @Test - public void regionIdleTimeoutExpirationConfigurationIsCorrect() throws Exception { + public void regionCustomEntryIdleTimeoutExpirationConfigurationIsCorrect() throws Exception { assertThat(this.sessions).isNotNull(); @@ -100,11 +104,30 @@ public class CustomSessionExpirationConfigurationIntegrationTests { assertThat(sessionRegionAttributes.getCustomEntryIdleTimeout()) .isInstanceOf(SessionExpirationPolicyCustomExpiryAdapter.class); - SessionExpirationPolicyCustomExpiryAdapter adapter = + SessionExpirationPolicyCustomExpiryAdapter customEntryIdleTimeout = (SessionExpirationPolicyCustomExpiryAdapter) sessionRegionAttributes.getCustomEntryIdleTimeout(); - assertThat(this.invokeMethod(adapter, "getSessionExpirationPolicy")) - .isEqualTo(this.sessionExpirationPolicy); + SessionExpirationPolicy actualSessionExpirationPolicy = + invokeMethod(customEntryIdleTimeout, "getSessionExpirationPolicy"); + + assertThat(actualSessionExpirationPolicy).isEqualTo(this.sessionExpirationPolicy); + + } + + @Test + public void regionEntryIdleTimeoutExpirationConfigurationIsCorrect() { + + assertThat(this.sessions).isNotNull(); + + RegionAttributes sessionRegionAttributes = this.sessions.getAttributes(); + + assertThat(sessionRegionAttributes).isNotNull(); + + ExpirationAttributes entryIdleTimeout = sessionRegionAttributes.getEntryIdleTimeout(); + + assertThat(entryIdleTimeout).isNotNull(); + assertThat(entryIdleTimeout.getTimeout()).isEqualTo(600); + assertThat(entryIdleTimeout.getAction()).isEqualTo(ExpirationAction.INVALIDATE); } @PeerCacheApplication 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 62d05c6..6e39485 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,8 +81,11 @@ import org.springframework.util.StringUtils; * {@link javax.servlet.http.HttpSession} provider implementation in Spring {@link Session}. * * @author John Blum + * @see java.time.Duration + * @see org.apache.geode.DataSerializer * @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 @@ -411,6 +414,8 @@ public class GemFireHttpSessionConfiguration extends AbstractGemFireHttpSessionC * Callback with the {@link AnnotationMetadata} of the class containing {@link Import @Import} annotation * that imported this {@link Configuration @Configuration} class. * + * The {@link Configuration @Configuration} class should have been annotated with {@link EnableGemFireHttpSession}. + * * @param importMetadata {@link AnnotationMetadata} of the application class importing * this {@link Configuration} class. * @see org.springframework.core.type.AnnotationMetadata @@ -461,6 +466,7 @@ public class GemFireHttpSessionConfiguration extends AbstractGemFireHttpSessionC } private void configurePoolName(AnnotationAttributes enableGemFireHttpSessionAttributes) { + String defaultPoolName = enableGemFireHttpSessionAttributes.getString("poolName"); setPoolName(resolveProperty(poolNamePropertyName(), defaultPoolName)); @@ -471,8 +477,8 @@ public class GemFireHttpSessionConfiguration extends AbstractGemFireHttpSessionC RegionShortcut defaultServerRegionShortcut = enableGemFireHttpSessionAttributes.getEnum("serverRegionShortcut"); - setServerRegionShortcut(resolveProperty(serverRegionShortcutPropertyName(), - RegionShortcut.class, defaultServerRegionShortcut)); + setServerRegionShortcut(resolveProperty(serverRegionShortcutPropertyName(), RegionShortcut.class, + defaultServerRegionShortcut)); } private void configureSessionExpirationPolicyBeanName(AnnotationAttributes enableGemFireHttpSessionAttributes) { @@ -500,6 +506,20 @@ public class GemFireHttpSessionConfiguration extends AbstractGemFireHttpSessionC defaultSessionSerializerBeanName)); } + private void applySpringSessionGemFireConfigurer() { + + resolveSpringSessionGemFireConfigurer().ifPresent(configurer -> { + setClientRegionShortcut(configurer.getClientRegionShortcut()); + setIndexableSessionAttributes(configurer.getIndexableSessionAttributes()); + setMaxInactiveIntervalInSeconds(configurer.getMaxInactiveIntervalInSeconds()); + setPoolName(configurer.getPoolName()); + setServerRegionShortcut(configurer.getServerRegionShortcut()); + setSessionRegionName(configurer.getRegionName()); + setSessionExpirationPolicyBeanName(configurer.getSessionExpirationPolicyBeanName()); + setSessionSerializerBeanName(configurer.getSessionSerializerBeanName()); + }); + } + private Optional resolveSpringSessionGemFireConfigurer() { try { @@ -519,20 +539,6 @@ public class GemFireHttpSessionConfiguration extends AbstractGemFireHttpSessionC return (!(cause instanceof NoUniqueBeanDefinitionException) && cause instanceof NoSuchBeanDefinitionException); } - private void applySpringSessionGemFireConfigurer() { - - resolveSpringSessionGemFireConfigurer().ifPresent(configurer -> { - setClientRegionShortcut(configurer.getClientRegionShortcut()); - setIndexableSessionAttributes(configurer.getIndexableSessionAttributes()); - setMaxInactiveIntervalInSeconds(configurer.getMaxInactiveIntervalInSeconds()); - setPoolName(configurer.getPoolName()); - setServerRegionShortcut(configurer.getServerRegionShortcut()); - setSessionRegionName(configurer.getRegionName()); - setSessionExpirationPolicyBeanName(configurer.getSessionExpirationPolicyBeanName()); - setSessionSerializerBeanName(configurer.getSessionSerializerBeanName()); - }); - } - @PostConstruct public void init() { getBeanFactory().registerAlias(getSessionSerializerBeanName(), SESSION_SERIALIZER_BEAN_ALIAS); @@ -546,6 +552,26 @@ public class GemFireHttpSessionConfiguration extends AbstractGemFireHttpSessionC return new SessionExpirationTimeoutAwareBeanPostProcessor(expirationTimeout); } + @Bean + BeanPostProcessor sessionSerializerConfigurationBeanPostProcessor() { + + return new BeanPostProcessor() { + + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + + if (bean instanceof CacheFactoryBean) { + + SessionSerializer sessionSerializer = resolveSessionSerializer(); + + configureSerialization((CacheFactoryBean) bean, sessionSerializer); + } + + return bean; + } + }; + } + private Optional resolveSessionExpirationPolicy() { Optional sessionExpirationPolicyBeanName = getSessionExpirationPolicyBeanName(); @@ -568,26 +594,6 @@ public class GemFireHttpSessionConfiguration extends AbstractGemFireHttpSessionC return Optional.empty(); } - @Bean - BeanPostProcessor sessionSerializerConfigurationBeanPostProcessor() { - - return new BeanPostProcessor() { - - @Override - public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { - - if (bean instanceof CacheFactoryBean) { - - SessionSerializer sessionSerializer = resolveSessionSerializer(); - - configureSerialization((CacheFactoryBean) bean, sessionSerializer); - } - - return bean; - } - }; - } - private SessionSerializer resolveSessionSerializer() { return getApplicationContext().getBean(SESSION_SERIALIZER_BEAN_ALIAS, SessionSerializer.class); } @@ -623,11 +629,25 @@ public class GemFireHttpSessionConfiguration extends AbstractGemFireHttpSessionC } } + /** + * {@link SessionSerializer} bean implemented with Apache Geode/Pivotal GemFire DataSerialization framework. + * + * @return a DataSerialization {@link SessionSerializer} implementation. + * @see org.springframework.session.data.gemfire.serialization.data.provider.DataSerializableSessionSerializer + * @see org.springframework.session.data.gemfire.serialization.SessionSerializer + */ @Bean(SESSION_DATA_SERIALIZER_BEAN_NAME) public Object sessionDataSerializer() { return new DataSerializableSessionSerializer(); } + /** + * {@link SessionSerializer} bean implemented with Apache Geode/Pivotal GemFire PDX serialization framework. + * + * @return a PDX serialization {@link SessionSerializer} implementation. + * @see org.springframework.session.data.gemfire.serialization.pdx.provider.PdxSerializableSessionSerializer + * @see org.springframework.session.data.gemfire.serialization.SessionSerializer + */ @Bean(SESSION_PDX_SERIALIZER_BEAN_NAME) public Object sessionPdxSerializer() { return new PdxSerializableSessionSerializer(); @@ -693,16 +713,12 @@ public class GemFireHttpSessionConfiguration extends AbstractGemFireHttpSessionC regionAttributes.setStatisticsEnabled(true); - Optional sessionExpirationPolicy = resolveSessionExpirationPolicy(); + regionAttributes.setEntryIdleTimeout(new ExpirationAttributes( + Math.max(getMaxInactiveIntervalInSeconds(), 0), ExpirationAction.INVALIDATE)); - if (sessionExpirationPolicy.isPresent()) { - regionAttributes.setCustomEntryIdleTimeout(new SessionExpirationPolicyCustomExpiryAdapter( - sessionExpirationPolicy.get())); - } - else { - regionAttributes.setEntryIdleTimeout(new ExpirationAttributes( - Math.max(getMaxInactiveIntervalInSeconds(), 0), ExpirationAction.INVALIDATE)); - } + resolveSessionExpirationPolicy() + .map(SessionExpirationPolicyCustomExpiryAdapter::new) + .ifPresent(regionAttributes::setCustomEntryIdleTimeout); } else { getLogger().info("Expiration is not allowed on Regions with a data management policy of {}",