diff --git a/src/main/java/org/springframework/data/gemfire/CacheFactoryBean.java b/src/main/java/org/springframework/data/gemfire/CacheFactoryBean.java index e776648f..d368d562 100644 --- a/src/main/java/org/springframework/data/gemfire/CacheFactoryBean.java +++ b/src/main/java/org/springframework/data/gemfire/CacheFactoryBean.java @@ -912,8 +912,13 @@ public class CacheFactoryBean implements BeanClassLoaderAware, BeanFactoryAware, /* (non-Javadoc) */ private void initBeanFactory() { if (getBeanFactory() instanceof ConfigurableBeanFactory) { - ((ConfigurableBeanFactory) getBeanFactory()).registerCustomEditor(IndexMaintenanceType.class, - IndexMaintenanceTypeConverter.class); + ConfigurableBeanFactory beanFactory = (ConfigurableBeanFactory) getBeanFactory(); + + beanFactory.registerCustomEditor(EvictionType.class, EvictionTypeConverter.class); + beanFactory.registerCustomEditor(ExpirationActionType.class, ExpirationActionTypeConverter.class); + beanFactory.registerCustomEditor(IndexMaintenanceType.class, IndexMaintenanceTypeConverter.class); + beanFactory.registerCustomEditor(IndexType.class, IndexTypeConverter.class); + beanFactory.registerCustomEditor(SubscriptionType.class, SubscriptionTypeConverter.class); } } diff --git a/src/main/java/org/springframework/data/gemfire/ExpirationActionType.java b/src/main/java/org/springframework/data/gemfire/ExpirationActionType.java index db6b7953..6fdbbc50 100644 --- a/src/main/java/org/springframework/data/gemfire/ExpirationActionType.java +++ b/src/main/java/org/springframework/data/gemfire/ExpirationActionType.java @@ -32,6 +32,8 @@ public enum ExpirationActionType { LOCAL_DESTROY(ExpirationAction.LOCAL_DESTROY), LOCAL_INVALIDATE(ExpirationAction.LOCAL_INVALIDATE); + public static final ExpirationActionType DEFAULT = ExpirationActionType.INVALIDATE; + private final ExpirationAction expirationAction; /** diff --git a/src/main/java/org/springframework/data/gemfire/ExpirationAttributesFactoryBean.java b/src/main/java/org/springframework/data/gemfire/ExpirationAttributesFactoryBean.java new file mode 100644 index 00000000..96ccb313 --- /dev/null +++ b/src/main/java/org/springframework/data/gemfire/ExpirationAttributesFactoryBean.java @@ -0,0 +1,120 @@ +/* + * Copyright 2010-2013 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.data.gemfire; + +import org.springframework.beans.factory.FactoryBean; +import org.springframework.beans.factory.InitializingBean; + +import com.gemstone.gemfire.cache.ExpirationAttributes; + +/** + * The ExpirationAttributesFactoryBean class is a Spring FactoryBean used to create GemFire ExpirationAttributes + * to specify Expiration policies for Region Time-to-Live (TTL) and Idle-Timeouts (TTI) as well as + * Entry Time-to-Live (TTL) and Idle-Timeouts (TTI). + * + * @author John Blum + * @see org.springframework.beans.factory.FactoryBean + * @see org.springframework.beans.factory.InitializingBean + * @see com.gemstone.gemfire.cache.ExpirationAttributes + * @since 1.6.0 + */ +@SuppressWarnings("unused") +public class ExpirationAttributesFactoryBean implements FactoryBean, InitializingBean { + + protected static final int DEFAULT_TIMEOUT = 0; + + protected static final ExpirationActionType DEFAULT_EXPIRATION_ACTION = ExpirationActionType.DEFAULT; + + private ExpirationAttributes expirationAttributes; + + private Integer timeout; + + private ExpirationActionType action; + + /* non-Javadoc */ + @Override + public ExpirationAttributes getObject() throws Exception { + return expirationAttributes; + } + + /* non-Javadoc */ + @Override + public Class getObjectType() { + return (expirationAttributes != null ? expirationAttributes.getClass() : ExpirationAttributes.class); + } + + /* non-Javadoc */ + @Override + public boolean isSingleton() { + return true; + } + + /** + * Sets the action to perform when a Region or an Entry expire. + * + * @param action the type of action to perform on expiration + * @see org.springframework.data.gemfire.ExpirationActionType + */ + public void setAction(ExpirationActionType action) { + this.action = action; + } + + /** + * Gets the action to perform when a Region or an Entry expires. + * + * @return the type of action to perform on expiration. + * @see org.springframework.data.gemfire.ExpirationActionType + * @see com.gemstone.gemfire.cache.ExpirationAttributes#getAction() + */ + public ExpirationActionType getAction() { + return (action != null ? action : DEFAULT_EXPIRATION_ACTION); + } + + /** + * Sets the number of seconds before a Region or an Entry expires. + * + * @param timeout the number of seconds before a Region or an Entry expires. + */ + public void setTimeout(final Integer timeout) { + this.timeout = timeout; + } + + /** + * Gets the number of seconds before a Region or an Entry expires. + * + * @return the number of seconds before a Region or an Entry expires. + * @see com.gemstone.gemfire.cache.ExpirationAttributes#getTimeout() + */ + public int getTimeout() { + return (timeout != null ? timeout : DEFAULT_TIMEOUT); + } + + /** + * Initializes the GemFire ExpirationAttributes produced by this factory. + * + * @throws Exception if the construction of the ExpirationAttributes was not successful. + * @see #getAction() + * @see #getTimeout() + * @see org.springframework.data.gemfire.ExpirationActionType#getExpirationAction() + * @see com.gemstone.gemfire.cache.ExpirationAttributes + */ + @Override + public void afterPropertiesSet() throws Exception { + expirationAttributes = new ExpirationAttributes(getTimeout(), getAction().getExpirationAction()); + } + +} diff --git a/src/main/java/org/springframework/data/gemfire/config/ParsingUtils.java b/src/main/java/org/springframework/data/gemfire/config/ParsingUtils.java index 0061448f..86d85cda 100644 --- a/src/main/java/org/springframework/data/gemfire/config/ParsingUtils.java +++ b/src/main/java/org/springframework/data/gemfire/config/ParsingUtils.java @@ -26,9 +26,9 @@ import org.springframework.beans.factory.support.ManagedList; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.core.Conventions; import org.springframework.data.gemfire.EvictionAttributesFactoryBean; -import org.springframework.data.gemfire.EvictionType; import org.springframework.data.gemfire.ExpirationActionType; import org.springframework.data.gemfire.ExpirationActionTypeConverter; +import org.springframework.data.gemfire.ExpirationAttributesFactoryBean; import org.springframework.data.gemfire.GemfireUtils; import org.springframework.data.gemfire.SubscriptionAttributesFactoryBean; import org.springframework.data.gemfire.SubscriptionType; @@ -198,10 +198,10 @@ abstract class ParsingUtils { setPropertyValue(evictionElement, evictionAttributesBuilder, "action"); setPropertyValue(evictionElement, evictionAttributesBuilder, "threshold"); - String evictionType = evictionElement.getAttribute("type"); + String typeAttributeValue = evictionElement.getAttribute("type"); - if (StringUtils.hasText(evictionType)) { - evictionAttributesBuilder.addPropertyValue("type", EvictionType.valueOf(evictionType.toUpperCase())); + if (StringUtils.hasText(typeAttributeValue)) { + evictionAttributesBuilder.addPropertyValue("type", StringUtils.trimWhitespace(typeAttributeValue)); } Element objectSizerElement = DomUtils.getChildElementByTagName(evictionElement, "object-sizer"); @@ -212,7 +212,8 @@ abstract class ParsingUtils { evictionAttributesBuilder.addPropertyValue("ObjectSizer", sizer); } - regionAttributesBuilder.addPropertyValue("evictionAttributes", evictionAttributesBuilder.getBeanDefinition()); + regionAttributesBuilder.addPropertyValue("evictionAttributes", + evictionAttributesBuilder.getBeanDefinition()); return true; } @@ -263,8 +264,8 @@ abstract class ParsingUtils { } } - static void parseStatistics(Element element, BeanDefinitionBuilder attrBuilder) { - setPropertyValue(element, attrBuilder, "statistics", "statisticsEnabled"); + static void parseStatistics(Element element, BeanDefinitionBuilder regionAttributesBuilder) { + setPropertyValue(element, regionAttributesBuilder, "statistics", "statisticsEnabled"); } /** @@ -379,23 +380,19 @@ abstract class ParsingUtils { private static boolean parseExpiration(Element rootElement, String elementName, String propertyName, BeanDefinitionBuilder regionAttributesBuilder) { + Element expirationElement = DomUtils.getChildElementByTagName(rootElement, elementName); if (expirationElement != null) { - String timeoutAttribute = expirationElement.getAttribute("timeout"); - String expirationTimeout = (StringUtils.hasText(timeoutAttribute) ? timeoutAttribute : "0"); + String actionAttributeValue = expirationElement.getAttribute("action"); + String timeoutAttributeValue = expirationElement.getAttribute("timeout"); - String actionAttribute = StringUtils.trimAllWhitespace(expirationElement.getAttribute("action")); + BeanDefinitionBuilder expirationAttributesBuilder = BeanDefinitionBuilder.genericBeanDefinition( + ExpirationAttributesFactoryBean.class); - ExpirationActionType expirationActionType = new ExpirationActionTypeConverter().convert(actionAttribute); - ExpirationAction expirationAction = (expirationActionType != null - ? expirationActionType.getExpirationAction() : ExpirationAction.INVALIDATE); - - BeanDefinitionBuilder expirationAttributes = BeanDefinitionBuilder.genericBeanDefinition( - ExpirationAttributes.class); - expirationAttributes.addConstructorArgValue(expirationTimeout); - expirationAttributes.addConstructorArgValue(expirationAction); - regionAttributesBuilder.addPropertyValue(propertyName, expirationAttributes.getBeanDefinition()); + expirationAttributesBuilder.addPropertyValue("action", actionAttributeValue); + expirationAttributesBuilder.addPropertyValue("timeout", timeoutAttributeValue); + regionAttributesBuilder.addPropertyValue(propertyName, expirationAttributesBuilder.getBeanDefinition()); return true; } diff --git a/src/main/resources/org/springframework/data/gemfire/config/spring-gemfire-1.6.xsd b/src/main/resources/org/springframework/data/gemfire/config/spring-gemfire-1.6.xsd index 94d5baad..612d7b80 100644 --- a/src/main/resources/org/springframework/data/gemfire/config/spring-gemfire-1.6.xsd +++ b/src/main/resources/org/springframework/data/gemfire/config/spring-gemfire-1.6.xsd @@ -1603,38 +1603,20 @@ Entity computing sizes for objects stored into the grid. - - - - - - - - - - - - - - - - - - - - + + + + diff --git a/src/test/java/org/springframework/data/gemfire/ExpirationActionTypeTest.java b/src/test/java/org/springframework/data/gemfire/ExpirationActionTypeTest.java index 681624e8..e5c325e6 100644 --- a/src/test/java/org/springframework/data/gemfire/ExpirationActionTypeTest.java +++ b/src/test/java/org/springframework/data/gemfire/ExpirationActionTypeTest.java @@ -35,6 +35,12 @@ import com.gemstone.gemfire.cache.ExpirationAction; */ public class ExpirationActionTypeTest { + @Test + public void testDefault() { + assertEquals(ExpirationActionType.INVALIDATE, ExpirationActionType.DEFAULT); + assertEquals(ExpirationAction.INVALIDATE, ExpirationActionType.DEFAULT.getExpirationAction()); + } + @Test public void testValueOf() { assertEquals(ExpirationActionType.DESTROY, ExpirationActionType.valueOf(ExpirationAction.DESTROY)); diff --git a/src/test/java/org/springframework/data/gemfire/ExpirationAttributesFactoryBeanTest.java b/src/test/java/org/springframework/data/gemfire/ExpirationAttributesFactoryBeanTest.java new file mode 100644 index 00000000..8445cb10 --- /dev/null +++ b/src/test/java/org/springframework/data/gemfire/ExpirationAttributesFactoryBeanTest.java @@ -0,0 +1,96 @@ +/* + * Copyright 2010-2013 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.data.gemfire; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import com.gemstone.gemfire.cache.ExpirationAction; +import com.gemstone.gemfire.cache.ExpirationAttributes; + +/** + * The ExpirationAttributesFactoryBeanTest class is a test suite of test cases testing the contract and functionality + * of the ExpirationAttributesFactoryBean class. + * + * @author John Blum + * @see org.junit.Test + * @see org.springframework.data.gemfire.ExpirationAttributesFactoryBean + * @since 1.6.0 + */ +public class ExpirationAttributesFactoryBeanTest { + + @Test + public void testIsSingleton() { + assertTrue(new ExpirationAttributesFactoryBean().isSingleton()); + } + + @Test + public void testSetAndGetAction() { + ExpirationAttributesFactoryBean expirationAttributesFactoryBean = new ExpirationAttributesFactoryBean(); + + assertEquals(ExpirationAttributesFactoryBean.DEFAULT_EXPIRATION_ACTION, + expirationAttributesFactoryBean.getAction()); + + expirationAttributesFactoryBean.setAction(ExpirationActionType.LOCAL_DESTROY); + + assertEquals(ExpirationActionType.LOCAL_DESTROY, expirationAttributesFactoryBean.getAction()); + + expirationAttributesFactoryBean.setAction(null); + + assertEquals(ExpirationAttributesFactoryBean.DEFAULT_EXPIRATION_ACTION, + expirationAttributesFactoryBean.getAction()); + } + + @Test + public void testSetAndGetTimeout() { + ExpirationAttributesFactoryBean expirationAttributesFactoryBean = new ExpirationAttributesFactoryBean(); + + assertEquals(0, expirationAttributesFactoryBean.getTimeout()); + + expirationAttributesFactoryBean.setTimeout(60000); + + assertEquals(60000, expirationAttributesFactoryBean.getTimeout()); + + expirationAttributesFactoryBean.setTimeout(null); + + assertEquals(0, expirationAttributesFactoryBean.getTimeout()); + } + + @Test + public void testAfterPropertiesSet() throws Exception { + ExpirationAttributesFactoryBean expirationAttributesFactoryBean = new ExpirationAttributesFactoryBean(); + + assertNull(expirationAttributesFactoryBean.getObject()); + assertEquals(ExpirationAttributes.class, expirationAttributesFactoryBean.getObjectType()); + + expirationAttributesFactoryBean.setAction(ExpirationActionType.DESTROY); + expirationAttributesFactoryBean.setTimeout(8192); + expirationAttributesFactoryBean.afterPropertiesSet(); + + ExpirationAttributes expirationAttributes = expirationAttributesFactoryBean.getObject(); + + assertNotNull(expirationAttributes); + assertEquals(ExpirationAction.DESTROY, expirationAttributes.getAction()); + assertEquals(8192, expirationAttributes.getTimeout()); + assertEquals(expirationAttributes.getClass(), expirationAttributesFactoryBean.getObjectType()); + } + +} diff --git a/src/test/resources/org/springframework/data/gemfire/config/RegionEvictionAttributesNamespaceTest-context.xml b/src/test/resources/org/springframework/data/gemfire/config/RegionEvictionAttributesNamespaceTest-context.xml index 385654fe..e84b8bdc 100644 --- a/src/test/resources/org/springframework/data/gemfire/config/RegionEvictionAttributesNamespaceTest-context.xml +++ b/src/test/resources/org/springframework/data/gemfire/config/RegionEvictionAttributesNamespaceTest-context.xml @@ -1,14 +1,22 @@ + + heap_percentage + + + + RegionEvictionAttributesNamespaceTest 0 @@ -26,11 +34,11 @@ - + - + diff --git a/src/test/resources/org/springframework/data/gemfire/config/RegionExpirationAttributesNamespaceTest-context.xml b/src/test/resources/org/springframework/data/gemfire/config/RegionExpirationAttributesNamespaceTest-context.xml index 29fa02f3..c703e633 100644 --- a/src/test/resources/org/springframework/data/gemfire/config/RegionExpirationAttributesNamespaceTest-context.xml +++ b/src/test/resources/org/springframework/data/gemfire/config/RegionExpirationAttributesNamespaceTest-context.xml @@ -1,15 +1,23 @@ + + Destroy + + + + RegionExpirationAttributesNamespaceTest 0 @@ -19,20 +27,20 @@ - + - +