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:
@@ -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 {
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user