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:
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user