Fixes bug SGF-225 involving GemFire SubRegion bean definition inconsistencies when data-policy is specified along with SGF-242 that involves the use of membership-attributes configuration on a GemFire Region.

This commit is contained in:
John Blum
2013-12-06 16:17:07 -08:00
parent bccf918b72
commit 101d977026
23 changed files with 850 additions and 494 deletions

View File

@@ -77,6 +77,8 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
private Object[] asyncEventQueues;
private Object[] gatewaySenders;
private Region<?, ?> parent;
private RegionAttributes<K, V> attributes;
private Resource snapshot;
@@ -103,11 +105,11 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
AttributesFactory.validateAttributes(attributes);
}
final RegionFactory<K, V> regionFactory = (attributes != null ? cache.createRegionFactory(attributes) :
cache.<K, V> createRegionFactory());
RegionFactory<K, V> regionFactory = (attributes != null ? cache.createRegionFactory(attributes)
: cache.<K, V>createRegionFactory());
if (hubId != null) {
enableGateway = enableGateway == null ? true : enableGateway;
enableGateway = (enableGateway == null || enableGateway);
Assert.isTrue(enableGateway, "hubId requires the enableGateway property to be true");
regionFactory.setGatewayHubId(hubId);
@@ -115,20 +117,15 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
if (enableGateway != null) {
if (enableGateway) {
Assert.notNull(hubId, "enableGateway requires the hubId property to be true");
Assert.notNull(hubId, "The 'enableGateway' property requires the 'hubId' property to be set.");
}
regionFactory.setEnableGateway(enableGateway);
}
if (!ObjectUtils.isEmpty(cacheListeners)) {
for (CacheListener<K, V> listener : cacheListeners) {
regionFactory.addCacheListener(listener);
}
}
if (!ObjectUtils.isEmpty(gatewaySenders)) {
Assert.isTrue(hubId == null, "It is invalid to configure a region with both a hubId and gatewaySenders."
+ " Note that the enableGateway and hubId properties are deprecated since Gemfire 7.0");
for (Object gatewaySender : gatewaySenders) {
regionFactory.addGatewaySenderId(((GatewaySender) gatewaySender).getId());
}
@@ -140,6 +137,12 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
}
}
if (!ObjectUtils.isEmpty(cacheListeners)) {
for (CacheListener<K, V> listener : cacheListeners) {
regionFactory.addCacheListener(listener);
}
}
if (cacheLoader != null) {
regionFactory.setCacheLoader(cacheLoader);
}
@@ -164,10 +167,20 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
}
// get underlying AttributesFactory
postProcess(findAttrFactory(regionFactory));
postProcess(findAttributesFactory(regionFactory));
Region<K, V> region = regionFactory.create(regionName);
log.info("Created new cache region [" + regionName + "]");
Region<K, V> region = (this.parent != null ? regionFactory.createSubregion(parent, regionName)
: regionFactory.create(regionName));
if (log.isInfoEnabled()) {
if (parent != null) {
log.info(String.format("Created new Cache sub-Region [%1$s] under parent Region [%2$s].",
regionName, parent.getName()));
}
else {
log.info(String.format("Created new Cache Region [%1$s].", regionName));
}
}
if (snapshot != null) {
region.loadSnapshot(snapshot.getInputStream());
@@ -205,7 +218,7 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
}
@SuppressWarnings("unchecked")
private AttributesFactory<K, V> findAttrFactory(RegionFactory<K, V> regionFactory) {
private AttributesFactory<K, V> findAttributesFactory(RegionFactory<K, V> regionFactory) {
Field attrsFactoryField = ReflectionUtils.findField(RegionFactory.class, "attrsFactory",
AttributesFactory.class);
ReflectionUtils.makeAccessible(attrsFactoryField);
@@ -218,12 +231,13 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
* already initialized and configured by the factory bean before this method
* is invoked.
*
* @param attrFactory attribute factory
* @param attributesFactory attribute factory
* @deprecated as of GemFire 6.5, the use of {@link AttributesFactory} has
* been deprecated
*/
@Deprecated
protected void postProcess(AttributesFactory<K, V> attrFactory) {
@SuppressWarnings("unused")
protected void postProcess(AttributesFactory<K, V> attributesFactory) {
}
/**
@@ -233,6 +247,7 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
*
* @param region
*/
@SuppressWarnings("unused")
protected void postProcess(Region<K, V> region) {
}
@@ -244,17 +259,38 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
if (!getRegion().getRegionService().isClosed()) {
try {
getRegion().close();
} catch (Exception cce) {
// nothing to see folks, move on.
}
catch (Exception ignore) {
}
}
} if (destroy) {
}
if (destroy) {
getRegion().destroyRegion();
}
}
}
/**
*
* @param asyncEventQueues defined as Object for backward compatibility with
* Gemfire 6
*/
public void setAsyncEventQueues(Object[] asyncEventQueues) {
this.asyncEventQueues = asyncEventQueues;
}
/**
* Sets the region attributes used for the region used by this factory.
* Allows maximum control in specifying the region settings. Used only when
* a new region is created.
*
* @param attributes the attributes to set on a newly created region
*/
public void setAttributes(RegionAttributes<K, V> attributes) {
this.attributes = attributes;
}
/**
* Indicates whether the region referred by this factory bean, will be
* closed on shutdown (default true).
@@ -263,26 +299,6 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
this.close = close;
}
/**
* Indicates whether the region referred by this factory bean, will be
* destroyed on shutdown (default false).
*/
public void setDestroy(boolean destroy) {
this.destroy = destroy;
}
/**
* Sets the snapshots used for loading a newly <i>created</i> region. That
* is, the snapshot will be used <i>only</i> when a new region is created -
* if the region already exists, no loading will be performed.
*
* @see #setName(String)
* @param snapshot the snapshot to set
*/
public void setSnapshot(Resource snapshot) {
this.snapshot = snapshot;
}
/**
* Sets the cache listeners used for the region used by this factory. Used
* only when a new region is created.Overrides the settings specified
@@ -317,18 +333,11 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
}
/**
* Sets the region scope. Used only when a new region is created. Overrides
* the settings specified through {@link #setAttributes(RegionAttributes)}.
*
* @see Scope
* @param scope the region scope
* Indicates whether the region referred by this factory bean, will be
* destroyed on shutdown (default false).
*/
public void setScope(Scope scope) {
this.scope = scope;
}
public void setPersistent(boolean persistent) {
this.persistent = persistent;
public void setDestroy(boolean destroy) {
this.destroy = destroy;
}
/**
@@ -348,6 +357,10 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
this.diskStoreName = diskStoreName;
}
public void setEnableGateway(boolean enableGateway) {
this.enableGateway = enableGateway;
}
/**
*
* @param gatewaySenders defined as Object for backward compatibility with
@@ -357,32 +370,39 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
this.gatewaySenders = gatewaySenders;
}
/**
*
* @param asyncEventQueues defined as Object for backward compatibility with
* Gemfire 6
*/
public void setAsyncEventQueues(Object[] asyncEventQueues) {
this.asyncEventQueues = asyncEventQueues;
}
public void setEnableGateway(boolean enableGateway) {
this.enableGateway = enableGateway;
}
public void setHubId(String hubId) {
this.hubId = hubId;
}
public void setParent(Region<?, ?> parent) {
this.parent = parent;
}
public void setPersistent(boolean persistent) {
this.persistent = persistent;
}
/**
* Sets the region attributes used for the region used by this factory.
* Allows maximum control in specifying the region settings. Used only when
* a new region is created.
* Sets the region scope. Used only when a new region is created. Overrides
* the settings specified through {@link #setAttributes(RegionAttributes)}.
*
* @param attributes the attributes to set on a newly created region
* @see Scope
* @param scope the region scope
*/
public void setAttributes(RegionAttributes<K, V> attributes) {
this.attributes = attributes;
public void setScope(Scope scope) {
this.scope = scope;
}
/**
* Sets the snapshots used for loading a newly <i>created</i> region. That
* is, the snapshot will be used <i>only</i> when a new region is created -
* if the region already exists, no loading will be performed.
*
* @see #setName(String)
* @param snapshot the snapshot to set
*/
public void setSnapshot(Resource snapshot) {
this.snapshot = snapshot;
}
/**

View File

@@ -29,11 +29,11 @@ import com.gemstone.gemfire.cache.GemFireCache;
import com.gemstone.gemfire.cache.Region;
/**
* Simple FactoryBean for retrieving generic GemFire {@link Region}s. If the region doesn't exist, an exception is thrown.
*
* For declaring and configuring new regions, see {@link RegionFactoryBean}.
*
* Simple FactoryBean for retrieving generic GemFire {@link Region}s. If the Region does not exist,
* an exception is thrown. For declaring and configuring new regions, see {@link RegionFactoryBean}.
* <p/>
* @author Costin Leau
* @author John Blum
*/
public class RegionLookupFactoryBean<K, V> implements FactoryBean<Region<K, V>>, InitializingBean, BeanNameAware {
@@ -45,21 +45,24 @@ public class RegionLookupFactoryBean<K, V> implements FactoryBean<Region<K, V>>,
private String beanName;
private String name;
private String regionName;
public void afterPropertiesSet() throws Exception {
Assert.notNull(cache, "Cache property must be set");
Assert.notNull(cache, "The 'cache' property must be set.");
name = (StringUtils.hasText(name) ? name : beanName);
Assert.hasText(name, "The 'name' or 'beanName' property must be set.");
String regionName = (StringUtils.hasText(this.regionName) ? this.regionName
: (StringUtils.hasText(name) ? name : beanName));
Assert.hasText(regionName, "The 'regionName', 'name' or 'beanName' property must be set.");
synchronized (cache) {
region = cache.getRegion(name);
region = cache.getRegion(regionName);
if (region != null) {
log.info(String.format("Retrieved region [%1$s] from cache [%2$s].", name, cache.getName()));
log.info(String.format("Retrieved Region [%1$s] from Cache [%2$s].", regionName, cache.getName()));
}
else {
region = lookupFallback(cache, name);
region = lookupFallback(cache, regionName);
}
}
}
@@ -73,7 +76,8 @@ public class RegionLookupFactoryBean<K, V> implements FactoryBean<Region<K, V>>,
* @throws Exception
*/
protected Region<K, V> lookupFallback(GemFireCache cache, String regionName) throws Exception {
throw new BeanInitializationException("Cannot find region [" + regionName + "] in cache " + cache);
throw new BeanInitializationException(String.format("Cannot find Region [%1$s] in Cache [%2$s].",
regionName, cache));
}
public Region<K, V> getObject() throws Exception {
@@ -88,34 +92,52 @@ public class RegionLookupFactoryBean<K, V> implements FactoryBean<Region<K, V>>,
return true;
}
/**
* Sets the name of the Cache Region based on the bean 'id' attribute. If no Region is found for the given name,
* a new one will be created.
* <p/>
* @param name the name of this bean (Region) in the application context (bean factory).
* @see org.springframework.beans.factory.BeanNameAware#setBeanName(String)
*/
public void setBeanName(String name) {
this.beanName = name;
}
/**
* Sets the cache used for creating the region.
*
* Sets a reference to the Cache used to create the Region.
* <p/>
* @param cache a reference to the Cache.
* @see org.springframework.data.gemfire.CacheFactoryBean
* @param cache the cache to set
* @see com.gemstone.gemfire.cache.GemFireCache
*/
public void setCache(GemFireCache cache) {
this.cache = cache;
}
/**
* Sets the name of the cache region. If no cache is found under
* the given name, a new one will be created.
* If no name is given, the beanName will be used.
*
* @see com.gemstone.gemfire.cache.Region#getFullPath()
* @see #setBeanName(String)
*
* Sets the name of the Cache Region based on the bean 'name' attribute. If no Region is found with the given name,
* a new one will be created. If no name is given, the value of the 'beanName' property will be used.
* <p/>
* @param name the region name
* @see #setBeanName(String)
* @see com.gemstone.gemfire.cache.Region#getFullPath()
*/
public void setName(String name) {
this.name = name;
}
/**
* Sets the name of the Cache Region as expected by GemFire. If no Region is found with the given name, a new one
* will be created. If no name is given, the value of the 'name' property will be used.
* <p/>
* @param regionName a String indicating the name of the Region in GemFire.
* @see #setName(String)
* @see com.gemstone.gemfire.cache.Region#getName()
*/
public void setRegionName(String regionName) {
this.regionName = regionName;
}
protected Region<K, V> getRegion() {
return region;
}

View File

@@ -33,19 +33,19 @@ public class ReplicatedRegionFactoryBean<K, V> extends RegionFactoryBean<K, V> {
Assert.notNull(resolvedDataPolicy, String.format("Data Policy '%1$s' is invalid.", dataPolicy));
// Validate that the data-policy and persistent attributes are compatible when specified!
assertDataPolicyAndPersistentAttributesAreCompatible(resolvedDataPolicy);
if (DataPolicy.EMPTY.equals(resolvedDataPolicy)) {
resolvedDataPolicy = DataPolicy.EMPTY;
}
else {
// Validate that the user-defined Data Policy matches the appropriate Spring GemFire XML namespace
// configuration meta-data element for Region (i.e. <gfe:replicated-region .../>)!
Assert.isTrue(resolvedDataPolicy.withReplication(), String.format("" +
Assert.isTrue(resolvedDataPolicy.withReplication(), String.format(
"Data Policy '%1$s' is not supported in Replicated Regions.", resolvedDataPolicy));
}
// Validate that the data-policy and persistent attributes are compatible when specified!
assertDataPolicyAndPersistentAttributesAreCompatible(resolvedDataPolicy);
regionFactory.setDataPolicy(resolvedDataPolicy);
}
else {

View File

@@ -29,16 +29,18 @@ import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.asyncqueue.AsyncEventQueue;
import com.gemstone.gemfire.cache.wan.GatewaySender;
@SuppressWarnings("deprecation")
/**
* FactoryBean for creating a Gemfire Region as a sub-Region.
* FactoryBean for creating a Gemfire sub-Regions.
* <p/>
* @author David Turanski
* @author John Blum
* @param <K> - Region Key Type
* @param <V> - Region Value Type
* @param <K> Region Key Type
* @param <V> Region Value Type
* @deprecated as Spring Data GemFire 1.4.0. Use Region type specific FactoryBeans
* (e.g. ReplicatedRegionFactoryBean) instead.
*/
// TODO why does this class extend the com.gemstone.gemfire.cache.AttributesFactory class? AttributesFactory is deprecated!
@Deprecated
@SuppressWarnings("deprecation")
public class SubRegionFactoryBean<K, V> extends AttributesFactory<K, V> implements FactoryBean<Region<K, V>>,
InitializingBean {

View File

@@ -29,7 +29,6 @@ import org.springframework.beans.factory.support.ManagedArray;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.data.gemfire.GemfireUtils;
import org.springframework.data.gemfire.SubRegionFactoryBean;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
@@ -46,7 +45,7 @@ abstract class AbstractRegionParser extends AbstractSingleBeanDefinitionParser {
@Override
protected Class<?> getBeanClass(Element element) {
return (isSubRegion(element) ? SubRegionFactoryBean.class : getRegionFactoryClass());
return getRegionFactoryClass();
}
protected abstract Class<?> getRegionFactoryClass();
@@ -67,45 +66,45 @@ abstract class AbstractRegionParser extends AbstractSingleBeanDefinitionParser {
boolean subRegion);
protected void doParseCommonRegionConfiguration(Element element, ParserContext parserContext,
BeanDefinitionBuilder builder, BeanDefinitionBuilder attrBuilder, boolean subRegion) {
BeanDefinitionBuilder builder, BeanDefinitionBuilder regionAttributesBuilder, boolean subRegion) {
String cacheRef = element.getAttribute("cache-ref");
String resolvedCacheRef = (StringUtils.hasText(cacheRef) ? cacheRef
: GemfireConstants.DEFAULT_GEMFIRE_CACHE_NAME);
if (!subRegion) {
String cacheRef = element.getAttribute("cache-ref");
// add cache reference (fallback to default if nothing is specified)
builder.addPropertyReference("cache", (StringUtils.hasText(cacheRef) ? cacheRef : GemfireConstants.DEFAULT_GEMFIRE_CACHE_NAME));
builder.addPropertyReference("cache", resolvedCacheRef);
ParsingUtils.setPropertyValue(element, builder, "close");
ParsingUtils.setPropertyValue(element, builder, "destroy");
}
// add attributes
ParsingUtils.setPropertyValue(element, builder, "name");
ParsingUtils.parseOptionalRegionAttributes(parserContext, element, attrBuilder);
ParsingUtils.parseStatistics(element, attrBuilder);
ParsingUtils.setPropertyValue(element, attrBuilder, "publisher");
if (!isSubRegion(element)) {
ParsingUtils.setPropertyValue(element, builder, "persistent");
}
// set the data policy
ParsingUtils.setPropertyValue(element, builder, "name");
ParsingUtils.setPropertyValue(element, builder, "data-policy");
ParsingUtils.setPropertyValue(element, builder, "persistent");
ParsingUtils.setPropertyValue(element, regionAttributesBuilder, "publisher");
if (StringUtils.hasText(element.getAttribute("disk-store-ref"))) {
ParsingUtils.setPropertyValue(element, builder, "disk-store-ref", "diskStoreName");
builder.addDependsOn(element.getAttribute("disk-store-ref"));
}
ParsingUtils.parseExpiration(parserContext, element, attrBuilder);
ParsingUtils.parseSubscription(parserContext, element, attrBuilder);
ParsingUtils.parseEviction(parserContext, element, attrBuilder);
ParsingUtils.parseMembershipAttributes(parserContext, element, attrBuilder);
ParsingUtils.parseOptionalRegionAttributes(parserContext, element, regionAttributesBuilder);
ParsingUtils.parseStatistics(element, regionAttributesBuilder);
ParsingUtils.parseExpiration(parserContext, element, regionAttributesBuilder);
ParsingUtils.parseSubscription(parserContext, element, regionAttributesBuilder);
ParsingUtils.parseEviction(parserContext, element, regionAttributesBuilder);
ParsingUtils.parseMembershipAttributes(parserContext, element, regionAttributesBuilder);
String enableGateway = element.getAttribute("enable-gateway");
String hubId = element.getAttribute("hub-id");
// Factory will enable gateway if it is not set and hub-id is set.
if (StringUtils.hasText(enableGateway)) {
if (GemfireUtils.isGemfireVersion7OrAbove()) {
log.warn("'enable-gateway' is deprecated since Gemfire 7.0");
}
}
ParsingUtils.setPropertyValue(element, builder, "enable-gateway");
if (StringUtils.hasText(hubId)) {
@@ -117,16 +116,16 @@ abstract class AbstractRegionParser extends AbstractSingleBeanDefinitionParser {
element);
}
}
ParsingUtils.setPropertyValue(element, builder, "hub-id");
// Parse child elements
parseCollectionOfCustomSubElements(parserContext, element, builder,
"com.gemstone.gemfire.cache.wan.GatewaySender", "gateway-sender","gatewaySenders");
parseCollectionOfCustomSubElements(parserContext, element, builder,
"com.gemstone.gemfire.cache.asyncqueue.AsyncEventQueue", "async-event-queue", "asyncEventQueues");
parseCollectionOfCustomSubElements(element, parserContext, builder,
"com.gemstone.gemfire.cache.asyncqueue.AsyncEventQueue", "async-event-queue", "asyncEventQueues");
parseCollectionOfCustomSubElements(element, parserContext, builder,
"com.gemstone.gemfire.cache.wan.GatewaySender", "gateway-sender","gatewaySenders");
List<Element> subElements = DomUtils.getChildElements(element);
for (Element subElement : subElements) {
if (subElement.getLocalName().equals("cache-listener")) {
builder.addPropertyValue("cacheListeners",
@@ -143,43 +142,47 @@ abstract class AbstractRegionParser extends AbstractSingleBeanDefinitionParser {
}
if (!subRegion) {
Map<String, Element> allSubRegionElements = new HashMap<String, Element>();
findSubregionElements(element, getRegionNameFromElement(element), allSubRegionElements);
if (!CollectionUtils.isEmpty(allSubRegionElements)) {
for (Map.Entry<String, Element> entry : allSubRegionElements.entrySet()) {
parseSubRegion(entry.getValue(), parserContext, entry.getKey());
}
}
parseSubRegions(element, parserContext, resolvedCacheRef);
}
}
private void parseCollectionOfCustomSubElements(ParserContext parserContext, Element element,
BeanDefinitionBuilder builder, String className, String subElementName, String propertyName) {
List<Element> subElements = DomUtils.getChildElementsByTagName(element, new String[] { subElementName,
subElementName + "-ref" });
if (!CollectionUtils.isEmpty(subElements)) {
private void parseSubRegions(Element element, ParserContext parserContext, String resolvedCacheRef) {
Map<String, Element> allSubRegionElements = new HashMap<String, Element>();
findSubRegionElements(element, getRegionNameFromElement(element), allSubRegionElements);
if (!CollectionUtils.isEmpty(allSubRegionElements)) {
for (Map.Entry<String, Element> entry : allSubRegionElements.entrySet()) {
parseSubRegion(entry.getValue(), parserContext, entry.getKey(), resolvedCacheRef);
}
}
}
private void parseCollectionOfCustomSubElements(Element element, ParserContext parserContext,
BeanDefinitionBuilder builder, String className, String subElementName, String propertyName) {
List<Element> subElements = DomUtils.getChildElementsByTagName(element,
new String[] { subElementName, subElementName + "-ref" });
if (!CollectionUtils.isEmpty(subElements)) {
ManagedArray array = new ManagedArray(className, subElements.size());
for (Element subElement : subElements) {
array.add(ParsingUtils.parseRefOrNestedCustomElement(parserContext, subElement, builder));
}
builder.addPropertyValue(propertyName, array);
}
}
private BeanDefinition parseSubRegion(Element element, ParserContext parserContext, String regionPath) {
String parentBeanName = getParentPathForSubRegion(regionPath);
String regionName = getRegionNameFromElement(element); // do before 'renaming' the element, below
element.setAttribute("id", regionPath);
element.setAttribute("name", regionPath);
BeanDefinition beanDefinition = parserContext.getDelegate().parseCustomElement(element);
beanDefinition.getPropertyValues().add("parent", new RuntimeBeanReference(parentBeanName));
beanDefinition.getPropertyValues().add("regionName", regionName);
return beanDefinition;
private void findSubRegionElements(Element parent, String parentPath, Map<String, Element> allSubRegionElements) {
for (Element element : DomUtils.getChildElements(parent)) {
if (element.getLocalName().endsWith("region")) {
String subRegionName = getRegionNameFromElement(element);
String subRegionPath = buildSubRegionPath(parentPath, subRegionName);
allSubRegionElements.put(subRegionPath, element);
findSubRegionElements(element, subRegionPath, allSubRegionElements);
}
}
}
private String getRegionNameFromElement(Element element) {
@@ -187,15 +190,33 @@ abstract class AbstractRegionParser extends AbstractSingleBeanDefinitionParser {
return (StringUtils.hasText(name) ? name : element.getAttribute(ID_ATTRIBUTE));
}
private String buildPathForSubRegion(String parentName, String regionName) {
String regionPath = StringUtils.arrayToDelimitedString(new String[] { parentName, regionName }, "/");
if (!regionPath.startsWith("/")) {
regionPath = "/" + regionPath;
}
return regionPath;
}
private String buildSubRegionPath(String parentName, String regionName) {
String regionPath = StringUtils.arrayToDelimitedString(new String[] { parentName, regionName }, "/");
if (!regionPath.startsWith("/")) {
regionPath = "/" + regionPath;
}
return regionPath;
}
private String getParentPathForSubRegion(String regionPath) {
private BeanDefinition parseSubRegion(Element element, ParserContext parserContext, String subRegionPath,
String cacheRef) {
String parentBeanName = getParentRegionPathFrom(subRegionPath);
String regionName = getRegionNameFromElement(element); // do before 'renaming' the element below
element.setAttribute("id", subRegionPath);
element.setAttribute("name", subRegionPath);
BeanDefinition beanDefinition = parserContext.getDelegate().parseCustomElement(element);
beanDefinition.getPropertyValues().add("cache", new RuntimeBeanReference(cacheRef));
beanDefinition.getPropertyValues().add("parent", new RuntimeBeanReference(parentBeanName));
beanDefinition.getPropertyValues().add("regionName", regionName);
return beanDefinition;
}
private String getParentRegionPathFrom(String regionPath) {
int index = regionPath.lastIndexOf("/");
String parentPath = regionPath.substring(0, index);
if (parentPath.lastIndexOf("/") == 0) {
@@ -204,14 +225,4 @@ abstract class AbstractRegionParser extends AbstractSingleBeanDefinitionParser {
return parentPath;
}
private void findSubregionElements(Element parent, String parentPath, Map<String, Element> allSubregionElements) {
for (Element element : DomUtils.getChildElements(parent)) {
if (element.getLocalName().endsWith("region")) {
String regionPath = buildPathForSubRegion(parentPath, getRegionNameFromElement(element));
allSubregionElements.put(regionPath, element);
findSubregionElements(element, regionPath, allSubregionElements);
}
}
}
}

View File

@@ -78,6 +78,7 @@ class ClientRegionParser extends AbstractRegionParser {
builder.addPropertyValue("attributes", regionAttributesBuilder.getBeanDefinition());
List<Element> subElements = DomUtils.getChildElements(element);
ManagedList<Object> interests = new ManagedList<Object>();
for (Element subElement : subElements) {
@@ -110,7 +111,7 @@ class ClientRegionParser extends AbstractRegionParser {
@Override
protected void doParseRegion(Element element, ParserContext parserContext, BeanDefinitionBuilder builder,
boolean subRegion) {
boolean subRegion) {
throw new UnsupportedOperationException(String.format(
"doParseRegion(:Element, :ParserContext, :BeanDefinitionBuilder, :boolean) is not supported on %1$s",
getClass().getName()));

View File

@@ -31,12 +31,12 @@ import org.w3c.dom.Element;
* @author David Turanski
*/
class GemfireNamespaceHandler extends NamespaceHandlerSupport {
static final List<String> GEMFIRE7_ELEMENTS = Arrays.asList("async-event-queue", "gateway-sender",
"gateway-receiver");
protected static final List<String> GEMFIRE7_ELEMENTS = Arrays.asList("async-event-queue", "gateway-sender",
"gateway-receiver");
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
boolean v7ElementsPresent = GEMFIRE7_ELEMENTS.contains(element.getLocalName());
if (v7ElementsPresent) {
@@ -49,24 +49,23 @@ class GemfireNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
registerBeanDefinitionParser("cache", new CacheParser());
registerBeanDefinitionParser("client-cache", new ClientCacheParser());
registerBeanDefinitionParser("lookup-region", new LookupRegionParser());
registerBeanDefinitionParser("replicated-region", new ReplicatedRegionParser());
registerBeanDefinitionParser("partitioned-region", new PartitionedRegionParser());
registerBeanDefinitionParser("local-region", new LocalRegionParser());
registerBeanDefinitionParser("client-region", new ClientRegionParser());
registerBeanDefinitionParser("pool", new PoolParser());
registerBeanDefinitionParser("index", new IndexParser());
registerBeanDefinitionParser("disk-store", new DiskStoreParser());
registerBeanDefinitionParser("cache-server", new CacheServerParser());
registerBeanDefinitionParser("transaction-manager", new TransactionManagerParser());
registerBeanDefinitionParser("cq-listener-container", new GemfireListenerContainerParser());
registerBeanDefinitionParser("client-cache", new ClientCacheParser());
registerBeanDefinitionParser("client-region", new ClientRegionParser());
registerBeanDefinitionParser("lookup-region", new LookupRegionParser());
registerBeanDefinitionParser("local-region", new LocalRegionParser());
registerBeanDefinitionParser("partitioned-region", new PartitionedRegionParser());
registerBeanDefinitionParser("replicated-region", new ReplicatedRegionParser());
registerBeanDefinitionParser("async-event-queue", new AsyncEventQueueParser());
registerBeanDefinitionParser("gateway-sender", new GatewaySenderParser());
registerBeanDefinitionParser("gateway-receiver", new GatewayReceiverParser());
registerBeanDefinitionParser("function-service", new FunctionServiceParser());
// V6 WAN parsers
registerBeanDefinitionParser("disk-store", new DiskStoreParser());
registerBeanDefinitionParser("gateway-hub", new GatewayHubParser());
registerBeanDefinitionParser("gateway-receiver", new GatewayReceiverParser());
registerBeanDefinitionParser("gateway-sender", new GatewaySenderParser());
registerBeanDefinitionParser("index", new IndexParser());
registerBeanDefinitionParser("pool", new PoolParser());
registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
registerBeanDefinitionParser("cq-listener-container", new GemfireListenerContainerParser());
registerBeanDefinitionParser("function-service", new FunctionServiceParser());
registerBeanDefinitionParser("transaction-manager", new TransactionManagerParser());
}
}

View File

@@ -23,27 +23,28 @@ import org.springframework.data.gemfire.RegionAttributesFactoryBean;
import org.w3c.dom.Element;
/**
* Parser for &lt;local-region;gt; definitions.
*
* Parser for &lt;local-region;gt; bean definitions.
* <p/>
* @author David Turanski
* @author John Blum
*/
class LocalRegionParser extends AbstractRegionParser {
@Override
protected void doParseRegion(Element element, ParserContext parserContext, BeanDefinitionBuilder builder,
boolean subRegion) {
BeanDefinitionBuilder attrBuilder = subRegion ? builder : BeanDefinitionBuilder
.genericBeanDefinition(RegionAttributesFactoryBean.class);
super.doParseCommonRegionConfiguration(element, parserContext, builder, attrBuilder, subRegion);
if (!subRegion) {
builder.addPropertyValue("attributes", attrBuilder.getBeanDefinition());
}
}
@Override
protected Class<?> getRegionFactoryClass() {
return LocalRegionFactoryBean.class;
}
}
@Override
protected void doParseRegion(Element element, ParserContext parserContext, BeanDefinitionBuilder builder,
boolean subRegion) {
BeanDefinitionBuilder regionAttributesBuilder = BeanDefinitionBuilder.genericBeanDefinition(
RegionAttributesFactoryBean.class);
super.doParseCommonRegionConfiguration(element, parserContext, builder, regionAttributesBuilder, subRegion);
builder.addPropertyValue("attributes", regionAttributesBuilder.getBeanDefinition());
}
}

View File

@@ -24,9 +24,10 @@ import org.w3c.dom.Element;
/**
* Parser for &lt;lookup-region;gt; definitions.
*
* <p/>
* @author Costin Leau
* @author David Turanski
* @author John Blum
*/
class LookupRegionParser extends AbstractRegionParser {
@@ -43,9 +44,9 @@ class LookupRegionParser extends AbstractRegionParser {
ParsingUtils.setPropertyValue(element, builder, "name", "name");
if (!subRegion) {
String attr = element.getAttribute("cache-ref");
// add cache reference (fallback to default if nothing is specified)
builder.addPropertyReference("cache", (StringUtils.hasText(attr) ? attr : GemfireConstants.DEFAULT_GEMFIRE_CACHE_NAME));
String cacheRef = element.getAttribute("cache-ref");
builder.addPropertyReference("cache", (StringUtils.hasText(cacheRef) ? cacheRef
: GemfireConstants.DEFAULT_GEMFIRE_CACHE_NAME));
}
else {
builder.addPropertyValue("lookupOnly", true);

View File

@@ -183,10 +183,12 @@ abstract class ParsingUtils {
* <p/>
* @param parserContext the context used for parsing the XML document.
* @param element the XML elements being parsed.
* @param attributesBuilder the Region Attributes builder.
* @param regionAttributesBuilder the Region Attributes builder.
* @return true if parsing actually occurred, false otherwise.
*/
static boolean parseEviction(ParserContext parserContext, Element element, BeanDefinitionBuilder attributesBuilder) {
static boolean parseEviction(ParserContext parserContext, Element element,
BeanDefinitionBuilder regionAttributesBuilder) {
Element evictionElement = DomUtils.getChildElementByTagName(element, "eviction");
if (evictionElement != null) {
@@ -210,7 +212,7 @@ abstract class ParsingUtils {
evictionAttributesBuilder.addPropertyValue("ObjectSizer", sizer);
}
attributesBuilder.addPropertyValue("evictionAttributes", evictionAttributesBuilder.getBeanDefinition());
regionAttributesBuilder.addPropertyValue("evictionAttributes", evictionAttributesBuilder.getBeanDefinition());
return true;
}
@@ -223,27 +225,32 @@ abstract class ParsingUtils {
* <p/>
* @param parserContext the context used while parsing the XML document.
* @param element the XML element being parsed.
* @param attrBuilder the Region Attributes builder.
* @param regionAttributesBuilder the Region Attributes builder.
* @return true if parsing actually occurred, false otherwise.
*/
@SuppressWarnings("unused")
static boolean parseSubscription(ParserContext parserContext, Element element, BeanDefinitionBuilder attrBuilder) {
static boolean parseSubscription(ParserContext parserContext, Element element,
BeanDefinitionBuilder regionAttributesBuilder) {
Element subscriptionElement = DomUtils.getChildElementByTagName(element, "subscription");
if (subscriptionElement == null)
return false;
if (subscriptionElement != null) {
BeanDefinitionBuilder subscriptionAttributesBuilder = BeanDefinitionBuilder.genericBeanDefinition(
SubscriptionAttributesFactoryBean.class);
BeanDefinitionBuilder subscriptionDefBuilder = BeanDefinitionBuilder
.genericBeanDefinition(SubscriptionAttributesFactoryBean.class);
// do manual conversion since the enum is not public
String type = subscriptionElement.getAttribute("type");
// do manual conversion since the enum is not public
String attr = subscriptionElement.getAttribute("type");
if (StringUtils.hasText(attr)) {
subscriptionDefBuilder.addPropertyValue("type", SubscriptionType.valueOf(attr.toUpperCase()));
if (StringUtils.hasText(type)) {
subscriptionAttributesBuilder.addPropertyValue("type", SubscriptionType.valueOf(type.toUpperCase()));
}
regionAttributesBuilder.addPropertyValue("subscriptionAttributes", subscriptionAttributesBuilder.getBeanDefinition());
return true;
}
attrBuilder.addPropertyValue("subscriptionAttributes", subscriptionDefBuilder.getBeanDefinition());
return true;
return false;
}
@@ -284,85 +291,90 @@ abstract class ParsingUtils {
return result;
}
@SuppressWarnings("unused")
static void parseOptionalRegionAttributes(ParserContext parserContext, Element element,
BeanDefinitionBuilder attrBuilder) {
BeanDefinitionBuilder regionAttributesBuilder) {
if (!("partitioned-region".equals(element.getLocalName()))) {
setPropertyValue(element, attrBuilder, "persistent", "persistBackup");
setPropertyValue(element, regionAttributesBuilder, "persistent", "persistBackup");
}
setPropertyValue(element, attrBuilder, "ignore-jta", "ignoreJTA");
setPropertyValue(element, attrBuilder, "key-constraint");
setPropertyValue(element, attrBuilder, "value-constraint");
setPropertyValue(element, attrBuilder, "is-lock-grantor", "lockGrantor");
setPropertyValue(element, attrBuilder, "enable-subscription-conflation");
setPropertyValue(element, attrBuilder, "enable-async-conflation");
setPropertyValue(element, attrBuilder, "initial-capacity");
setPropertyValue(element, attrBuilder, "load-factor");
setPropertyValue(element, attrBuilder, "cloning-enabled");
setPropertyValue(element, attrBuilder, "concurrency-level");
setPropertyValue(element, attrBuilder, "multicast-enabled");
setPropertyValue(element, regionAttributesBuilder, "cloning-enabled");
setPropertyValue(element, regionAttributesBuilder, "concurrency-level");
setPropertyValue(element, regionAttributesBuilder, "enable-async-conflation");
setPropertyValue(element, regionAttributesBuilder, "enable-subscription-conflation");
setPropertyValue(element, regionAttributesBuilder, "ignore-jta", "ignoreJTA");
setPropertyValue(element, regionAttributesBuilder, "initial-capacity");
setPropertyValue(element, regionAttributesBuilder, "is-lock-grantor", "lockGrantor");
setPropertyValue(element, regionAttributesBuilder, "key-constraint");
setPropertyValue(element, regionAttributesBuilder, "load-factor");
setPropertyValue(element, regionAttributesBuilder, "multicast-enabled");
setPropertyValue(element, regionAttributesBuilder, "value-constraint");
String indexUpdateType = element.getAttribute("index-update-type");
if (StringUtils.hasText(indexUpdateType)) {
attrBuilder.addPropertyValue("indexMaintenanceSynchronous", "synchronous".equals(indexUpdateType));
regionAttributesBuilder.addPropertyValue("indexMaintenanceSynchronous", "synchronous".equals(indexUpdateType));
}
String concurrencyChecksEnabled = element.getAttribute("concurrency-checks-enabled");
if (StringUtils.hasText(concurrencyChecksEnabled)) {
if (!GemfireUtils.isGemfireVersion7OrAbove()) {
log.warn("'concurrency-checks-enabled' is only available in Gemfire 7.0 or above");
} else {
ParsingUtils.setPropertyValue(element, attrBuilder, "concurrency-checks-enabled");
log.warn("Setting 'concurrency-checks-enabled' is only available in Gemfire 7.0 or above");
}
else {
ParsingUtils.setPropertyValue(element, regionAttributesBuilder, "concurrency-checks-enabled");
}
}
}
@SuppressWarnings("unused")
static void parseMembershipAttributes(ParserContext parserContext, Element element,
BeanDefinitionBuilder attrBuilder) {
BeanDefinitionBuilder regionAttributesBuilder) {
Element membershipAttributes = DomUtils.getChildElementByTagName(element, "membership-attributes");
if (membershipAttributes != null) {
String requiredRoles[] = StringUtils.commaDelimitedListToStringArray(membershipAttributes
.getAttribute("required-roles"));
String lossActionAttr = membershipAttributes.getAttribute("loss-action");
LossAction lossAction = StringUtils.hasText(lossActionAttr) ? LossAction.fromName(lossActionAttr
.toUpperCase().replace("-", "_")) : null;
String resumptionActionAttr = membershipAttributes.getAttribute("resumption-action");
ResumptionAction resumptionAction = StringUtils.hasText(resumptionActionAttr) ? ResumptionAction
.fromName(resumptionActionAttr.toUpperCase().replace("-", "_")) : null;
String[] requiredRoles = StringUtils.commaDelimitedListToStringArray(
membershipAttributes.getAttribute("required-roles"));
ManagedArray requiredRolesArray = new ManagedArray("java.lang.String", requiredRoles.length);
for (int i = 0; i < requiredRoles.length; i++) {
requiredRolesArray.add(requiredRoles[i]);
}
BeanDefinitionBuilder membershipAttributesBuilder = BeanDefinitionBuilder
.genericBeanDefinition(MembershipAttributes.class);
membershipAttributesBuilder.addConstructorArgValue(requiredRolesArray);
membershipAttributesBuilder.addConstructorArgValue(lossAction);
membershipAttributesBuilder.addConstructorArgValue(resumptionAction);
String lossActionValue = membershipAttributes.getAttribute("loss-action");
attrBuilder.addPropertyValue("membershipAttributes", membershipAttributesBuilder.getRawBeanDefinition());
LossAction lossAction = (StringUtils.hasText(lossActionValue)
? LossAction.fromName(lossActionValue.toUpperCase().replace("-", "_"))
: LossAction.NO_ACCESS);
String resumptionActionValue = membershipAttributes.getAttribute("resumption-action");
ResumptionAction resumptionAction = (StringUtils.hasText(resumptionActionValue)
? ResumptionAction.fromName(resumptionActionValue.toUpperCase().replace("-", "_"))
: ResumptionAction.REINITIALIZE);
regionAttributesBuilder.addPropertyValue("membershipAttributes",
new MembershipAttributes(requiredRoles, lossAction, resumptionAction));
}
}
static void throwExceptionIfNotGemfireV7(String elementName, String attributeName, ParserContext parserContext) {
if (!GemfireUtils.isGemfireVersion7OrAbove()) {
String messagePrefix = (attributeName == null) ? "element '" + elementName + "'" : "attribute '"
+ attributeName + " of element '" + elementName + "'";
String messagePrefix = (attributeName != null)
? String.format("Attribute '%1$s' of element '%2$s'", attributeName, elementName)
: String.format("Element '%1$s'", elementName);
parserContext.getReaderContext().error(
messagePrefix + " requires Gemfire version 7 or later. The current version is " + GemfireUtils.GEMFIRE_VERSION,
null);
String.format("%1$s requires GemFire version 7 or later. The current version is %2$s.",
messagePrefix, GemfireUtils.GEMFIRE_VERSION), null);
}
}
static void parseScope(Element element, BeanDefinitionBuilder builder) {
String scope = element.getAttribute("scope");
if (StringUtils.hasText(scope)) {
builder.addPropertyValue("scope", Scope.fromString(scope.toUpperCase().replace("-", "_")));
}
else {
builder.addPropertyValue("scope", Scope.DISTRIBUTED_ACK);
}
String scopeAttributeValue = element.getAttribute("scope");
Scope scope = (StringUtils.hasText(scopeAttributeValue)
? Scope.fromString(scopeAttributeValue.toUpperCase().replace("-", "_"))
: Scope.DISTRIBUTED_ACK);
builder.addPropertyValue("scope", scope);
}
private static boolean parseExpiration(Element rootElement, String elementName, String propertyName,

View File

@@ -31,11 +31,10 @@ import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
/**
* Parser for &lt;partitioned-region;gt; definitions.
*
* To avoid eager evaluations, the region attributes are declared as a nested
* definition.
*
* Parser for &lt;partitioned-region;gt; bean definitions.
* <p/>
* To avoid eager evaluations, the region attributes are declared as a nested definition.
* <p/>
* @author Costin Leau
* @author David Turanski
* @author John Blum
@@ -53,58 +52,57 @@ class PartitionedRegionParser extends AbstractRegionParser {
boolean subRegion) {
super.doParse(element, builder);
BeanDefinitionBuilder regionAttributesBuilder = (subRegion ? builder
: BeanDefinitionBuilder.genericBeanDefinition(RegionAttributesFactoryBean.class));
BeanDefinitionBuilder regionAttributesBuilder = BeanDefinitionBuilder.genericBeanDefinition(
RegionAttributesFactoryBean.class);
super.doParseCommonRegionConfiguration(element, parserContext, builder, regionAttributesBuilder, subRegion);
builder.addPropertyValue("attributes", regionAttributesBuilder.getBeanDefinition());
BeanDefinitionBuilder partitionAttributesBuilder = BeanDefinitionBuilder.genericBeanDefinition(
PartitionAttributesFactoryBean.class);
parseColocatedWith(element, builder, partitionAttributesBuilder, "colocated-with");
ParsingUtils.setPropertyValue(element, partitionAttributesBuilder, "local-max-memory");
ParsingUtils.setPropertyValue(element, partitionAttributesBuilder, "copies","redundantCopies");
ParsingUtils.setPropertyValue(element, partitionAttributesBuilder, "local-max-memory");
ParsingUtils.setPropertyValue(element, partitionAttributesBuilder, "recovery-delay");
ParsingUtils.setPropertyValue(element, partitionAttributesBuilder, "startup-recovery-delay");
ParsingUtils.setPropertyValue(element, partitionAttributesBuilder, "total-max-memory");
ParsingUtils.setPropertyValue(element, partitionAttributesBuilder, "total-buckets","totalNumBuckets");
ParsingUtils.setPropertyValue(element, partitionAttributesBuilder, "total-max-memory");
Element subElement = DomUtils.getChildElementByTagName(element, "partition-resolver");
// parse nested partition resolver element
if (subElement != null) {
Element partitionResolverSubElement = DomUtils.getChildElementByTagName(element, "partition-resolver");
if (partitionResolverSubElement != null) {
partitionAttributesBuilder.addPropertyValue("partitionResolver",
parsePartitionResolver(parserContext, subElement, builder));
parsePartitionResolver(partitionResolverSubElement, parserContext, builder));
}
subElement = DomUtils.getChildElementByTagName(element, "partition-listener");
// parse nested partition listener element
if (subElement != null) {
Element partitionListenerSubElement = DomUtils.getChildElementByTagName(element, "partition-listener");
if (partitionListenerSubElement != null) {
partitionAttributesBuilder.addPropertyValue("partitionListeners",
parsePartitionListeners(parserContext, subElement, builder));
parsePartitionListeners(partitionListenerSubElement, parserContext, builder));
}
List<Element> fixedPartitions = DomUtils.getChildElementsByTagName(element, "fixed-partition");
List<Element> fixedPartitionSubElements = DomUtils.getChildElementsByTagName(element, "fixed-partition");
if (!CollectionUtils.isEmpty(fixedPartitions)){
if (!CollectionUtils.isEmpty(fixedPartitionSubElements)){
@SuppressWarnings("rawtypes")
ManagedList fixedPartitionAttributes = new ManagedList();
for (Element fp: fixedPartitions) {
BeanDefinitionBuilder fpaBuilder = BeanDefinitionBuilder.genericBeanDefinition(
for (Element fixedPartition : fixedPartitionSubElements) {
BeanDefinitionBuilder fixedPartitionAttributesBuilder = BeanDefinitionBuilder.genericBeanDefinition(
FixedPartitionAttributesFactoryBean.class);
ParsingUtils.setPropertyValue(fp, fpaBuilder, "partition-name");
ParsingUtils.setPropertyValue(fp, fpaBuilder, "num-buckets");
ParsingUtils.setPropertyValue(fp, fpaBuilder, "primary");
fixedPartitionAttributes.add(fpaBuilder.getBeanDefinition());
ParsingUtils.setPropertyValue(fixedPartition, fixedPartitionAttributesBuilder, "partition-name");
ParsingUtils.setPropertyValue(fixedPartition, fixedPartitionAttributesBuilder, "num-buckets");
ParsingUtils.setPropertyValue(fixedPartition, fixedPartitionAttributesBuilder, "primary");
fixedPartitionAttributes.add(fixedPartitionAttributesBuilder.getBeanDefinition());
}
partitionAttributesBuilder.addPropertyValue("fixedPartitionAttributes", fixedPartitionAttributes);
}
// add partition attributes to region attributes
regionAttributesBuilder.addPropertyValue("partitionAttributes", partitionAttributesBuilder.getBeanDefinition());
// add partition/overflow settings as attributes to Region (via PartitionRegionFactoryBean -> RegionFactoryBean)
if (!subRegion) {
builder.addPropertyValue("attributes", regionAttributesBuilder.getBeanDefinition());
}
}
private void parseColocatedWith(Element element, BeanDefinitionBuilder regionBuilder,
@@ -124,12 +122,12 @@ class PartitionedRegionParser extends AbstractRegionParser {
}
}
private Object parsePartitionResolver(ParserContext parserContext, Element subElement,
private Object parsePartitionResolver(Element subElement, ParserContext parserContext,
BeanDefinitionBuilder builder) {
return ParsingUtils.parseRefOrSingleNestedBeanDeclaration(parserContext, subElement, builder);
}
private Object parsePartitionListeners(ParserContext parserContext, Element subElement,
private Object parsePartitionListeners(Element subElement, ParserContext parserContext,
BeanDefinitionBuilder builder) {
return ParsingUtils.parseRefOrNestedBeanDeclaration(parserContext, subElement, builder);
}

View File

@@ -24,9 +24,10 @@ import org.w3c.dom.Element;
/**
* Parser for &lt;replicated-region;gt; definitions.
*
* <p/>
* @author Costin Leau
* @author David Turanski
* @author John Blum
*/
class ReplicatedRegionParser extends AbstractRegionParser {
@@ -41,15 +42,13 @@ class ReplicatedRegionParser extends AbstractRegionParser {
ParsingUtils.parseScope(element, builder);
BeanDefinitionBuilder regionAttributesFactoryBuilder = (subRegion ? builder
: BeanDefinitionBuilder.genericBeanDefinition(RegionAttributesFactoryBean.class));
BeanDefinitionBuilder regionAttributesBuilder = BeanDefinitionBuilder.genericBeanDefinition(
RegionAttributesFactoryBean.class);
super.doParseCommonRegionConfiguration(element, parserContext, builder, regionAttributesFactoryBuilder,
super.doParseCommonRegionConfiguration(element, parserContext, builder, regionAttributesBuilder,
subRegion);
if (!subRegion) {
builder.addPropertyValue("attributes", regionAttributesFactoryBuilder.getBeanDefinition());
}
builder.addPropertyValue("attributes", regionAttributesBuilder.getBeanDefinition());
}
}

View File

@@ -733,37 +733,33 @@ arbitrarily pick one.
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
<xsd:element name="membership-attributes" minOccurs="0"
maxOccurs="1">
<xsd:element name="membership-attributes" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation><![CDATA[
Configures a Region to require one or more membership roles to be present in the system for reliable access to the Region
]]></xsd:documentation>
Establishes reliability requirements and behavior for a region. Use this to configure the region to require one or more membership roles to be running in the system for reliable access to the region.
]]></xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:attribute name="required-roles" type="xsd:string"
use="required">
<xsd:attribute name="required-roles" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation><![CDATA[
A comma delimited list of required role names
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="loss-action" type="xsd:string"
use="optional">
<xsd:attribute name="loss-action" type="xsd:string" default="no-access">
<xsd:annotation>
<xsd:documentation><![CDATA[
Specifies the behavior when one or more required roles are missing:
(full-access, limited-access, no-access, or reconnect)
Set one of the following values to specify how access to the region is affected when one or more required roles are lost:
(full-access, limited-access, no-access, or reconnect).
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="resumption-action" type="xsd:string"
use="optional">
<xsd:attribute name="resumption-action" type="xsd:string" default="reinitialize">
<xsd:annotation>
<xsd:documentation><![CDATA[
Specifies how the region is affected by resumption of reliability
when one or more missing required roles is restored to the distributed membership (none or reinitialize)
Specifies how the region is affected by resumption of reliability when one or more missing required roles return to the distributed membership:
(none or reinitialize).
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>

View File

@@ -0,0 +1,139 @@
/*
* 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.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.DataPolicy;
import com.gemstone.gemfire.cache.EvictionAction;
import com.gemstone.gemfire.cache.EvictionAttributes;
import com.gemstone.gemfire.cache.InterestPolicy;
import com.gemstone.gemfire.cache.LossAction;
import com.gemstone.gemfire.cache.MembershipAttributes;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.RegionAttributes;
import com.gemstone.gemfire.cache.ResumptionAction;
import com.gemstone.gemfire.cache.Scope;
import com.gemstone.gemfire.cache.SubscriptionAttributes;
/**
* The SubRegionIntegrationTest class is a test suite of test cases testing the functionality of SubRegions in GemFire
* configured with Spring Data GemFire's XML namespace configuration meta-data. This test class tests a complex
* SubRegion configuration in order to ensure functional completeness.
* <p/>
* @author John Blum
* @see org.junit.Test
* @see org.junit.runner.RunWith
* @see org.springframework.test.context.ContextConfiguration
* @see org.springframework.test.context.junit4.SpringJUnit4ClassRunner
* @since 1.4.0
* @since 7.0.1 (GemFire)
*/
@ContextConfiguration("complex-subregion.xml")
@RunWith(SpringJUnit4ClassRunner.class)
public class SubRegionIntegrationTest {
@Autowired
private Cache cache;
@Resource(name = "Customers")
private Region customers;
@Resource(name = "/Customers/Accounts")
private Region accounts;
@Test
public void testGemFireAccountsSubRegionCreation() {
assertNotNull("The GemFire Cache was not properly initialized!", cache);
Region customers = cache.getRegion("Customers");
assertNotNull(customers);
assertEquals("Customers", customers.getName());
assertEquals("/Customers", customers.getFullPath());
Region accounts = customers.getSubregion("Accounts");
assertNotNull(accounts);
assertEquals("Accounts", accounts.getName());
assertEquals("/Customers/Accounts", accounts.getFullPath());
Region cacheAccounts = cache.getRegion("/Customers/Accounts");
assertSame(accounts, cacheAccounts);
}
@Test
public void testSpringSubRegionConfiguration() {
assertNotNull("The /Customers/Accounts SubRegion was not properly initialized!", accounts);
assertEquals("Accounts", accounts.getName());
assertEquals("/Customers/Accounts", accounts.getFullPath());
RegionAttributes regionAttributes = accounts.getAttributes();
assertNotNull(regionAttributes);
assertEquals(DataPolicy.PERSISTENT_REPLICATE, regionAttributes.getDataPolicy());
assertEquals(20, regionAttributes.getConcurrencyLevel());
assertTrue(regionAttributes.isDiskSynchronous());
assertTrue(regionAttributes.getIgnoreJTA());
assertFalse(regionAttributes.getIndexMaintenanceSynchronous());
assertEquals(1000, regionAttributes.getInitialCapacity());
assertEquals(Long.class, regionAttributes.getKeyConstraint());
assertEquals(Scope.DISTRIBUTED_ACK, regionAttributes.getScope());
assertTrue(regionAttributes.getStatisticsEnabled());
assertEquals(String.class, regionAttributes.getValueConstraint());
assertNotNull(regionAttributes.getCacheListeners());
assertEquals(1, regionAttributes.getCacheListeners().length);
assertTrue(regionAttributes.getCacheListeners()[0] instanceof SimpleCacheListener);
assertTrue(regionAttributes.getCacheLoader() instanceof SimpleCacheLoader);
assertTrue(regionAttributes.getCacheWriter() instanceof SimpleCacheWriter);
EvictionAttributes evictionAttributes = regionAttributes.getEvictionAttributes();
assertNotNull(evictionAttributes);
assertEquals(EvictionAction.OVERFLOW_TO_DISK, evictionAttributes.getAction());
assertEquals(10000, evictionAttributes.getMaximum());
MembershipAttributes membershipAttributes = regionAttributes.getMembershipAttributes();
assertNotNull(membershipAttributes);
assertNotNull(membershipAttributes.getRequiredRoles());
assertEquals(1, membershipAttributes.getRequiredRoles().size());
assertTrue(membershipAttributes.getRequiredRoles().iterator().next().getName().equalsIgnoreCase("TEST"));
assertEquals(LossAction.LIMITED_ACCESS, membershipAttributes.getLossAction());
assertEquals(ResumptionAction.REINITIALIZE, membershipAttributes.getResumptionAction());
SubscriptionAttributes subscriptionAttributes = regionAttributes.getSubscriptionAttributes();
assertNotNull(subscriptionAttributes);
assertEquals(InterestPolicy.CACHE_CONTENT, subscriptionAttributes.getInterestPolicy());
}
}

View File

@@ -16,7 +16,6 @@
package org.springframework.data.gemfire.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
@@ -28,7 +27,7 @@ import org.springframework.context.support.ClassPathXmlApplicationContext;
* bean definition with both data-policy and shortcut specified.
* <p/>
* @author John Blum
* @see org.junit.Assert
* @see org.junit.Test
* @since 1.3.3
*/
public class ClientRegionUsingDataPolicyAndShortcutTest {

View File

@@ -24,24 +24,31 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.data.gemfire.SubRegionFactoryBean;
import org.springframework.data.gemfire.ReplicatedRegionFactoryBean;
import org.springframework.data.gemfire.TestUtils;
import org.springframework.data.gemfire.test.GemfireTestApplicationContextInitializer;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.gemstone.gemfire.cache.AttributesFactory;
import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.CacheLoader;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.RegionAttributes;
/**
* The SubRegionNamespaceTest class is a test suite of test cases testing the contract and functionality of
* Region/SubRegion creation in a GemFire Cache.
* <p/>
* @author David Turanski
* @author John Blum
* @see org.junit.Test
* @see org.junit.runner.RunWith
* @see org.springframework.data.gemfire.test.GemfireTestApplicationContextInitializer
* @see org.springframework.test.context.ContextConfiguration
* @see org.springframework.test.context.junit4.SpringJUnit4ClassRunner
*/
@SuppressWarnings("deprecation")
@ContextConfiguration(locations = "subregion-ns.xml", initializers = GemfireTestApplicationContextInitializer.class)
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="subregion-ns.xml",
initializers=GemfireTestApplicationContextInitializer.class)
@SuppressWarnings("deprecation")
public class SubRegionNamespaceTest {
@Autowired
@@ -51,6 +58,7 @@ public class SubRegionNamespaceTest {
@Test
public void testNestedRegionsCreated() {
Cache cache = context.getBean(Cache.class);
assertNotNull(cache.getRegion("parent"));
assertNotNull(cache.getRegion("/parent/child"));
assertNotNull(cache.getRegion("/parent/child/grandchild"));
@@ -59,35 +67,31 @@ public class SubRegionNamespaceTest {
@SuppressWarnings("rawtypes")
@Test
public void testNestedReplicatedRegions() {
Region parent = null;
parent = context.getBean("parent", Region.class);
Cache cache = context.getBean(Cache.class);
Region parent = context.getBean("parent", Region.class);
Region child = context.getBean("/parent/child", Region.class);
Region grandchild = context.getBean("/parent/child/grandchild", Region.class);
assertNotNull(child);
assertEquals("/parent/child", child.getFullPath());
assertSame(child, parent.getSubregion("child"));
assertNotNull(grandchild);
assertEquals("/parent/child/grandchild", grandchild.getFullPath());
assertSame(grandchild, child.getSubregion("grandchild"));
}
@SuppressWarnings({ "unused", "rawtypes", "unchecked" })
@SuppressWarnings({ "rawtypes", "unchecked" })
@Test
public void testMixedNestedRegions() {
Cache cache = context.getBean(Cache.class);
Region parent = context.getBean("replicatedParent", Region.class);
Region child = context.getBean("/replicatedParent/replicatedChild", Region.class);
Region grandchild = context.getBean("/replicatedParent/replicatedChild/partitionedGrandchild", Region.class);
assertNotNull(child);
assertEquals("/replicatedParent/replicatedChild", child.getFullPath());
assertEquals(child, parent.getSubregion("replicatedChild"));
assertNotNull(grandchild);
assertEquals("/replicatedParent/replicatedChild/partitionedGrandchild", grandchild.getFullPath());
assertSame(grandchild, child.getSubregion("partitionedGrandchild"));
}
@SuppressWarnings("rawtypes")
@@ -100,25 +104,29 @@ public class SubRegionNamespaceTest {
assertEquals("/parentWithSiblings/child2", child2.getFullPath());
assertSame(child1, parent.getSubregion("child1"));
assertSame(child2, parent.getSubregion("child2"));
Region grandchild1 = context.getBean("/parentWithSiblings/child1/grandChild11", Region.class);
assertEquals("/parentWithSiblings/child1/grandChild11", grandchild1.getFullPath());
}
@SuppressWarnings({ "unused", "rawtypes" })
@SuppressWarnings({ "rawtypes", "unused" })
@Test
public void testComplexNestedRegions() throws Exception {
Region parent = context.getBean("complexNested", Region.class);
Region child1 = context.getBean("/complexNested/child1", Region.class);
Region child2 = context.getBean("/complexNested/child2", Region.class);
Region grandchild1 = context.getBean("/complexNested/child1/grandChild11", Region.class);
Region grandchild11 = context.getBean("/complexNested/child1/grandChild11", Region.class);
SubRegionFactoryBean grandchild1fb = context.getBean("&/complexNested/child1/grandChild11",
SubRegionFactoryBean.class);
assertNotNull(grandchild1fb);
RegionAttributes attr = grandchild1fb.create();
assertNotNull(attr);
CacheLoader cl = attr.getCacheLoader();
assertNotNull(cl);
ReplicatedRegionFactoryBean grandchild11FactoryBean = context.getBean("&/complexNested/child1/grandChild11",
ReplicatedRegionFactoryBean.class);
assertNotNull(grandchild11FactoryBean);
CacheLoader expectedCacheLoader = TestUtils.readField("cacheLoader", grandchild11FactoryBean);
assertNotNull(expectedCacheLoader);
CacheLoader actualCacheLoader = grandchild11.getAttributes().getCacheLoader();
assertSame(expectedCacheLoader, actualCacheLoader);
}
}
}

View File

@@ -0,0 +1,68 @@
/*
* 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.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* The SubRegionWithInvalidDataPolicyTest class is a test suite of test cases testing the data-policy and persistent
* attributes settings are consistent for GemFire SubRegion bean definitions.
* <p/>
* @author John Blum
* @see org.junit.Test
* @see org.springframework.test.context.junit4.SpringJUnit4ClassRunner
* @since GemFire 7.0.1
* @since Spring Data GemFire 1.4.0
*/
public class SubRegionWithInvalidDataPolicyTest {
@Test(expected = BeanCreationException.class)
public void testSubRegionBeanDefinitionWithInconsistentDataPolicy() {
try {
new ClassPathXmlApplicationContext("/org/springframework/data/gemfire/config/subregion-with-invalid-datapolicy.xml");
}
catch (BeanCreationException expected) {
//expected.printStackTrace(System.err);
assertTrue(expected.getMessage().contains("Error creating bean with name '/Parent/Child'"));
assertTrue(expected.getCause() instanceof IllegalArgumentException);
assertEquals("Data Policy 'PERSISTENT_PARTITION' is not supported in Replicated Regions.",
expected.getCause().getMessage());
throw expected;
}
}
@Test(expected = BeanCreationException.class)
public void testSubRegionBeanDefinitionWithInvalidDataPolicyPersistentSettings() {
try {
new ClassPathXmlApplicationContext("/org/springframework/data/gemfire/config/subregion-with-inconsistent-datapolicy-persistent-settings.xml");
}
catch (BeanCreationException expected) {
//expected.printStackTrace(System.err);
assertTrue(expected.getMessage().contains("Error creating bean with name '/Parent/Child'"));
assertTrue(expected.getCause() instanceof IllegalArgumentException);
assertEquals("Data Policy 'REPLICATE' is invalid when persistent is true.",
expected.getCause().getMessage());
throw expected;
}
}
}

View File

@@ -42,19 +42,19 @@ import com.gemstone.gemfire.cache.RegionService;
import com.gemstone.gemfire.cache.Scope;
import com.gemstone.gemfire.cache.SubscriptionAttributes;
import com.gemstone.gemfire.cache.query.QueryService;
/**
* @author David Turanski
*
* @author John Blum
*/
@SuppressWarnings("deprecation")
public class MockRegionFactory<K,V> {
private static QueryService queryService = mock(QueryService.class);
private static RegionService regionService = mock(RegionService.class);
private AttributesFactory<K,V> attributesFactory;
private final StubCache cache;
public MockRegionFactory(StubCache cache) {
@@ -64,50 +64,55 @@ public class MockRegionFactory<K,V> {
public RegionFactory<K, V> createMockRegionFactory() {
return createMockRegionFactory(null);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public RegionFactory<K, V> createMockRegionFactory(RegionAttributes<K,V> attributes) {
attributesFactory = attributes == null?
new AttributesFactory<K,V>() :
new AttributesFactory<K,V>(attributes) ;
//Workaround for GemFire bug
if(attributes !=null) {
attributesFactory.setLockGrantor(attributes.isLockGrantor());
}
final RegionFactory<K, V> regionFactory = mock(RegionFactory.class);
when(regionFactory.create(anyString())).thenAnswer(new Answer<Region>() {
@SuppressWarnings({ "unchecked", "rawtypes" })
public RegionFactory<K, V> createMockRegionFactory(RegionAttributes<K,V> attributes) {
attributesFactory = (attributes != null ? new AttributesFactory<K,V>(attributes)
: new AttributesFactory<K,V>());
//Workaround for GemFire bug
if (attributes !=null) {
attributesFactory.setLockGrantor(attributes.isLockGrantor());
}
final RegionFactory<K, V> regionFactory = mock(RegionFactory.class);
when(regionFactory.create(anyString())).thenAnswer(new Answer<Region>() {
@Override
public Region answer(InvocationOnMock invocation) throws Throwable {
String name = (String)invocation.getArguments()[0];
String name = (String) invocation.getArguments()[0];
Region region = mockRegion(name);
cache.allRegions().put(name, region);
return region;
}});
when(regionFactory.createSubregion(any(Region.class),anyString())).thenAnswer(new Answer<Region>() {
}
});
when(regionFactory.createSubregion(any(Region.class),anyString())).thenAnswer(new Answer<Region>() {
@Override
public Region answer(InvocationOnMock invocation) throws Throwable {
Region parent = (Region)invocation.getArguments()[0];
String name = (String)invocation.getArguments()[1];
String parentName = null;
Region parent = (Region) invocation.getArguments()[0];
String name = (String) invocation.getArguments()[1];
String parentRegionName = null;
for (String key: cache.allRegions().keySet()) {
if (cache.allRegions().get(key).equals(parent)) {
parentName = key;
parentRegionName = key;
}
}
String regionName = parentName.startsWith("/") ? parentName+"/"+name : "/"+parentName+"/"+ name;
Region subRegion = mockRegion(regionName);
cache.allRegions().put(regionName, subRegion);
assert parentRegionName != null : "The parent Region name was null!";
String subRegionName = (parentRegionName.startsWith("/") ? parentRegionName+"/"+name
: "/"+parentRegionName+"/"+ name);
Region subRegion = mockRegion(subRegionName);
cache.allRegions().put(subRegionName, subRegion);
return subRegion;
}});
}
});
when(regionFactory.setCacheLoader(any(CacheLoader.class))).thenAnswer(new Answer<RegionFactory>(){
@Override
public RegionFactory answer(InvocationOnMock invocation) throws Throwable {
@@ -116,7 +121,7 @@ public class MockRegionFactory<K,V> {
return regionFactory;
}
});
when(regionFactory.setCacheWriter(any(CacheWriter.class))).thenAnswer(new Answer<RegionFactory>(){
@Override
public RegionFactory answer(InvocationOnMock invocation) throws Throwable {
@@ -125,8 +130,8 @@ public class MockRegionFactory<K,V> {
return regionFactory;
}
});
when(regionFactory.addAsyncEventQueueId(anyString())).thenAnswer(new Answer<RegionFactory>(){
@Override
public RegionFactory answer(InvocationOnMock invocation) throws Throwable {
@@ -135,7 +140,7 @@ public class MockRegionFactory<K,V> {
return regionFactory;
}
});
when(regionFactory.addCacheListener(any(CacheListener.class))).thenAnswer(new Answer<RegionFactory>(){
@Override
public RegionFactory answer(InvocationOnMock invocation) throws Throwable {
@@ -144,7 +149,7 @@ public class MockRegionFactory<K,V> {
return regionFactory;
}
});
when(regionFactory.setEvictionAttributes(any(EvictionAttributes.class))).thenAnswer(new Answer<RegionFactory>(){
@Override
public RegionFactory answer(InvocationOnMock invocation) throws Throwable {
@@ -153,7 +158,7 @@ public class MockRegionFactory<K,V> {
return regionFactory;
}
});
when(regionFactory.setEntryIdleTimeout(any(ExpirationAttributes.class))).thenAnswer(new Answer<RegionFactory>(){
@Override
public RegionFactory answer(InvocationOnMock invocation) throws Throwable {
@@ -171,7 +176,7 @@ public class MockRegionFactory<K,V> {
return regionFactory;
}
});
when(regionFactory.setEntryTimeToLive(any(ExpirationAttributes.class))).thenAnswer(new Answer<RegionFactory>(){
@Override
public RegionFactory answer(InvocationOnMock invocation) throws Throwable {
@@ -189,7 +194,7 @@ public class MockRegionFactory<K,V> {
return regionFactory;
}
});
when(regionFactory.setRegionIdleTimeout(any(ExpirationAttributes.class))).thenAnswer(new Answer<RegionFactory>(){
@Override
public RegionFactory answer(InvocationOnMock invocation) throws Throwable {
@@ -198,7 +203,7 @@ public class MockRegionFactory<K,V> {
return regionFactory;
}
});
when(regionFactory.setRegionTimeToLive(any(ExpirationAttributes.class))).thenAnswer(new Answer<RegionFactory>(){
@Override
public RegionFactory answer(InvocationOnMock invocation) throws Throwable {
@@ -207,7 +212,7 @@ public class MockRegionFactory<K,V> {
return regionFactory;
}
});
when(regionFactory.setScope(any(Scope.class))).thenAnswer(new Answer<RegionFactory>(){
@Override
public RegionFactory answer(InvocationOnMock invocation) throws Throwable {
@@ -216,7 +221,7 @@ public class MockRegionFactory<K,V> {
return regionFactory;
}
});
when(regionFactory.setDataPolicy(any(DataPolicy.class))).thenAnswer(new Answer<RegionFactory>(){
@Override
public RegionFactory answer(InvocationOnMock invocation) throws Throwable {
@@ -225,7 +230,7 @@ public class MockRegionFactory<K,V> {
return regionFactory;
}
});
when(regionFactory.setEarlyAck(anyBoolean())).thenAnswer(new Answer<RegionFactory>(){
@Override
public RegionFactory answer(InvocationOnMock invocation) throws Throwable {
@@ -234,7 +239,7 @@ public class MockRegionFactory<K,V> {
return regionFactory;
}
});
when(regionFactory.setMulticastEnabled(anyBoolean())).thenAnswer(new Answer<RegionFactory>(){
@Override
public RegionFactory answer(InvocationOnMock invocation) throws Throwable {
@@ -243,7 +248,7 @@ public class MockRegionFactory<K,V> {
return regionFactory;
}
});
when(regionFactory.setPoolName(anyString())).thenAnswer(new Answer<RegionFactory>(){
@Override
public RegionFactory answer(InvocationOnMock invocation) throws Throwable {
@@ -252,7 +257,7 @@ public class MockRegionFactory<K,V> {
return regionFactory;
}
});
when(regionFactory.setEnableGateway(anyBoolean())).thenAnswer(new Answer<RegionFactory>(){
@Override
public RegionFactory answer(InvocationOnMock invocation) throws Throwable {
@@ -261,7 +266,7 @@ public class MockRegionFactory<K,V> {
return regionFactory;
}
});
when(regionFactory.setEnableAsyncConflation(anyBoolean())).thenAnswer(new Answer<RegionFactory>(){
@Override
public RegionFactory answer(InvocationOnMock invocation) throws Throwable {
@@ -270,7 +275,7 @@ public class MockRegionFactory<K,V> {
return regionFactory;
}
});
when(regionFactory.setEnableSubscriptionConflation(anyBoolean())).thenAnswer(new Answer<RegionFactory>(){
@Override
public RegionFactory answer(InvocationOnMock invocation) throws Throwable {
@@ -279,7 +284,7 @@ public class MockRegionFactory<K,V> {
return regionFactory;
}
});
when(regionFactory.setKeyConstraint(any(Class.class))).thenAnswer(new Answer<RegionFactory>(){
@Override
public RegionFactory answer(InvocationOnMock invocation) throws Throwable {
@@ -288,7 +293,7 @@ public class MockRegionFactory<K,V> {
return regionFactory;
}
});
when(regionFactory.setValueConstraint(any(Class.class))).thenAnswer(new Answer<RegionFactory>(){
@Override
public RegionFactory answer(InvocationOnMock invocation) throws Throwable {
@@ -297,7 +302,7 @@ public class MockRegionFactory<K,V> {
return regionFactory;
}
});
when(regionFactory.setInitialCapacity(anyInt())).thenAnswer(new Answer<RegionFactory>(){
@Override
public RegionFactory answer(InvocationOnMock invocation) throws Throwable {
@@ -307,7 +312,7 @@ public class MockRegionFactory<K,V> {
return regionFactory;
}
});
when(regionFactory.setLoadFactor(anyInt())).thenAnswer(new Answer<RegionFactory>(){
@Override
public RegionFactory answer(InvocationOnMock invocation) throws Throwable {
@@ -316,7 +321,7 @@ public class MockRegionFactory<K,V> {
return regionFactory;
}
});
when(regionFactory.setConcurrencyLevel(anyInt())).thenAnswer(new Answer<RegionFactory>(){
@Override
public RegionFactory answer(InvocationOnMock invocation) throws Throwable {
@@ -325,7 +330,7 @@ public class MockRegionFactory<K,V> {
return regionFactory;
}
});
when(regionFactory.setConcurrencyChecksEnabled(anyBoolean())).thenAnswer(new Answer<RegionFactory>(){
@Override
public RegionFactory answer(InvocationOnMock invocation) throws Throwable {
@@ -334,7 +339,7 @@ public class MockRegionFactory<K,V> {
return regionFactory;
}
});
when(regionFactory.setDiskWriteAttributes(any(DiskWriteAttributes.class))).thenAnswer(new Answer<RegionFactory>(){
@Override
public RegionFactory answer(InvocationOnMock invocation) throws Throwable {
@@ -343,7 +348,7 @@ public class MockRegionFactory<K,V> {
return regionFactory;
}
});
when(regionFactory.setDiskStoreName(anyString())).thenAnswer(new Answer<RegionFactory>(){
@Override
public RegionFactory answer(InvocationOnMock invocation) throws Throwable {
@@ -352,7 +357,7 @@ public class MockRegionFactory<K,V> {
return regionFactory;
}
});
when(regionFactory.setDiskSynchronous(anyBoolean())).thenAnswer(new Answer<RegionFactory>(){
@Override
public RegionFactory answer(InvocationOnMock invocation) throws Throwable {
@@ -361,7 +366,7 @@ public class MockRegionFactory<K,V> {
return regionFactory;
}
});
when(regionFactory.setDiskDirs(any(File[].class))).thenAnswer(new Answer<RegionFactory>(){
@Override
public RegionFactory answer(InvocationOnMock invocation) throws Throwable {
@@ -370,7 +375,7 @@ public class MockRegionFactory<K,V> {
return regionFactory;
}
});
when(regionFactory.setDiskDirsAndSizes(any(File[].class),any(int[].class))).thenAnswer(new Answer<RegionFactory>(){
@Override
public RegionFactory answer(InvocationOnMock invocation) throws Throwable {
@@ -380,7 +385,7 @@ public class MockRegionFactory<K,V> {
return regionFactory;
}
});
when(regionFactory.setPartitionAttributes(any(PartitionAttributes.class))).thenAnswer(new Answer<RegionFactory>(){
@Override
public RegionFactory answer(InvocationOnMock invocation) throws Throwable {
@@ -389,7 +394,7 @@ public class MockRegionFactory<K,V> {
return regionFactory;
}
});
when(regionFactory.setMembershipAttributes(any(MembershipAttributes.class))).thenAnswer(new Answer<RegionFactory>(){
@Override
public RegionFactory answer(InvocationOnMock invocation) throws Throwable {
@@ -398,7 +403,7 @@ public class MockRegionFactory<K,V> {
return regionFactory;
}
});
when(regionFactory.setIndexMaintenanceSynchronous(anyBoolean())).thenAnswer(new Answer<RegionFactory>(){
@Override
public RegionFactory answer(InvocationOnMock invocation) throws Throwable {
@@ -407,7 +412,7 @@ public class MockRegionFactory<K,V> {
return regionFactory;
}
});
when(regionFactory.setStatisticsEnabled(anyBoolean())).thenAnswer(new Answer<RegionFactory>(){
@Override
public RegionFactory answer(InvocationOnMock invocation) throws Throwable {
@@ -416,7 +421,7 @@ public class MockRegionFactory<K,V> {
return regionFactory;
}
});
when(regionFactory.setIgnoreJTA(anyBoolean())).thenAnswer(new Answer<RegionFactory>(){
@Override
public RegionFactory answer(InvocationOnMock invocation) throws Throwable {
@@ -425,7 +430,7 @@ public class MockRegionFactory<K,V> {
return regionFactory;
}
});
when(regionFactory.setLockGrantor(anyBoolean())).thenAnswer(new Answer<RegionFactory>(){
@Override
public RegionFactory answer(InvocationOnMock invocation) throws Throwable {
@@ -435,7 +440,7 @@ public class MockRegionFactory<K,V> {
return regionFactory;
}
});
when(regionFactory.setSubscriptionAttributes(any(SubscriptionAttributes.class))).thenAnswer(new Answer<RegionFactory>(){
@Override
public RegionFactory answer(InvocationOnMock invocation) throws Throwable {
@@ -444,7 +449,7 @@ public class MockRegionFactory<K,V> {
return regionFactory;
}
});
when(regionFactory.setGatewayHubId(anyString())).thenAnswer(new Answer<RegionFactory>(){
@Override
public RegionFactory answer(InvocationOnMock invocation) throws Throwable {
@@ -453,7 +458,7 @@ public class MockRegionFactory<K,V> {
return regionFactory;
}
});
when(regionFactory.setCloningEnabled(anyBoolean())).thenAnswer(new Answer<RegionFactory>(){
@Override
public RegionFactory answer(InvocationOnMock invocation) throws Throwable {
@@ -462,7 +467,7 @@ public class MockRegionFactory<K,V> {
return regionFactory;
}
});
when(regionFactory.addGatewaySenderId(anyString())).thenAnswer(new Answer<RegionFactory>(){
@Override
public RegionFactory answer(InvocationOnMock invocation) throws Throwable {
@@ -471,7 +476,7 @@ public class MockRegionFactory<K,V> {
return regionFactory;
}
});
when(regionFactory.addAsyncEventQueueId(anyString())).thenAnswer(new Answer<RegionFactory>(){
@Override
public RegionFactory answer(InvocationOnMock invocation) throws Throwable {
@@ -480,82 +485,80 @@ public class MockRegionFactory<K,V> {
return regionFactory;
}
});
return regionFactory;
}
@SuppressWarnings("rawtypes")
@SuppressWarnings("rawtypes")
RegionFactory createRegionFactory() {
return createMockRegionFactory();
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public Region mockRegion(String name) {
RegionService regionService = mockRegionService();
Region region = mock(Region.class);
when(region.getRegionService()).thenReturn(regionService);
when(region.getAttributes()).thenAnswer(new Answer<RegionAttributes>() {
when(region.getRegionService()).thenReturn(regionService);
when(region.getAttributes()).thenAnswer(new Answer<RegionAttributes>() {
@Override
public RegionAttributes answer(InvocationOnMock invocation) throws Throwable {
RegionAttributes attributes = attributesFactory.create();
return attributes;
}
});
when(region.getName()).thenReturn(name);
when(region.getSubregion(anyString())).thenAnswer(new Answer<Region>() {
when(region.getFullPath()).thenReturn(name);
when(region.getName()).thenReturn(name);
when(region.getSubregion(anyString())).thenAnswer(new Answer<Region>() {
@Override
public Region answer(InvocationOnMock invocation) throws Throwable {
Region parent = (Region) invocation.getMock();
String parentRegionName = parent.getName();
String subRegionName = (String) invocation.getArguments()[0];
String subRegionPath = (parentRegionName.startsWith("/") ? parentRegionName+"/"+subRegionName
: "/"+parentRegionName+"/"+subRegionName);
Region region = cache.getRegion(subRegionPath);
return region;
}
});
when(region.createSubregion(anyString(), any(RegionAttributes.class))).thenAnswer(new Answer<Region>() {
@Override
public Region answer(InvocationOnMock invocation) throws Throwable {
String name = (String) invocation.getArguments()[0];
Region parent = (Region)invocation.getMock();
String parentName = parent.getName();
String regionName = parentName.startsWith("/") ? parentName+"/"+ name :
"/"+parentName+"/"+ name;
RegionAttributes attributes = (RegionAttributes) invocation.getArguments()[1];
Region region = cache.getRegion(regionName);
return region;
}
});
when(region.createSubregion(anyString(),any(RegionAttributes.class))).thenAnswer(new Answer<Region>() {
@Override
public Region answer(InvocationOnMock invocation) throws Throwable {
String name = (String)invocation.getArguments()[0];
RegionAttributes attributes = (RegionAttributes)invocation.getArguments()[1];
Region parent = (Region)invocation.getMock();
Region parent = (Region) invocation.getMock();
String parentName = parent.getName();
String regionName = parentName.startsWith("/") ? parentName+"/"+name : "/"+parentName+"/"+ name;
Region subRegion = new MockRegionFactory(cache).createMockRegionFactory(attributes).create(regionName);
when(subRegion.getFullPath()).thenReturn(regionName);
cache.allRegions().put(regionName, subRegion);
return subRegion;
}});
}
});
return region;
}
public static RegionService mockRegionService() {
when(regionService.getQueryService()).thenReturn(queryService);
return regionService;
}
public static QueryService mockQueryService() {
return queryService;
}
}
}

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:gfe="http://www.springframework.org/schema/gemfire"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/gemfire http://www.springframework.org/schema/gemfire/spring-gemfire-1.3.xsd">
<gfe:cache/>
<gfe:replicated-region id="Customers" persistent="false">
<gfe:replicated-region name="Accounts"
concurrency-level="20"
destroy="true"
disk-synchronous="true"
ignore-jta="true"
index-update-type="asynchronous"
initial-capacity="1000"
key-constraint="java.lang.Long"
persistent="true"
scope="distributed-ack"
statistics="true"
value-constraint="java.lang.String">
<!-- NOTE Async Event Queue and Gateway Sender tests are covered in the subregionsubelement-ns.xml and associated test class -->
<gfe:cache-listener>
<bean class="org.springframework.data.gemfire.SimpleCacheListener"/>
</gfe:cache-listener>
<gfe:cache-loader>
<bean class="org.springframework.data.gemfire.SimpleCacheLoader"/>
</gfe:cache-loader>
<gfe:cache-writer>
<bean class="org.springframework.data.gemfire.SimpleCacheWriter"/>
</gfe:cache-writer>
<gfe:membership-attributes loss-action="limited-access" required-roles="TEST" resumption-action="reinitialize"/>
<gfe:subscription type="CACHE_CONTENT"/>
<gfe:eviction action="OVERFLOW_TO_DISK" threshold="10000"/>
</gfe:replicated-region>
</gfe:replicated-region>
</beans>

View File

@@ -7,6 +7,8 @@
http://www.springframework.org/schema/gemfire http://www.springframework.org/schema/gemfire/spring-gemfire.xsd
">
<bean class="org.springframework.data.gemfire.test.GemfireTestBeanPostProcessor"/>
<gfe:pool>
<gfe:locator host="localhost" port="10334"/>
</gfe:pool>

View File

@@ -1,13 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:gfe="http://www.springframework.org/schema/gemfire"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/gemfire http://www.springframework.org/schema/gemfire/spring-gemfire.xsd
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd" >
<gfe:cache />
http://www.springframework.org/schema/gemfire http://www.springframework.org/schema/gemfire/spring-gemfire.xsd
">
<gfe:cache/>
<gfe:replicated-region id="parent">
<gfe:replicated-region name="child">
@@ -15,36 +15,35 @@
</gfe:replicated-region>
</gfe:replicated-region>
<gfe:replicated-region id="replicatedParent">
<gfe:replicated-region id="replicatedParent">
<gfe:replicated-region name="replicatedChild">
<gfe:partitioned-region name="partitionedGrandchild"/>
</gfe:replicated-region>
</gfe:replicated-region>
<gfe:replicated-region id="parentWithSiblings">
<gfe:replicated-region id="parentWithSiblings">
<gfe:replicated-region name="child1">
<gfe:replicated-region name="grandChild11"/>
<gfe:replicated-region name="grandChild12"/>
<gfe:replicated-region name="grandChild12"/>
</gfe:replicated-region>
<gfe:replicated-region name="child2"/>
</gfe:replicated-region>
<gfe:replicated-region id="complexNested">
<gfe:cache-listener ref="c-listener"/>
<gfe:replicated-region name="child1">
<gfe:replicated-region name="grandChild11">
<gfe:cache-loader ref="c-loader"/>
</gfe:replicated-region>
<gfe:replicated-region name="grandChild12"/>
</gfe:replicated-region>
<gfe:replicated-region name="child2">
<gfe:cache-writer ref="c-writer"/>
</gfe:replicated-region>
</gfe:replicated-region>
<gfe:replicated-region id="complexNested">
<gfe:cache-listener ref="c-listener"/>
<gfe:replicated-region name="child1">
<gfe:replicated-region name="grandChild11">
<gfe:cache-loader ref="c-loader"/>
</gfe:replicated-region>
<gfe:replicated-region name="grandChild12"/>
</gfe:replicated-region>
<gfe:replicated-region name="child2">
<gfe:cache-writer ref="c-writer"/>
</gfe:replicated-region>
</gfe:replicated-region>
<bean id="c-listener" class="org.springframework.data.gemfire.SimpleCacheListener"/>
<bean id="c-listener" class="org.springframework.data.gemfire.SimpleCacheListener"/>
<bean id="c-loader" class="org.springframework.data.gemfire.SimpleCacheLoader"/>
<bean id="c-writer" class="org.springframework.data.gemfire.SimpleCacheWriter"/>
</beans>
</beans>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:gfe="http://www.springframework.org/schema/gemfire"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/gemfire http://www.springframework.org/schema/gemfire/spring-gemfire.xsd
">
<bean class="org.springframework.data.gemfire.test.GemfireTestBeanPostProcessor"/>
<gfe:cache/>
<gfe:replicated-region id="Parent" persistent="false" destroy="true">
<gfe:replicated-region name="Child" data-policy="REPLICATE" persistent="true"/>
</gfe:replicated-region>
</beans>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:gfe="http://www.springframework.org/schema/gemfire"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/gemfire http://www.springframework.org/schema/gemfire/spring-gemfire.xsd
">
<bean class="org.springframework.data.gemfire.test.GemfireTestBeanPostProcessor"/>
<gfe:cache/>
<gfe:replicated-region id="Parent" persistent="false" destroy="true">
<gfe:replicated-region name="Child" data-policy="PERSISTENT_PARTITION"/>
</gfe:replicated-region>
</beans>