Fixes JIRA issue SGF-241 adding support for defining client sub-Regions using the gfe:client-region XML namespace element in an nested fashion.
This commit is contained in:
@@ -50,6 +50,7 @@ import com.gemstone.gemfire.internal.cache.GemFireCacheImpl;
|
||||
* @author David Turanski
|
||||
* @author John Blum
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> implements BeanFactoryAware,
|
||||
DisposableBean {
|
||||
|
||||
@@ -74,6 +75,8 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
|
||||
|
||||
private Interest<K>[] interests;
|
||||
|
||||
private Region<?, ?> parent;
|
||||
|
||||
private RegionAttributes<K, V> attributes;
|
||||
|
||||
private Resource snapshot;
|
||||
@@ -96,7 +99,7 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
|
||||
Assert.isTrue(((GemFireCacheImpl) cache).isClient(), "A client-cache instance is required.");
|
||||
}
|
||||
|
||||
final ClientCache clientCache = (ClientCache) cache;
|
||||
ClientCache clientCache = (ClientCache) cache;
|
||||
|
||||
ClientRegionFactory<K, V> factory = clientCache.createClientRegionFactory(resolveClientRegionShortcut());
|
||||
|
||||
@@ -142,8 +145,18 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
|
||||
factory.setDiskStoreName(diskStoreName);
|
||||
}
|
||||
|
||||
Region<K, V> clientRegion = factory.create(regionName);
|
||||
log.info("Created new cache region [" + regionName + "]");
|
||||
Region<K, V> clientRegion = (this.parent != null ? factory.createSubregion(parent, regionName)
|
||||
: factory.create(regionName));
|
||||
|
||||
if (log.isInfoEnabled()) {
|
||||
if (parent != null) {
|
||||
log.info(String.format("Created new Client Cache sub-Region [%1$s] under parent Region [%2$s].",
|
||||
regionName, parent.getName()));
|
||||
}
|
||||
else {
|
||||
log.info(String.format("Created new Client Cache Region [%1$s].", regionName));
|
||||
}
|
||||
}
|
||||
|
||||
if (snapshot != null) {
|
||||
clientRegion.loadSnapshot(snapshot.getInputStream());
|
||||
@@ -481,6 +494,10 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
|
||||
setDataPolicy(resolvedDataPolicy);
|
||||
}
|
||||
|
||||
public void setParent(Region<?, ?> parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
protected boolean isPersistent() {
|
||||
return Boolean.TRUE.equals(persistent);
|
||||
}
|
||||
|
||||
@@ -35,9 +35,10 @@ import org.springframework.util.xml.DomUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Base class for all Region Parsers
|
||||
*
|
||||
* Abstract base class encapsulating functionality common to all Region Parsers.
|
||||
* <p/>
|
||||
* @author David Turanski
|
||||
* @author John Blum
|
||||
*/
|
||||
abstract class AbstractRegionParser extends AbstractSingleBeanDefinitionParser {
|
||||
|
||||
@@ -68,9 +69,7 @@ abstract class AbstractRegionParser extends AbstractSingleBeanDefinitionParser {
|
||||
protected void doParseCommonRegionConfiguration(Element element, ParserContext parserContext,
|
||||
BeanDefinitionBuilder builder, BeanDefinitionBuilder regionAttributesBuilder, boolean subRegion) {
|
||||
|
||||
String cacheRef = element.getAttribute("cache-ref");
|
||||
String resolvedCacheRef = (StringUtils.hasText(cacheRef) ? cacheRef
|
||||
: GemfireConstants.DEFAULT_GEMFIRE_CACHE_NAME);
|
||||
String resolvedCacheRef = ParsingUtils.resolveCacheReference(element.getAttribute("cache-ref"));
|
||||
|
||||
if (!subRegion) {
|
||||
builder.addPropertyReference("cache", resolvedCacheRef);
|
||||
@@ -89,9 +88,9 @@ abstract class AbstractRegionParser extends AbstractSingleBeanDefinitionParser {
|
||||
}
|
||||
|
||||
ParsingUtils.parseOptionalRegionAttributes(parserContext, element, regionAttributesBuilder);
|
||||
ParsingUtils.parseSubscription(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);
|
||||
|
||||
@@ -146,18 +145,6 @@ abstract class AbstractRegionParser extends AbstractSingleBeanDefinitionParser {
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
@@ -174,6 +161,18 @@ abstract class AbstractRegionParser extends AbstractSingleBeanDefinitionParser {
|
||||
}
|
||||
}
|
||||
|
||||
protected 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 findSubRegionElements(Element parent, String parentPath, Map<String, Element> allSubRegionElements) {
|
||||
for (Element element : DomUtils.getChildElements(parent)) {
|
||||
if (element.getLocalName().endsWith("region")) {
|
||||
|
||||
@@ -46,18 +46,19 @@ class ClientRegionParser extends AbstractRegionParser {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
|
||||
super.doParse(element, builder);
|
||||
protected void doParseRegion(Element element, ParserContext parserContext, BeanDefinitionBuilder builder,
|
||||
boolean subRegion) {
|
||||
|
||||
validateDataPolicyShortcutMutualExclusion(element, parserContext);
|
||||
|
||||
String cacheRefAttributeValue = element.getAttribute("cache-ref");
|
||||
String resolvedCacheRef = ParsingUtils.resolveCacheReference(element.getAttribute("cache-ref"));
|
||||
|
||||
builder.addPropertyReference("cache", (StringUtils.hasText(cacheRefAttributeValue) ? cacheRefAttributeValue
|
||||
: GemfireConstants.DEFAULT_GEMFIRE_CACHE_NAME));
|
||||
if (!subRegion) {
|
||||
builder.addPropertyReference("cache", resolvedCacheRef);
|
||||
ParsingUtils.setPropertyValue(element, builder, "close");
|
||||
ParsingUtils.setPropertyValue(element, builder, "destroy");
|
||||
}
|
||||
|
||||
ParsingUtils.setPropertyValue(element, builder, "close");
|
||||
ParsingUtils.setPropertyValue(element, builder, "destroy");
|
||||
ParsingUtils.setPropertyValue(element, builder, "data-policy", "dataPolicyName");
|
||||
ParsingUtils.setPropertyValue(element, builder, "name");
|
||||
ParsingUtils.setPropertyValue(element, builder, "persistent");
|
||||
@@ -72,8 +73,8 @@ class ClientRegionParser extends AbstractRegionParser {
|
||||
|
||||
ParsingUtils.parseOptionalRegionAttributes(parserContext, element, regionAttributesBuilder);
|
||||
ParsingUtils.parseStatistics(element, regionAttributesBuilder);
|
||||
ParsingUtils.parseEviction(parserContext, element, regionAttributesBuilder);
|
||||
ParsingUtils.parseExpiration(parserContext, element, regionAttributesBuilder);
|
||||
ParsingUtils.parseEviction(parserContext, element, regionAttributesBuilder);
|
||||
|
||||
builder.addPropertyValue("attributes", regionAttributesBuilder.getBeanDefinition());
|
||||
|
||||
@@ -107,14 +108,10 @@ class ClientRegionParser extends AbstractRegionParser {
|
||||
if (!interests.isEmpty()) {
|
||||
builder.addPropertyValue("interests", interests);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doParseRegion(Element element, ParserContext parserContext, BeanDefinitionBuilder builder,
|
||||
boolean subRegion) {
|
||||
throw new UnsupportedOperationException(String.format(
|
||||
"doParseRegion(:Element, :ParserContext, :BeanDefinitionBuilder, :boolean) is not supported on %1$s",
|
||||
getClass().getName()));
|
||||
if (!subRegion) {
|
||||
parseSubRegions(element, parserContext, resolvedCacheRef);
|
||||
}
|
||||
}
|
||||
|
||||
private void validateDataPolicyShortcutMutualExclusion(final Element element, final ParserContext parserContext) {
|
||||
@@ -134,6 +131,12 @@ class ClientRegionParser extends AbstractRegionParser {
|
||||
}
|
||||
}
|
||||
|
||||
private void parseCommonInterestAttributes(Element element, BeanDefinitionBuilder builder) {
|
||||
ParsingUtils.setPropertyValue(element, builder, "durable", "durable");
|
||||
ParsingUtils.setPropertyValue(element, builder, "result-policy", "policy");
|
||||
ParsingUtils.setPropertyValue(element, builder, "receive-values", "receiveValues");
|
||||
}
|
||||
|
||||
private Object parseKeyInterest(Element keyInterestElement, ParserContext parserContext) {
|
||||
BeanDefinitionBuilder keyInterestBuilder = BeanDefinitionBuilder.genericBeanDefinition(Interest.class);
|
||||
|
||||
@@ -153,10 +156,4 @@ class ClientRegionParser extends AbstractRegionParser {
|
||||
return regexInterestBuilder.getBeanDefinition();
|
||||
}
|
||||
|
||||
private void parseCommonInterestAttributes(Element element, BeanDefinitionBuilder builder) {
|
||||
ParsingUtils.setPropertyValue(element, builder, "durable", "durable");
|
||||
ParsingUtils.setPropertyValue(element, builder, "result-policy", "policy");
|
||||
ParsingUtils.setPropertyValue(element, builder, "receive-values", "receiveValues");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.ManagedArray;
|
||||
import org.springframework.beans.factory.support.ManagedList;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.core.Conventions;
|
||||
@@ -39,7 +38,7 @@ import com.gemstone.gemfire.cache.ResumptionAction;
|
||||
import com.gemstone.gemfire.cache.Scope;
|
||||
|
||||
/**
|
||||
* Various minor utilities used by the parser.
|
||||
* Utilities used by the Spring Data GemFire XML Namespace parsers.
|
||||
* <p/>
|
||||
* @author Costin Leau
|
||||
* @author David Turanski
|
||||
@@ -271,22 +270,25 @@ 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 a boolean indicating whether Region expiration attributes were specified.
|
||||
*/
|
||||
static boolean parseExpiration(ParserContext parserContext, Element element, BeanDefinitionBuilder attrBuilder) {
|
||||
boolean result = parseExpiration(element, "region-ttl", "regionTimeToLive", attrBuilder);
|
||||
static boolean parseExpiration(ParserContext parserContext, Element element,
|
||||
BeanDefinitionBuilder regionAttributesBuilder) {
|
||||
|
||||
result |= parseExpiration(element, "region-tti", "regionIdleTimeout", attrBuilder);
|
||||
result |= parseExpiration(element, "entry-ttl", "entryTimeToLive", attrBuilder);
|
||||
result |= parseExpiration(element, "entry-tti", "entryIdleTimeout", attrBuilder);
|
||||
result |= parseCustomExpiration(parserContext, element,"custom-entry-ttl","customEntryTimeToLive",attrBuilder);
|
||||
result |= parseCustomExpiration(parserContext, element,"custom-entry-tti","customEntryIdleTimeout",attrBuilder);
|
||||
boolean result = parseExpiration(element, "region-ttl", "regionTimeToLive", regionAttributesBuilder);
|
||||
|
||||
result |= parseExpiration(element, "region-tti", "regionIdleTimeout", regionAttributesBuilder);
|
||||
result |= parseExpiration(element, "entry-ttl", "entryTimeToLive", regionAttributesBuilder);
|
||||
result |= parseExpiration(element, "entry-tti", "entryIdleTimeout", regionAttributesBuilder);
|
||||
result |= parseCustomExpiration(parserContext, element,"custom-entry-ttl","customEntryTimeToLive",
|
||||
regionAttributesBuilder);
|
||||
result |= parseCustomExpiration(parserContext, element,"custom-entry-tti","customEntryIdleTimeout",
|
||||
regionAttributesBuilder);
|
||||
|
||||
// TODO why?
|
||||
if (result) {
|
||||
// turn on statistics
|
||||
attrBuilder.addPropertyValue("statisticsEnabled", Boolean.TRUE);
|
||||
regionAttributesBuilder.addPropertyValue("statisticsEnabled", Boolean.TRUE);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -314,7 +316,8 @@ abstract class ParsingUtils {
|
||||
String indexUpdateType = element.getAttribute("index-update-type");
|
||||
|
||||
if (StringUtils.hasText(indexUpdateType)) {
|
||||
regionAttributesBuilder.addPropertyValue("indexMaintenanceSynchronous", "synchronous".equals(indexUpdateType));
|
||||
regionAttributesBuilder.addPropertyValue("indexMaintenanceSynchronous",
|
||||
"synchronous".equals(indexUpdateType));
|
||||
}
|
||||
|
||||
String concurrencyChecksEnabled = element.getAttribute("concurrency-checks-enabled");
|
||||
@@ -433,4 +436,9 @@ abstract class ParsingUtils {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static String resolveCacheReference(final String cacheRef) {
|
||||
return (StringUtils.hasText(cacheRef) ? cacheRef : GemfireConstants.DEFAULT_GEMFIRE_CACHE_NAME);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -874,10 +874,11 @@ The name of the region definition.
|
||||
<!-- -->
|
||||
<xsd:group name="subRegionGroup">
|
||||
<xsd:choice>
|
||||
<xsd:element name="lookup-region" type="lookupSubRegionType" />
|
||||
<xsd:element name="replicated-region" type="replicatedSubRegionType" />
|
||||
<xsd:element name="partitioned-region" type="partitionedSubRegionType" />
|
||||
<xsd:element name="local-region" type="localSubRegionType" />
|
||||
<xsd:element name="lookup-region" type="lookupSubRegionType"/>
|
||||
<xsd:element name="replicated-region" type="replicatedSubRegionType"/>
|
||||
<xsd:element name="partitioned-region" type="partitionedSubRegionType"/>
|
||||
<xsd:element name="local-region" type="localSubRegionType"/>
|
||||
<xsd:element name="client-region" type="clientSubRegionType"/>
|
||||
</xsd:choice>
|
||||
</xsd:group>
|
||||
<!-- -->
|
||||
@@ -965,7 +966,6 @@ Subscription policy for the replicated region.
|
||||
<xsd:attribute name="type" type="subscriptionPolicyType" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="eviction" minOccurs="0" maxOccurs="1">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
@@ -987,10 +987,9 @@ The action to take when performing eviction.
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:group ref="subRegionGroup" minOccurs="0" maxOccurs="unbounded" />
|
||||
</xsd:sequence>
|
||||
<xsd:attributeGroup ref="distributedRegionAttributes" />
|
||||
<xsd:attributeGroup ref="distributedRegionAttributes"/>
|
||||
<xsd:attribute name="concurrency-level">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
@@ -1048,7 +1047,7 @@ The name of the region definition.
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
<!-- -->
|
||||
<xsd:element name="replicated-region" type="replicatedRegionType" />
|
||||
<xsd:element name="replicated-region" type="replicatedRegionType"/>
|
||||
<!-- -->
|
||||
<xsd:complexType name="baseLocalRegionType">
|
||||
<xsd:annotation>
|
||||
@@ -1130,7 +1129,7 @@ The name of the region definition.
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
<!-- -->
|
||||
<xsd:element name="local-region" type="localRegionType" />
|
||||
<xsd:element name="local-region" type="localRegionType"/>
|
||||
<!-- -->
|
||||
<xsd:complexType name="basePartitionedRegionType">
|
||||
<xsd:annotation>
|
||||
@@ -1348,8 +1347,7 @@ The name of the region definition.
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
<!-- -->
|
||||
<xsd:element name="partitioned-region" type="partitionedRegionType" />
|
||||
|
||||
<xsd:element name="partitioned-region" type="partitionedRegionType"/>
|
||||
<!-- -->
|
||||
<xsd:complexType name="expirationType">
|
||||
<xsd:attribute name="timeout" type="xsd:string" default="0">
|
||||
@@ -1394,7 +1392,6 @@ When the region or cached object expires, it is destroyed locally only. Not supp
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
<!-- -->
|
||||
<xsd:complexType name="customExpirationType">
|
||||
<xsd:sequence>
|
||||
@@ -1416,7 +1413,6 @@ use inner bean declarations.
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
<!-- -->
|
||||
<xsd:complexType name="evictionType">
|
||||
<xsd:sequence minOccurs="0" maxOccurs="1">
|
||||
@@ -1491,7 +1487,7 @@ reclaim memory.
|
||||
</xsd:enumeration>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<!-- -->
|
||||
<xsd:simpleType name="subscriptionPolicyType">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:enumeration value="ALL">
|
||||
@@ -1646,7 +1642,7 @@ The name of the bean defining the GemFire cache (by default 'gemfireCache').
|
||||
<!-- -->
|
||||
<xsd:element name="disk-store" type="diskStoreType" />
|
||||
<!-- -->
|
||||
<xsd:element name="client-region">
|
||||
<xsd:complexType name="baseClientRegionType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation
|
||||
source="org.springframework.data.gemfire.client.ClientRegionFactoryBean"><![CDATA[
|
||||
@@ -1659,12 +1655,10 @@ which it receives its data. The client can hold some data locally or forward all
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="readOnlyRegionType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="cache-loader" type="beanDeclarationType"
|
||||
minOccurs="0" maxOccurs="1">
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="baseReadOnlyRegionType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="cache-loader" type="beanDeclarationType" minOccurs="0" maxOccurs="1">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="com.gemstone.gemfire.cache.CacheLoader"><![CDATA[
|
||||
The cache loader definition for this region. A cache loader allows data to be placed into a region.
|
||||
@@ -1676,8 +1670,7 @@ The cache loader definition for this region. A cache loader allows data to be pl
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
<xsd:element name="cache-writer" type="beanDeclarationType"
|
||||
minOccurs="0" maxOccurs="1">
|
||||
<xsd:element name="cache-writer" type="beanDeclarationType" minOccurs="0" maxOccurs="1">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="com.gemstone.gemfire.cache.CacheWriter"><![CDATA[
|
||||
The cache writer definition for this region. A cache writer acts as a dedicated synchronous listener that is notified
|
||||
@@ -1693,8 +1686,8 @@ arbitrarily pick one.
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
<xsd:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:element name="key-interest">
|
||||
<xsd:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:element name="key-interest">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Key based interest. If the key is a List, then all the keys in the List will be registered. The key can also be the
|
||||
@@ -1728,7 +1721,7 @@ use the inner bean declaration.
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="regex-interest">
|
||||
<xsd:element name="regex-interest">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Regular expression based interest. If the pattern is '.*' then all keys of any type will be pushed to the client.
|
||||
@@ -1742,8 +1735,8 @@ Regular expression based interest. If the pattern is '.*' then all keys of any t
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
<xsd:element name="eviction" minOccurs="0" maxOccurs="1">
|
||||
</xsd:choice>
|
||||
<xsd:element name="eviction" minOccurs="0" maxOccurs="1">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Eviction policy for the partitioned region.
|
||||
@@ -1764,8 +1757,9 @@ The action to take when performing eviction.
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="data-policy" type="xsd:string"
|
||||
<xsd:group ref="subRegionGroup" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="data-policy" type="xsd:string"
|
||||
use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
@@ -1780,7 +1774,7 @@ cache to differ from other caches.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="pool-name" type="xsd:string"
|
||||
<xsd:attribute name="pool-name" type="xsd:string"
|
||||
use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
@@ -1788,7 +1782,7 @@ The name of the pool used by this client. If not set, a default pool (initialize
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="shortcut" use="optional">
|
||||
<xsd:attribute name="shortcut" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The ClientRegionShortcut for this region. Allows easy initialization of the region based on defaults.
|
||||
@@ -1808,10 +1802,33 @@ The ClientRegionShortcut for this region. Allows easy initialization of the regi
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
<!-- -->
|
||||
<xsd:complexType name="clientRegionType">
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="baseClientRegionType">
|
||||
<xsd:attributeGroup ref="topLevelRegionAttributes" />
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
<!-- -->
|
||||
<xsd:complexType name="clientSubRegionType">
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="baseClientRegionType">
|
||||
<xsd:attribute name="name" type="xsd:string" use="required">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The name of the region definition.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
<!-- -->
|
||||
<xsd:element name="client-region" type="clientRegionType"/>
|
||||
<!-- -->
|
||||
<xsd:complexType name="connectionType">
|
||||
<xsd:attribute name="host" type="xsd:string">
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* 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.client;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.gemfire.ForkUtil;
|
||||
import org.springframework.data.gemfire.GemfireTemplate;
|
||||
import org.springframework.data.gemfire.fork.SpringCacheServerProcess;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import com.gemstone.gemfire.cache.Region;
|
||||
import com.gemstone.gemfire.cache.client.ClientCache;
|
||||
|
||||
/**
|
||||
* The ClientSubRegionTest class is a test suite of test cases testing SubRegion functionality from a client
|
||||
* GemFire Cache.
|
||||
* <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("clientcache-with-subregion-config.xml")
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SuppressWarnings("unused")
|
||||
public class ClientSubRegionTest {
|
||||
|
||||
@Autowired
|
||||
private ClientCache clientCache;
|
||||
|
||||
@Resource(name = "parentTemplate")
|
||||
private GemfireTemplate parentTemplate;
|
||||
|
||||
@Resource(name = "childTemplate")
|
||||
private GemfireTemplate childTemplate;
|
||||
|
||||
@Resource(name = "Parent")
|
||||
private Region parent;
|
||||
|
||||
@Resource(name = "/Parent/Child")
|
||||
private Region child;
|
||||
|
||||
@BeforeClass
|
||||
public static void startCacheServer() throws Exception {
|
||||
ForkUtil.startCacheServer(SpringCacheServerProcess.class.getName() + " "
|
||||
+ "/org/springframework/data/gemfire/client/servercache-with-region-for-client.xml");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGemFireSubRegionCreationConfiguration() {
|
||||
assertNotNull("The Client Cache was not properly initialized!", clientCache);
|
||||
|
||||
Region parent = clientCache.getRegion("Parent");
|
||||
|
||||
assertNotNull(parent);
|
||||
assertEquals("Parent", parent.getName());
|
||||
assertEquals("/Parent", parent.getFullPath());
|
||||
|
||||
Region child = parent.getSubregion("Child");
|
||||
|
||||
assertNotNull(child);
|
||||
assertEquals("Child", child.getName());
|
||||
assertEquals("/Parent/Child", child.getFullPath());
|
||||
|
||||
Region clientCacheChild = clientCache.getRegion("/Parent/Child");
|
||||
|
||||
assertSame(child, clientCacheChild);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpringSubRegionCreationConfiguration() {
|
||||
assertNotNull(parent);
|
||||
assertEquals("Parent", parent.getName());
|
||||
assertEquals("/Parent", parent.getFullPath());
|
||||
assertNotNull(child);
|
||||
assertEquals("Child", child.getName());
|
||||
assertEquals("/Parent/Child", child.getFullPath());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTemplateCreationConfiguration() {
|
||||
assertNotNull(parentTemplate);
|
||||
assertSame(parent, parentTemplate.getRegion());
|
||||
assertNotNull(childTemplate);
|
||||
assertSame(child, childTemplate.getRegion());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:gfe="http://www.springframework.org/schema/gemfire"
|
||||
xmlns:p="http://www.springframework.org/schema/p"
|
||||
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
|
||||
">
|
||||
|
||||
<gfe:client-cache/>
|
||||
|
||||
<gfe:pool>
|
||||
<gfe:server host="localhost" port="54321"/>
|
||||
</gfe:pool>
|
||||
|
||||
<gfe:client-region id="Parent" shortcut="PROXY">
|
||||
<gfe:client-region name="Child" shortcut="PROXY"/>
|
||||
</gfe:client-region>
|
||||
|
||||
<bean id="parentTemplate" class="org.springframework.data.gemfire.GemfireTemplate" p:region-ref="Parent"/>
|
||||
|
||||
<bean id="childTemplate" class="org.springframework.data.gemfire.GemfireTemplate" p:region-ref="/Parent/Child"/>
|
||||
|
||||
</beans>
|
||||
@@ -11,4 +11,8 @@
|
||||
<gfe:cache-server auto-startup="true" port="54321"/>
|
||||
<gfe:local-region id="localAppDataRegion" name="LocalAppData"/>
|
||||
|
||||
<gfe:replicated-region id="Parent" persistent="false">
|
||||
<gfe:replicated-region name="Child" persistent="false"/>
|
||||
</gfe:replicated-region>
|
||||
|
||||
</beans>
|
||||
|
||||
Reference in New Issue
Block a user