SGF-404 - Enable Expiration settings and policies to be specified per application domain object using an @Expiration annotation and a custom, SDG-provided CustomExpiry instance.

Added support for Spring Property Placeholders in the @Expiration annotation attributes to offer even more flexibility when configuring Region Entry values, application domain object Expiration policies and settings.
(cherry picked from commit 92f3c4e80839ed4034fe3229c68aebf90091c9a1)

Signed-off-by: John Blum <jblum@pivotal.io>
This commit is contained in:
John Blum
2015-07-31 00:57:49 -07:00
parent f07c6990a4
commit 6264b93c7d
3 changed files with 180 additions and 27 deletions

View File

@@ -55,6 +55,9 @@ import com.gemstone.gemfire.cache.Region;
* @see org.springframework.data.gemfire.test.GemfireTestApplicationContextInitializer
* @see org.springframework.test.context.ContextConfiguration
* @see org.springframework.test.context.junit4.SpringJUnit4ClassRunner
* @see com.gemstone.gemfire.cache.CustomExpiry
* @see com.gemstone.gemfire.cache.ExpirationAction
* @see com.gemstone.gemfire.cache.ExpirationAttributes
* @since 1.7.0
*/
@RunWith(SpringJUnit4ClassRunner.class)
@@ -187,8 +190,8 @@ public class AnnotationBasedExpirationConfigurationIntegrationTest {
protected static class ApplicationDomainObjectWithNoExpirationPolicy {
}
@TimeToLiveExpiration(timeout = "@expirationProperties['gemfire.region.entry.expiration.timeout']",
action = "@expirationProperties['gemfire.region.entry.expiration.action.string']")
@TimeToLiveExpiration(timeout = "${gemfire.region.entry.expiration.timeout}",
action = "${gemfire.region.entry.expiration.action.string}")
protected static class RegionEntryTimeToLiveExpirationPolicy {
}
@@ -197,7 +200,7 @@ public class AnnotationBasedExpirationConfigurationIntegrationTest {
protected static class RegionEntryIdleTimeoutExpirationPolicy {
}
@Expiration(timeout = "@expirationProperties['gemfire.region.entry.expiration.timeout']",
@Expiration(timeout = "${gemfire.region.entry.expiration.timeout}",
action = "@expirationProperties['gemfire.region.entry.expiration.action.spring.type']")
protected static class RegionEntryGenericExpirationPolicy {
}

View File

@@ -17,13 +17,16 @@
package org.springframework.data.gemfire.support;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.isA;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.CoreMatchers.sameInstance;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -31,7 +34,19 @@ import static org.mockito.Mockito.when;
import static org.springframework.data.gemfire.support.AnnotationBasedExpiration.ExpirationMetaData;
import org.junit.Test;
import org.mockito.Matchers;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.gemfire.ExpirationActionType;
import org.springframework.data.gemfire.TestUtils;
import org.springframework.expression.BeanResolver;
import org.springframework.expression.PropertyAccessor;
import org.springframework.expression.TypeConverter;
import org.springframework.expression.TypeLocator;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import com.gemstone.gemfire.cache.ExpirationAction;
import com.gemstone.gemfire.cache.ExpirationAttributes;
@@ -146,6 +161,51 @@ public class AnnotationBasedExpirationTest {
verify(mockRegionEntry, atLeast(3)).getValue();
}
@Test
public void setAndGetBeanFactory() {
final StandardEvaluationContext mockEvaluationContext = mock(StandardEvaluationContext.class,
"MockStandardEvaluationContext");
ConversionService mockConversionService = mock(ConversionService.class, "MockConversionService");
final ConfigurableBeanFactory mockBeanFactory = mock(ConfigurableBeanFactory.class, "MockBeanFactory");
when(mockBeanFactory.getConversionService()).thenReturn(mockConversionService);
when(mockBeanFactory.getBeanClassLoader()).thenReturn(Thread.currentThread().getContextClassLoader());
doAnswer(new Answer<Void>() {
@Override public Void answer(final InvocationOnMock invocation) throws Throwable {
BeanResolver beanResolver = invocation.getArgumentAt(0, BeanResolver.class);
assertThat(beanResolver, is(instanceOf(BeanFactoryResolver.class)));
assertThat(TestUtils.<ConfigurableBeanFactory>readField("beanFactory", beanResolver),
is(equalTo(mockBeanFactory)));
return null;
}
}).when(mockEvaluationContext).setBeanResolver(Matchers.any(BeanResolver.class));
AnnotationBasedExpiration<Object, Object> annotationBasedExpiration = new AnnotationBasedExpiration<Object, Object>() {
@Override StandardEvaluationContext newEvaluationContext() {
return mockEvaluationContext;
}
};
annotationBasedExpiration.setBeanFactory(mockBeanFactory);
assertSame(mockBeanFactory, annotationBasedExpiration.getBeanFactory());
verify(mockEvaluationContext, times(3)).addPropertyAccessor(Matchers.any(PropertyAccessor.class));
verify(mockEvaluationContext, times(1)).setTypeConverter(Matchers.any(TypeConverter.class));
verify(mockEvaluationContext, times(1)).setTypeLocator(Matchers.any(TypeLocator.class));
verify(mockEvaluationContext, times(1)).setBeanResolver(Matchers.any(BeanResolver.class));
verify(mockBeanFactory, times(1)).getConversionService();
verify(mockBeanFactory, times(1)).getBeanClassLoader();
}
@Test(expected = IllegalStateException.class)
public void getUninitializedBeanFactory() {
new AnnotationBasedExpiration<Object, Object>().getBeanFactory();
}
@Test
public void setAndGetDefaultExpirationAttributes() {
ExpirationAttributes expectedExpirationAttributes = new ExpirationAttributes(120, ExpirationAction.INVALIDATE);