SGF-289 - Enumeration restrictions (xsd:enumeration) should be avoided in the XML schema.

Removed the XSD enumeration restriction on the 'type' attribute of the 'evictionType' XSD complex-type definition in the SDG XML namespace schema, which is used by the 'eviction' sub-elements in the LOCAL, PARTITION and REPLICATE Region element schema types.  In addition, created the ExpirationAttributesFactoryBean class in the org.springframework.data.gemfire package which serves as a Spring FactoryBean and builder for constructing GemFire EvictionAttributes used in Region configuration.  Updated tests to assert and validate the use of property placeholders on both the Eviction 'type' and Expiration 'action' attributes in the Spring Data GemFire XML namespace configuration meta-data.
This commit is contained in:
John Blum
2015-01-19 18:16:06 -08:00
parent 844c630614
commit 3f72ab8928
9 changed files with 278 additions and 54 deletions

View File

@@ -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);
}
}

View File

@@ -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;
/**

View File

@@ -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<ExpirationAttributes>, 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());
}
}

View File

@@ -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;
}