Additional work and changes for JIRA feature requests SGF-207 and SGF-254 to enable developers with the ability to create Region templates to model attributes and configuration meta-data common to multiple, strongly-typed GemFire Region types (e.g. REPLICATE, PARTITION, etc).

(cherry picked from commit 2f66eca99b)

Signed-off-by: John Blum <jblum@pivotal.io>
This commit is contained in:
John Blum
2014-09-03 16:33:25 -07:00
parent 083b4e2986
commit 5af6a7e2f0
5 changed files with 265 additions and 88 deletions

View File

@@ -22,6 +22,7 @@ import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
@@ -29,6 +30,7 @@ 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.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
@@ -81,6 +83,8 @@ abstract class AbstractRegionParser extends AbstractSingleBeanDefinitionParser {
protected void doParseCommonRegionConfiguration(Element element, ParserContext parserContext,
BeanDefinitionBuilder builder, BeanDefinitionBuilder regionAttributesBuilder, boolean subRegion) {
mergeTemplateRegionAttributes(element, parserContext, builder, regionAttributesBuilder);
String resolvedCacheRef = ParsingUtils.resolveCacheReference(element.getAttribute("cache-ref"));
if (!subRegion) {
@@ -158,6 +162,45 @@ abstract class AbstractRegionParser extends AbstractSingleBeanDefinitionParser {
}
}
void mergeTemplateRegionAttributes(Element element, ParserContext parserContext,
BeanDefinitionBuilder regionBuilder, BeanDefinitionBuilder regionAttributesBuilder) {
String regionTemplate = getParentName(element);
if (StringUtils.hasText(regionTemplate)) {
if (parserContext.getRegistry().containsBeanDefinition(regionTemplate)) {
BeanDefinition regionTemplateDefinition = parserContext.getRegistry()
.getBeanDefinition(regionTemplate);
BeanDefinition regionTemplateAttributesDefinition = getRegionAttributesBeanDefinition(
regionTemplateDefinition);
if (regionTemplateAttributesDefinition != null) {
// NOTE we only need to merge the parent RegionAttributes with this since the parent will have
// already merged it's parent's RegionAttributes and so on...
regionAttributesBuilder.getRawBeanDefinition().overrideFrom(regionTemplateAttributesDefinition);
}
}
else {
parserContext.getReaderContext().error(String.format(
"The Region template [%1$s] must be defined in the Spring context configuration meta-data 'before' the Region [%2$s] using the template!",
regionTemplate, resolveId(element, regionBuilder.getRawBeanDefinition(), parserContext)), element);
}
}
}
BeanDefinition getRegionAttributesBeanDefinition(final BeanDefinition region) {
Assert.notNull(region, "The 'Region' BeanDefinition must not be null!");
Object regionAttributesDefinition = null;
if (region.getPropertyValues().contains("attributes")) {
PropertyValue regionAttributes = region.getPropertyValues().getPropertyValue("attributes");
regionAttributesDefinition = regionAttributes.getValue();
}
return (regionAttributesDefinition instanceof BeanDefinition ? (BeanDefinition) regionAttributesDefinition : null);
}
private void parseCollectionOfCustomSubElements(Element element, ParserContext parserContext,
BeanDefinitionBuilder builder, String className, String subElementName, String propertyName) {
List<Element> subElements = DomUtils.getChildElementsByTagName(element, subElementName,

View File

@@ -18,6 +18,8 @@ package org.springframework.data.gemfire.config;
import java.util.List;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.xml.ParserContext;
@@ -53,8 +55,6 @@ class PartitionedRegionParser extends AbstractRegionParser {
validateDataPolicyShortcutAttributesMutualExclusion(element, parserContext);
super.doParse(element, regionBuilder);
BeanDefinitionBuilder regionAttributesBuilder = BeanDefinitionBuilder.genericBeanDefinition(
RegionAttributesFactoryBean.class);
@@ -65,6 +65,8 @@ class PartitionedRegionParser extends AbstractRegionParser {
BeanDefinitionBuilder partitionAttributesBuilder = BeanDefinitionBuilder.genericBeanDefinition(
PartitionAttributesFactoryBean.class);
mergeTemplateRegionPartitionAttributes(element, parserContext, regionBuilder, partitionAttributesBuilder);
parseColocatedWith(element, regionBuilder, partitionAttributesBuilder, "colocated-with");
ParsingUtils.setPropertyValue(element, partitionAttributesBuilder, "copies", "redundantCopies");
ParsingUtils.setPropertyValue(element, partitionAttributesBuilder, "local-max-memory");
@@ -108,6 +110,40 @@ class PartitionedRegionParser extends AbstractRegionParser {
regionAttributesBuilder.addPropertyValue("partitionAttributes", partitionAttributesBuilder.getBeanDefinition());
}
void mergeTemplateRegionPartitionAttributes(Element element, ParserContext parserContext,
BeanDefinitionBuilder regionBuilder, BeanDefinitionBuilder partitionAttributesBuilder) {
String regionTemplate = getParentName(element);
if (StringUtils.hasText(regionTemplate)) {
if (parserContext.getRegistry().containsBeanDefinition(regionTemplate)) {
BeanDefinition regionTemplateDefinition = parserContext.getRegistry()
.getBeanDefinition(regionTemplate);
BeanDefinition regionTemplateAttributesDefinition = getRegionAttributesBeanDefinition(
regionTemplateDefinition);
if (regionTemplateAttributesDefinition != null) {
if (regionTemplateAttributesDefinition.getPropertyValues().contains("partitionAttributes")) {
PropertyValue partitionAttributes = regionTemplateAttributesDefinition.getPropertyValues()
.getPropertyValue("partitionAttributes");
Object partitionAttributesDefinition = partitionAttributes.getValue();
if (partitionAttributesDefinition instanceof BeanDefinition) {
partitionAttributesBuilder.getRawBeanDefinition().overrideFrom(
(BeanDefinition) partitionAttributesDefinition);
}
}
}
}
else {
parserContext.getReaderContext().error(String.format(
"The Region template [%1$s] must be defined in the Spring context configuration meta-data 'before' the Region [%2$s] using the template!",
regionTemplate, resolveId(element, regionBuilder.getRawBeanDefinition(), parserContext)), element);
}
}
}
private void parseColocatedWith(Element element, BeanDefinitionBuilder regionBuilder,
BeanDefinitionBuilder partitionAttributesBuilder, String attributeName) {
// NOTE rather than using a dependency (with depends-on) we could also set the colocatedWith property of the

View File

@@ -117,32 +117,21 @@ Configures a data source to be bound to a JNDI context for use with Gemfire tran
</xsd:annotation>
</xsd:element>
</xsd:sequence>
<xsd:attribute name="copy-on-read" type="xsd:string"
use="optional" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
Controls whether entry value retrieval methods return direct references to the entry value objects in the cache (false)
or copies of the objects (true).
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="id" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The name of the cache definition (by default "gemfireCache").]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="cache-xml-location" type="xsd:string"
use="optional">
<xsd:attribute name="cache-xml-location" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation source="org.springframework.core.io.Resource"><![CDATA[
The location of the GemFire cache xml file, as a Spring resource location: a URL, a "classpath:" pseudo URL,
or a relative file path.
The location of the GemFire cache.xml file as a Spring Resource location: a URL, a "classpath:" pseudo URL,
or a relative file system path.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="properties-ref" type="xsd:string"
use="optional">
<xsd:attribute name="properties-ref" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation source="java.util.Properties"><![CDATA[
The bean name of a Java Properties object that will be used for property substitution. For loading properties
@@ -150,8 +139,16 @@ consider using a dedicated utility such as the <util:*/> namespace and its 'prop
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="use-bean-factory-locator" type="xsd:string"
use="optional" default="true">
<xsd:attribute name="lazy-init" default="true">
<xsd:annotation>
<xsd:documentation><![CDATA[
Determines if the cache should be initialized automatically. Normally the cache will be lazily initialized,
i.e., during creation of another bean references it. For cases in which there are no declared dependencies on the cache,
set this attribute to false.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="use-bean-factory-locator" type="xsd:string" use="optional" default="true">
<xsd:annotation>
<xsd:documentation><![CDATA[
Indicates whether a bean factory locator is enabled (default) for this cache definition or not. The locator stores
@@ -160,60 +157,20 @@ when the same cache is used in multiple application context/bean factories insid
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="pdx-serializer-ref" type="xsd:string"
use="optional">
<xsd:attribute name="close" default="true">
<xsd:annotation>
<xsd:documentation><![CDATA[
Sets the PDX serializer for the cache. If this serializer is set, it will be consulted to see if it can serialize any
domain classes which are added to the cache in portable data exchange (PDX) format.
]]></xsd:documentation>
Determines if the cache should be closed when the application context is closed. This value is true by default
but should be set to false if deploying multiple applications in a jvm that share the same cache instance.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="pdx-disk-store" type="xsd:string"
use="optional">
<xsd:attribute name="copy-on-read" type="xsd:string" use="optional" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
Sets the name of the disk store to use for PDX meta data. When serializing objects in the PDX format,
the type definitions are persisted to disk. This setting controls which disk store is used for that persistence.
If not set, the metadata will go in the default disk store.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="pdx-persistent" type="xsd:string"
use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
Control whether the type metadata for PDX objects is persisted to disk.
Set to true if you are using persistent regions, WAN gateways or GemFire's JSON support.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="pdx-read-serialized" type="xsd:string"
use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
Sets the object preference to PdxInstance type. When a cached object that was serialized as a PDX is read from the cache
a PdxInstance will be returned instead of the actual domain class. The PdxInstance is an interface that provides run time
access to the fields of a PDX without deserializing the entire PDX. The PdxInstance implementation is a light weight wrapper
that simply refers to the raw bytes of the PDX that are kept in the cache. Using this method applications can choose to
access PdxInstance instead of Java object.
Note that a PdxInstance is only returned if a serialized PDX is found in the cache. If the cache contains a deserialized PDX,
then a domain class instance is returned instead of a PdxInstance.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="pdx-ignore-unread-fields" type="xsd:string"
use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
Controls whether pdx ignores fields that were unread during deserialization. The default is to preserve unread fields be
including their data during serialization. But if you configure the cache to ignore unread fields then their data will be
lost during serialization.
You should only set this attribute to true if you know this member will only be reading cache data. In this use case you
do not need to pay the cost of preserving the unread fields since you will never be reserializing pdx data.
]]></xsd:documentation>
Controls whether entry value retrieval methods return direct references to the entry value objects in the cache (false)
or copies of the objects (true).
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="critical-heap-percentage">
@@ -237,21 +194,55 @@ JavaDocs for com.gemstone.gemfire.cache.control.ResourceManager for more informa
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="close" default="true">
<xsd:attribute name="pdx-serializer-ref" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
Determines if the cache should be closed when the application context is closed. This value is
true by default but should be set to false if deploying multiple applications in a jvm that share the
same cache instance.
]]></xsd:documentation>
Sets the PDX serializer for the cache. If this serializer is set, it will be consulted to see if it can serialize any
domain classes which are added to the cache in portable data exchange (PDX) format.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="lazy-init" default="true">
<xsd:attribute name="pdx-disk-store" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
Determines if the cache should be initialized automatically. Normally the cache will be lazily initialized, i.e., during creation of another bean references it.
For cases in which there are no declared dependencies on the cache, set this attribute to false.
]]></xsd:documentation>
Sets the name of the disk store to use for PDX meta data. When serializing objects in the PDX format,
the type definitions are persisted to disk. This setting controls which disk store is used for that persistence.
If not set, the metadata will go in the default disk store.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="pdx-persistent" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
Control whether the type metadata for PDX objects is persisted to disk.
Set to true if you are using persistent Regions, WAN Gateways or GemFire's JSON support.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="pdx-read-serialized" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
Sets the object preference to PdxInstance type. When a cached object that was serialized as a PDX is read from the cache
a PdxInstance will be returned instead of the actual domain class. The PdxInstance is an interface that provides run time
access to the fields of a PDX without deserializing the entire PDX. The PdxInstance implementation is a light weight wrapper
that simply refers to the raw bytes of the PDX that are kept in the cache. Using this method applications can choose to
access PdxInstance instead of Java object.
Note that a PdxInstance is only returned if a serialized PDX is found in the cache. If the cache contains a deserialized PDX,
then a domain class instance is returned instead of a PdxInstance.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="pdx-ignore-unread-fields" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
Controls whether pdx ignores fields that were unread during deserialization. The default is to preserve unread fields be
including their data during serialization. But if you configure the cache to ignore unread fields then their data will be
lost during serialization.
You should only set this attribute to true if you know this member will only be reading cache data. In this use case you
do not need to pay the cost of preserving the unread fields since you will never be reserializing pdx data.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>

View File

@@ -19,11 +19,11 @@ package org.springframework.data.gemfire.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.List;
import javax.annotation.Resource;
import org.junit.Test;
@@ -33,18 +33,24 @@ import org.springframework.beans.factory.BeanIsAbstractException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.data.gemfire.test.GemfireTestApplicationContextInitializer;
import org.springframework.data.gemfire.test.support.CollectionUtils;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.util.ObjectUtils;
import com.gemstone.gemfire.cache.CacheLoader;
import com.gemstone.gemfire.cache.CacheLoaderException;
import com.gemstone.gemfire.cache.DataPolicy;
import com.gemstone.gemfire.cache.EntryOperation;
import com.gemstone.gemfire.cache.EvictionAction;
import com.gemstone.gemfire.cache.EvictionAlgorithm;
import com.gemstone.gemfire.cache.EvictionAttributes;
import com.gemstone.gemfire.cache.InterestPolicy;
import com.gemstone.gemfire.cache.LoaderHelper;
import com.gemstone.gemfire.cache.PartitionResolver;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.RegionAttributes;
import com.gemstone.gemfire.cache.Scope;
import com.gemstone.gemfire.cache.SubscriptionAttributes;
import com.gemstone.gemfire.cache.asyncqueue.AsyncEvent;
import com.gemstone.gemfire.cache.asyncqueue.AsyncEventListener;
import com.gemstone.gemfire.cache.partition.PartitionListenerAdapter;
@@ -73,6 +79,25 @@ public class TemplateRegionsNamespaceTests {
@Resource(name = "SimpleReplicateRegion")
private Region<Integer, String> simpleReplicateRegion;
@Resource(name = "InheritedReplicateRegion")
private Region<Long, String> inheritedReplicateRegion;
@Resource(name = "ComplexReplicateRegion")
private Region complexReplicateRegion;
protected static void assertRegionMetaData(final Region<?, ?> region, final String expectedRegionName) {
assertRegionMetaData(region, expectedRegionName, Region.SEPARATOR + expectedRegionName);
}
protected static void assertRegionMetaData(final Region<?, ?> region, final String expectedRegionName, final String expectedRegionPath) {
assertNotNull(String.format("The '%1$s' Region was not properly configured and initialized!",
expectedRegionName), region);
assertEquals(expectedRegionName, region.getName());
assertEquals(expectedRegionPath, region.getFullPath());
assertNotNull(String.format("The '%1$s' Region must have RegionAttributes defined!",
expectedRegionName), region.getAttributes());
}
@SuppressWarnings("deprecation")
protected static <K, V> void assertBaseRegionAttributes(final Region<K, V> region) {
assertNotNull("The Region must not be null!", region);
@@ -100,6 +125,25 @@ public class TemplateRegionsNamespaceTests {
assertEquals("Y", regionAttributes.getCacheWriter().toString());
}
protected static <K, V> void assertBaseReplicateRegionAttributes(final Region<K, V> replicateRegion) {
assertBaseRegionAttributes(replicateRegion);
assertEquals(2, replicateRegion.getAttributes().getConcurrencyLevel());
assertTrue(replicateRegion.getAttributes().getEnableAsyncConflation());
assertTrue(replicateRegion.getAttributes().getEnableSubscriptionConflation());
EvictionAttributes evictionAttributes = replicateRegion.getAttributes().getEvictionAttributes();
assertNotNull(evictionAttributes);
assertEquals(EvictionAction.OVERFLOW_TO_DISK, evictionAttributes.getAction());
assertEquals(EvictionAlgorithm.LRU_ENTRY, evictionAttributes.getAlgorithm());
assertEquals(1000, evictionAttributes.getMaximum());
SubscriptionAttributes subscriptionAttributes = replicateRegion.getAttributes().getSubscriptionAttributes();
assertNotNull(subscriptionAttributes);
assertEquals(InterestPolicy.CACHE_CONTENT, subscriptionAttributes.getInterestPolicy());
}
@Test
public void testNoAbstractRegionTemplateBeans() {
String[] beanNames = {
@@ -124,7 +168,66 @@ public class TemplateRegionsNamespaceTests {
@Test
public void testSimpleReplicateRegion() {
fail("Not Implemented!");
assertRegionMetaData(simpleReplicateRegion, "SimpleReplicateRegion");
assertEquals(DataPolicy.PERSISTENT_REPLICATE, simpleReplicateRegion.getAttributes().getDataPolicy());
assertEquals(8, simpleReplicateRegion.getAttributes().getConcurrencyLevel());
assertEquals(Integer.class, simpleReplicateRegion.getAttributes().getKeyConstraint());
assertTrue(simpleReplicateRegion.getAttributes().isLockGrantor());
assertEquals(Scope.GLOBAL, simpleReplicateRegion.getAttributes().getScope());
assertNull(simpleReplicateRegion.getAttributes().getValueConstraint());
assertNotNull(simpleReplicateRegion.getAttributes().getCacheListeners());
assertEquals(1, simpleReplicateRegion.getAttributes().getCacheListeners().length);
assertTrue(simpleReplicateRegion.getAttributes().getCacheListeners()[0] instanceof TestCacheListener);
assertEquals("Simple", simpleReplicateRegion.getAttributes().getCacheListeners()[0].toString());
assertNull(simpleReplicateRegion.getAttributes().getCacheLoader());
assertNull(simpleReplicateRegion.getAttributes().getCacheWriter());
}
@Test
public void testInheritedReplicateRegion() {
assertRegionMetaData(inheritedReplicateRegion, "InheritedReplicateRegion");
assertEquals(Scope.DISTRIBUTED_ACK, inheritedReplicateRegion.getAttributes().getScope());
assertBaseReplicateRegionAttributes(inheritedReplicateRegion);
}
@Test
@SuppressWarnings("deprecation")
public void testComplexReplicateRegion() {
assertRegionMetaData(complexReplicateRegion, "ComplexReplicateRegion");
assertEquals(DataPolicy.PERSISTENT_REPLICATE, complexReplicateRegion.getAttributes().getDataPolicy());
assertEquals(Scope.DISTRIBUTED_ACK, complexReplicateRegion.getAttributes().getScope());
assertFalse(complexReplicateRegion.getAttributes().getCloningEnabled());
assertEquals(2, complexReplicateRegion.getAttributes().getConcurrencyLevel());
assertTrue(complexReplicateRegion.getAttributes().isDiskSynchronous());
assertFalse(complexReplicateRegion.getAttributes().getEnableAsyncConflation());
assertTrue(complexReplicateRegion.getAttributes().getEnableSubscriptionConflation());
assertFalse(complexReplicateRegion.getAttributes().getIgnoreJTA());
assertEquals(1000, complexReplicateRegion.getAttributes().getInitialCapacity());
assertEquals(Integer.class, complexReplicateRegion.getAttributes().getKeyConstraint());
assertEquals(0.90f, complexReplicateRegion.getAttributes().getLoadFactor());
assertTrue(complexReplicateRegion.getAttributes().getStatisticsEnabled());
assertTrue(complexReplicateRegion.getAttributes().getIndexMaintenanceSynchronous());
assertEquals(String.class, complexReplicateRegion.getAttributes().getValueConstraint());
assertNotNull(complexReplicateRegion.getAttributes().getCacheListeners());
assertEquals(1, complexReplicateRegion.getAttributes().getCacheListeners().length);
assertTrue(complexReplicateRegion.getAttributes().getCacheListeners()[0] instanceof TestCacheListener);
assertEquals("ComplexListener", complexReplicateRegion.getAttributes().getCacheListeners()[0].toString());
assertNotNull(complexReplicateRegion.getAttributes().getCacheLoader());
assertEquals("ComplexLoader", complexReplicateRegion.getAttributes().getCacheLoader().toString());
assertNotNull(complexReplicateRegion.getAttributes().getCacheWriter());
assertEquals("Y", complexReplicateRegion.getAttributes().getCacheWriter().toString());
EvictionAttributes evictionAttributes = complexReplicateRegion.getAttributes().getEvictionAttributes();
assertNotNull(evictionAttributes);
assertEquals(EvictionAction.OVERFLOW_TO_DISK, evictionAttributes.getAction());
assertEquals(EvictionAlgorithm.LRU_ENTRY, evictionAttributes.getAlgorithm());
assertEquals(1024, evictionAttributes.getMaximum());
SubscriptionAttributes subscriptionAttributes = complexReplicateRegion.getAttributes().getSubscriptionAttributes();
assertNotNull(subscriptionAttributes);
assertEquals(InterestPolicy.ALL, subscriptionAttributes.getInterestPolicy());
}
protected static interface Nameable {

View File

@@ -19,7 +19,7 @@
<gfe:gateway-sender id="TestGatewaySender" remote-distributed-system-id="123" manual-start="true" persistent="false"
parallel="true" dispatcher-threads="8"/>
<!-- Generic Region -->
<!-- Region Templates -->
<gfe:region-template id="BaseRegion" cloning-enabled="true" concurrency-checks-enabled="false"
disk-synchronous="true" ignore-jta="true" initial-capacity="1000"
@@ -34,7 +34,8 @@
</gfe:region-template>
<gfe:region-template id="ExtendedRegionWithOverrides" cloning-enabled="false" concurrency-checks-enabled="true"
disk-synchronous="false" ignore-jta="false" key-constraint="java.lang.String" template="BaseRegion">
disk-synchronous="false" ignore-jta="false" key-constraint="java.lang.String" persistent="false"
template="BaseRegion">
<gfe:cache-listener>
<bean class="org.springframework.data.gemfire.config.TemplateRegionsNamespaceTests$TestCacheListener" p:name="Z"/>
</gfe:cache-listener>
@@ -45,7 +46,7 @@
<!-- REPLICATE Region -->
<gfe:replicated-region-template id="BaseReplicateRegion" concurrency-level="2" enable-async-conflation="true"
enable-subscription-conflation="true" template="BaseRegion">
enable-subscription-conflation="true" scope="global" template="BaseRegion">
<gfe:subscription type="CACHE_CONTENT"/>
<gfe:eviction type="ENTRY_COUNT" threshold="1000" action="OVERFLOW_TO_DISK"/>
</gfe:replicated-region-template>
@@ -53,19 +54,19 @@
<gfe:replicated-region id="SimpleReplicateRegion" persistent="true" concurrency-level="8" is-lock-grantor="true" scope="global"
key-constraint="java.lang.Integer">
<gfe:cache-listener>
<bean class="org.springframework.data.gemfire.config.TemplateRegionsNamespaceTests$TestCacheListener" p:name="A"/>
<bean class="org.springframework.data.gemfire.config.TemplateRegionsNamespaceTests$TestCacheListener" p:name="Simple"/>
</gfe:cache-listener>
</gfe:replicated-region>
<gfe:replicated-region id="InheritedReplicateRegion" template="BaseReplicateRegion"/>
<gfe:replicated-region id="ComplexReplicateRegion" persistent="true" key-constraint="java.lang.Integer" cloning-enabled="false"
template="BaseReplicateRegion">
<gfe:replicated-region id="ComplexReplicateRegion" persistent="true" key-constraint="java.lang.Integer" ignore-jta="false"
enable-async-conflation="false" cloning-enabled="false" template="BaseReplicateRegion">
<gfe:cache-listener>
<bean class="org.springframework.data.gemfire.config.TemplateRegionsNamespaceTests$TestCacheListener" p:name="AAA"/>
<bean class="org.springframework.data.gemfire.config.TemplateRegionsNamespaceTests$TestCacheListener" p:name="ComplexListener"/>
</gfe:cache-listener>
<gfe:cache-loader>
<bean class="org.springframework.data.gemfire.config.TemplateRegionsNamespaceTests$TestCacheLoader" p:name="xyz"/>
<bean class="org.springframework.data.gemfire.config.TemplateRegionsNamespaceTests$TestCacheLoader" p:name="ComplexLoader"/>
</gfe:cache-loader>
<gfe:subscription type="ALL"/>
<gfe:eviction type="ENTRY_COUNT" threshold="1024" action="OVERFLOW_TO_DISK"/>
@@ -74,7 +75,8 @@
<!-- PARTITION Region -->
<gfe:partitioned-region-template id="BasePartitionRegion" copies="2" local-max-memory="1000" total-max-memory="4000"
total-buckets="77" recovery-delay="1000" startup-recovery-delay="5000">
total-buckets="77" recovery-delay="1000" startup-recovery-delay="5000"
template="ExtendedRegionWithOverrides">
<gfe:partition-resolver>
<bean class="org.springframework.data.gemfire.config.TemplateRegionsNamespaceTests$TestPartitionResolver" p:name="A"/>
</gfe:partition-resolver>
@@ -85,6 +87,8 @@
<gfe:eviction type="MEMORY_SIZE" threshold="4000" action="OVERFLOW_TO_DISK"/>
</gfe:partitioned-region-template>
<!-- LOCAL Region -->
<gfe:local-region-template id="BaseLocalRegion" concurrency-level="4">
<gfe:eviction type="ENTRY_COUNT" threshold="8192" action="LOCAL_DESTROY"/>
</gfe:local-region-template>