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:
John Blum
2013-12-09 10:50:16 -08:00
parent 101d977026
commit bb97756f8d
8 changed files with 273 additions and 91 deletions

View File

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

View File

@@ -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")) {

View File

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

View File

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

View File

@@ -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">

View File

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

View File

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

View File

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