added subregion support

This commit is contained in:
David Turanski
2012-06-08 10:19:09 -04:00
parent 40cb46a682
commit b740727b9b
14 changed files with 1834 additions and 1237 deletions

View File

@@ -1,37 +0,0 @@
package org.springframework.data.gemfire;
import java.util.List;
import com.gemstone.gemfire.cache.RegionAttributes;
/**
*
* @author David Turanski
*
* @param <K>
* @param <V>
*/
public class SubRegion<K, V> {
private final RegionAttributes<K, V> regionAttributes;
private final String regionName;
private List<SubRegion<?,?>> subRegions;
public SubRegion(String regionName, RegionAttributes<K, V> regionAttributes) {
this.regionAttributes = regionAttributes;
this.regionName = regionName;
}
public RegionAttributes<K, V> getRegionAttributes() {
return regionAttributes;
}
public String getRegionName() {
return regionName;
}
public List<SubRegion<?, ?>> getSubRegions() {
return subRegions;
}
public void setSubRegions(List<SubRegion<?, ?>> subRegions) {
this.subRegions = subRegions;
}
}

View File

@@ -1,42 +1,79 @@
/*
* Copyright 2010-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.gemfire;
import java.util.List;
import org.springframework.beans.factory.BeanNameAware;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
import com.gemstone.gemfire.cache.AttributesFactory;
import com.gemstone.gemfire.cache.Region;
public class SubRegionFactoryBean<K,V> extends AttributesFactory<K,V> implements FactoryBean<SubRegion<K, V>>, InitializingBean {
@SuppressWarnings("deprecation")
/**
* FactoryBean for creating a Gemfire Region as a subregion
* @author David Turanski
*
* @param <K> - Region Key Type
* @param <V> - Region Value Type
*/
public class SubRegionFactoryBean<K, V> extends AttributesFactory<K, V> implements FactoryBean<Region<K, V>>,
InitializingBean {
protected final Log log = LogFactory.getLog(getClass());
@SuppressWarnings("unused")
private String name;
private SubRegion<K,V> subRegion;
private String regionName;
private List<SubRegion<?,?>> subRegions;
public void setName(String name) {
this.name = name;
}
private Region<K, V> subRegion;
public void setSubRegions(List<SubRegion<?, ?>> subRegions) {
this.subRegions = subRegions;
private Region<?, ?> parent;
private boolean lookupOnly;
@Override
public void afterPropertiesSet() throws Exception {
Assert.notNull(parent, "parent region must not be null");
this.subRegion = parent.getSubregion(regionName);
if (this.subRegion == null) {
if (lookupOnly) {
throw new BeanInitializationException("Cannot find region [" + regionName + "] in cache "
+ parent.getRegionService());
}
else {
log.debug("creating subregion of [" + parent.getFullPath() + "] with name " + regionName);
this.subRegion = this.parent.createSubregion(regionName, create());
}
}
}
@Override
public void afterPropertiesSet() throws Exception {
this.subRegion = new SubRegion<K,V>(name,create());
this.subRegion.setSubRegions(this.subRegions);
}
@Override
public SubRegion<K, V> getObject() throws Exception {
public Region<K, V> getObject() throws Exception {
return this.subRegion;
}
@Override
public Class<?> getObjectType() {
return SubRegion.class;
return Region.class;
}
@Override
@@ -44,4 +81,37 @@ public class SubRegionFactoryBean<K,V> extends AttributesFactory<K,V> implements
return true;
}
/**
* Set the bean name - the same as the subregion full path
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* Set the simple name of the region
* @param regionName
*/
public void setRegionName(String regionName) {
this.regionName = regionName;
}
/**
* Set the parent Region
* @param parent
*/
public void setParent(Region<?, ?> parent) {
this.parent = parent;
}
/**
* Set to true if the subregion should already exist, e.g., specified by
* &lt;lookup-region&gt;
* @param lookupOnly
*/
public void setLookupOnly(boolean lookupOnly) {
this.lookupOnly = lookupOnly;
}
}

View File

@@ -0,0 +1,116 @@
/*
* Copyright 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.gemfire.config;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.data.gemfire.RegionFactoryBean;
import org.springframework.data.gemfire.SubRegionFactoryBean;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
/**
* Base class for all Region Parsers
*
* @author David Turanski
*/
abstract class AbstractRegionParser extends AliasReplacingBeanDefinitionParser {
protected final Log log = LogFactory.getLog(getClass());
protected Class<?> getBeanClass(Element element) {
if (element.hasAttribute("subregion")) {
return SubRegionFactoryBean.class;
}
else {
return RegionFactoryBean.class;
}
}
@Override
protected void doParseInternal(Element element, ParserContext parserContext, BeanDefinitionBuilder builder){
super.doParse(element, builder);
boolean subRegion = element.hasAttribute("subregion");
doParseRegion(element, parserContext, builder, subRegion);
if (subRegion) {
builder.addPropertyValue("parent", parserContext.getContainingBeanDefinition().getAttribute("parent"));
builder.addPropertyValue("regionName", element.getAttribute(NAME_ATTRIBUTE));
}
}
protected abstract void doParseRegion(Element element, ParserContext parserContext, BeanDefinitionBuilder builder,
boolean subRegion);
protected void doParseSubRegion(Element element, Element subElement, ParserContext parserContext,
BeanDefinitionBuilder builder, boolean subRegion) {
String regionPath = null;
String parentBeanName = null;
if (subRegion) {
parentBeanName = parserContext.getContainingBeanDefinition().getAttribute("regionPath").toString();
}
else {
parentBeanName = getRegionNameFromElement(element);
}
regionPath = StringUtils
.arrayToDelimitedString(
new String[] { parentBeanName, getRegionNameFromElement(subElement) }, "/");
if (!regionPath.startsWith("/")) {
regionPath = "/" + regionPath;
}
/*
* The Region parser needs some context to handle recursion correctly
*/
builder.getBeanDefinition().setAttribute("parent",
new BeanDefinitionHolder(builder.getBeanDefinition(), parentBeanName));
builder.getBeanDefinition().setAttribute("regionPath",regionPath);
// Make recursive call
BeanDefinition subRegionDef = this.parseSubRegion(subElement, parserContext, builder);
//TODO: Is there a better work-around?
/*
* This setting prevents the BF from generating a name for this been
*/
subRegionDef.setScope(BeanDefinition.SCOPE_PROTOTYPE);
if (log.isDebugEnabled()) {
log.debug("registering subregion as " + regionPath);
}
this.registerBeanDefinition(new BeanDefinitionHolder(subRegionDef, regionPath), parserContext.getRegistry());
}
private BeanDefinition parseSubRegion(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
/*
* Easy way to mark this element as a subregion
*/
element.setAttribute("subregion", "true");
BeanDefinition beanDefinition = parserContext.getDelegate().parseCustomElement(element,
builder.getBeanDefinition());
return beanDefinition;
}
private String getRegionNameFromElement(Element element){
String name = element.getAttribute(NAME_ATTRIBUTE);
return StringUtils.hasText(name)? name: element.getAttribute(ID_ATTRIBUTE);
}
}

View File

@@ -16,10 +16,14 @@
package org.springframework.data.gemfire.config;
import java.util.List;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.data.gemfire.RegionLookupFactoryBean;
import org.springframework.data.gemfire.SubRegionFactoryBean;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
/**
@@ -27,21 +31,41 @@ import org.w3c.dom.Element;
*
* @author Costin Leau
*/
class LookupRegionParser extends AliasReplacingBeanDefinitionParser {
class LookupRegionParser extends AbstractRegionParser {
@Override
protected Class<?> getBeanClass(Element element) {
return RegionLookupFactoryBean.class;
if (element.hasAttribute("subregion")) {
return SubRegionFactoryBean.class;
}
else {
return RegionLookupFactoryBean.class;
}
}
@Override
protected void doParseInternal(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
protected void doParseRegion(Element element, ParserContext parserContext, BeanDefinitionBuilder builder,
boolean subRegion) {
super.doParse(element, builder);
ParsingUtils.setPropertyValue(element, builder, "name", "name");
String attr = element.getAttribute("cache-ref");
// add cache reference (fallback to default if nothing is specified)
builder.addPropertyReference("cache", (StringUtils.hasText(attr) ? attr : "gemfire-cache"));
if (!subRegion) {
String attr = element.getAttribute("cache-ref");
// add cache reference (fallback to default if nothing is specified)
builder.addPropertyReference("cache", (StringUtils.hasText(attr) ? attr : "gemfire-cache"));
}
else {
builder.addPropertyValue("lookupOnly", true);
}
// parse nested elements
List<Element> subElements = DomUtils.getChildElements(element);
for (Element subElement : subElements) {
String name = subElement.getLocalName();
if (name.endsWith("region")) {
doParseSubRegion(element, subElement, parserContext, builder, subRegion);
}
}
}
}

View File

@@ -23,7 +23,6 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.data.gemfire.PartitionAttributesFactoryBean;
import org.springframework.data.gemfire.RegionAttributesFactoryBean;
import org.springframework.data.gemfire.RegionFactoryBean;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
@@ -35,18 +34,17 @@ import com.gemstone.gemfire.cache.Region;
/**
* Parser for &lt;partitioned-region;gt; definitions.
*
* To avoid eager evaluations, the region attributes are declared as a nested definition.
* To avoid eager evaluations, the region attributes are declared as a nested
* definition.
*
* @author Costin Leau
* @author David Turanski
*/
class PartitionedRegionParser extends AliasReplacingBeanDefinitionParser {
protected Class<?> getBeanClass(Element element) {
return RegionFactoryBean.class;
}
class PartitionedRegionParser extends AbstractRegionParser {
@Override
protected void doParseInternal(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
protected void doParseRegion(Element element, ParserContext parserContext, BeanDefinitionBuilder builder,
boolean subRegion) {
super.doParse(element, builder);
// set the data policy
@@ -67,23 +65,24 @@ class PartitionedRegionParser extends AliasReplacingBeanDefinitionParser {
builder.addPropertyValue("dataPolicy", DataPolicy.PARTITION);
}
BeanDefinitionBuilder attrBuilder = builder;
if (!subRegion) {
attr = element.getAttribute("cache-ref");
// add cache reference (fallback to default if nothing is specified)
builder.addPropertyReference("cache", (StringUtils.hasText(attr) ? attr : "gemfire-cache"));
attrBuilder = BeanDefinitionBuilder.genericBeanDefinition(RegionAttributesFactoryBean.class);
}
ParsingUtils.setPropertyValue(element, builder, "name", "name");
attr = element.getAttribute("cache-ref");
// add cache reference (fallback to default if nothing is specified)
builder.addPropertyReference("cache", (StringUtils.hasText(attr) ? attr : "gemfire-cache"));
// region attributes
BeanDefinitionBuilder attrBuilder = BeanDefinitionBuilder.genericBeanDefinition(RegionAttributesFactoryBean.class);
ParsingUtils.parseStatistics(element, attrBuilder);
ParsingUtils.parseExpiration(parserContext, element, attrBuilder);
ParsingUtils.parseEviction(parserContext, element, attrBuilder);
ParsingUtils.parseDiskStorage(element, attrBuilder);
// partition attributes
BeanDefinitionBuilder parAttrBuilder = BeanDefinitionBuilder.genericBeanDefinition(PartitionAttributesFactoryBean.class);
BeanDefinitionBuilder parAttrBuilder = BeanDefinitionBuilder
.genericBeanDefinition(PartitionAttributesFactoryBean.class);
attr = element.getAttribute("colocated-with");
@@ -122,7 +121,6 @@ class PartitionedRegionParser extends AliasReplacingBeanDefinitionParser {
parAttrBuilder.addPropertyValue("totalNumBuckets", Integer.valueOf(attr));
}
List<Element> subElements = DomUtils.getChildElements(element);
// parse nested cache-listener elements
@@ -142,15 +140,21 @@ class PartitionedRegionParser extends AliasReplacingBeanDefinitionParser {
}
else if ("partition-resolver".equals(name)) {
parAttrBuilder.addPropertyValue("partitionResolver", parsePartitionResolver(parserContext, subElement,
builder));
parAttrBuilder.addPropertyValue("partitionResolver",
parsePartitionResolver(parserContext, subElement, builder));
}
// subregion
else if (name.endsWith("region")) {
doParseSubRegion(element, subElement, parserContext, builder, subRegion);
}
}
// add partition attributes attributes
attrBuilder.addPropertyValue("partitionAttributes", parAttrBuilder.getBeanDefinition());
// add partition/overflow settings as attributes
builder.addPropertyValue("attributes", attrBuilder.getBeanDefinition());
if (!subRegion) {
builder.addPropertyValue("attributes", attrBuilder.getBeanDefinition());
}
}
private Object parseCacheListener(ParserContext parserContext, Element subElement, BeanDefinitionBuilder builder) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2011 the original author or authors.
* Copyright 2010-2012 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.
@@ -18,15 +18,9 @@ package org.springframework.data.gemfire.config;
import java.util.List;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.data.gemfire.RegionAttributesFactoryBean;
import org.springframework.data.gemfire.SubRegion;
import org.springframework.data.gemfire.SubRegionFactoryBean;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
@@ -38,18 +32,13 @@ import com.gemstone.gemfire.cache.Scope;
* Parser for &lt;replicated-region;gt; definitions.
*
* @author Costin Leau
* @author David Turanski
*/
class ReplicatedRegionParser extends AliasReplacingBeanDefinitionParser {
class ReplicatedRegionParser extends AbstractRegionParser {
@Override
protected void doParseInternal(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
super.doParse(element, builder);
System.out.println("building class " +
builder.getBeanDefinition().getBeanClassName());
protected void doParseRegion(Element element, ParserContext parserContext, BeanDefinitionBuilder builder,
boolean subRegion) {
boolean subRegion = element.hasAttribute("subregion");
// set the data policy
String attr = element.getAttribute("persistent");
if (Boolean.parseBoolean(attr)) {
@@ -64,8 +53,8 @@ class ReplicatedRegionParser extends AliasReplacingBeanDefinitionParser {
ParsingUtils.setPropertyValue(element, builder, "name", "name");
BeanDefinitionBuilder attrBuilder = builder;
if (!subRegion){
if (!subRegion) {
attr = element.getAttribute("cache-ref");
// add cache reference (fallback to default if nothing is specified)
builder.addPropertyReference("cache", (StringUtils.hasText(attr) ? attr : "gemfire-cache"));
@@ -84,13 +73,12 @@ class ReplicatedRegionParser extends AliasReplacingBeanDefinitionParser {
ParsingUtils.parseEviction(parserContext, element, attrBuilder);
ParsingUtils.parseDiskStorage(element, attrBuilder);
builder.addPropertyValue("attributes", attrBuilder.getBeanDefinition());
if (!subRegion) {
builder.addPropertyValue("attributes", attrBuilder.getBeanDefinition());
}
List<Element> subElements = DomUtils.getChildElements(element);
ManagedList subRegions = new ManagedList();
subRegions.setElementTypeName(SubRegionFactoryBean.class.getName());
// parse nested elements
for (Element subElement : subElements) {
String name = subElement.getLocalName();
@@ -106,23 +94,11 @@ class ReplicatedRegionParser extends AliasReplacingBeanDefinitionParser {
else if ("cache-writer".equals(name)) {
builder.addPropertyValue("cacheWriter", parseCacheWriter(parserContext, subElement, builder));
}
//subregion
else if (name.endsWith("region")){
System.out.println("element type:" + subElement.getSchemaTypeInfo().getTypeName());
String parentRegionName = StringUtils.hasLength(element.getAttribute(NAME_ATTRIBUTE))? element.getAttribute(NAME_ATTRIBUTE):
element.getAttribute(ID_ATTRIBUTE);
BeanDefinition subRegionDef = this.parseSubRegion(subElement, parserContext, parentRegionName,builder.getBeanDefinition());
subRegions.add(subRegionDef);
System.out.println("parsed subregion " + subRegionDef);
// subregion
else if (name.endsWith("region")) {
doParseSubRegion(element, subElement, parserContext, builder, subRegion);
}
}
if (!CollectionUtils.isEmpty(subRegions)) {
builder.addPropertyValue("subRegions", subRegions);
}
}
private Object parseCacheListener(ParserContext parserContext, Element subElement, BeanDefinitionBuilder builder) {
@@ -137,10 +113,4 @@ class ReplicatedRegionParser extends AliasReplacingBeanDefinitionParser {
return ParsingUtils.parseRefOrNestedBeanDeclaration(parserContext, subElement, builder);
}
private BeanDefinition parseSubRegion(Element element, ParserContext parserContext, String parentRegionName,
BeanDefinition parentDefinition) {
element.setAttribute("subregion", "true");
BeanDefinition beanDefinition = parserContext.getDelegate().parseCustomElement(element, parentDefinition);
return beanDefinition;
}
}

View File

@@ -1,13 +0,0 @@
package org.springframework.data.gemfire;
import org.junit.Test;
public class SubRegionFactoryBeanTest {
@Test
public void test() throws Exception {
SubRegionFactoryBean srfb = new SubRegionFactoryBean();
srfb.setName("child");
srfb.afterPropertiesSet();
SubRegion sr = srfb.getObject();
}
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright 2010-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.gemfire;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import org.junit.Test;
import com.gemstone.gemfire.cache.GemFireCache;
import com.gemstone.gemfire.cache.Region;
/**
*
* @author David Turanski
*
*/
public class SubRegionTest extends RecreatingContextTest {
@Override
protected String location() {
return "org/springframework/data/gemfire/basic-subregion.xml";
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Test
public void testBasic() throws Exception {
CacheFactoryBean cfb = new CacheFactoryBean();
cfb.setUseBeanFactoryLocator(false);
cfb.afterPropertiesSet();
GemFireCache cache = cfb.getObject();
RegionFactoryBean rfb = new RegionFactoryBean();
rfb.setCache(cache);
rfb.setName("parent");
rfb.afterPropertiesSet();
Region parent = rfb.getObject();
SubRegionFactoryBean srfb = new SubRegionFactoryBean();
srfb.setParent(parent);
srfb.setName("/parent/child");
srfb.setRegionName("child");
srfb.afterPropertiesSet();
Region child = srfb.getObject();
assertNotNull(parent.getSubregion("child"));
assertSame(child,parent.getSubregion("child"));
cache.close();
}
@SuppressWarnings("rawtypes")
@Test
public void testContext() throws Exception {
Region parent = ctx.getBean("parent", Region.class);
Region child = ctx.getBean("/parent/child", Region.class);
assertNotNull(parent.getSubregion("child"));
assertSame(child,parent.getSubregion("child"));
assertEquals("/parent/child",child.getFullPath());
}
@SuppressWarnings("rawtypes")
@Test
public void testChildOnly() throws Exception {
Region child = ctx.getBean("/parent/child", Region.class);
assertEquals("/parent/child",child.getFullPath());
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2011 the original author or authors.
* Copyright 2010-2012 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.
@@ -18,18 +18,15 @@ 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.assertSame;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.data.gemfire.RegionFactoryBean;
import org.springframework.data.gemfire.RegionLookupFactoryBean;
import org.springframework.data.gemfire.SubRegion;
import org.springframework.data.gemfire.TestUtils;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -90,10 +87,4 @@ public class ReplicatedRegionNamespaceTest {
assertEquals("existing", TestUtils.readField("name", lfb));
assertEquals(existing, context.getBean("lookup"));
}
@Test
public void testNestedRegions() {
Object parent = context.getBean("parent");
//SubRegion child = context.getBean("/parent/child", SubRegion.class);
}
}

View File

@@ -0,0 +1,114 @@
/*
* Copyright 2010-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.gemfire.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.data.gemfire.SubRegionFactoryBean;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.gemstone.gemfire.cache.AttributesFactory;
import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.CacheLoader;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.RegionAttributes;
/**
* @author David Turanski
*/
@SuppressWarnings("deprecation")
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("subregion-ns.xml")
public class SubRegionNamespaceTest {
@Autowired
private ApplicationContext context;
@SuppressWarnings("rawtypes")
@Test
public void testNestedReplicatedRegions() {
Region parent = context.getBean("parent",Region.class);
Region child = context.getBean("/parent/child", Region.class);
Region grandchild = context.getBean("/parent/child/grandchild", Region.class);
assertNotNull(child);
assertEquals("/parent/child",child.getFullPath());
assertSame(child,parent.getSubregion("child"));
assertEquals("/parent/child/grandchild",grandchild.getFullPath());
assertSame(grandchild,child.getSubregion("grandchild"));
}
@SuppressWarnings({ "unused", "rawtypes", "unchecked" })
@Test
public void testMixedNestedRegions() {
Cache cache = context.getBean(Cache.class);
Region parent = context.getBean("replicatedParent",Region.class);
parent.createSubregion("lookupChild",new AttributesFactory().create());
Region child = context.getBean("/replicatedParent/lookupChild", Region.class);
Region grandchild = context.getBean("/replicatedParent/lookupChild/partitionedGrandchild", Region.class);
assertNotNull(child);
assertEquals("/replicatedParent/lookupChild",child.getFullPath());
assertSame(child,parent.getSubregion("lookupChild"));
assertEquals("/replicatedParent/lookupChild/partitionedGrandchild",grandchild.getFullPath());
assertSame(grandchild,child.getSubregion("partitionedGrandchild"));
}
@SuppressWarnings("rawtypes")
@Test
public void testNestedRegionsWithSiblings() {
Region parent = context.getBean("parentWithSiblings",Region.class);
Region child1 = context.getBean("/parentWithSiblings/child1",Region.class);
assertEquals("/parentWithSiblings/child1",child1.getFullPath());
Region child2 = context.getBean("/parentWithSiblings/child2",Region.class);
assertEquals("/parentWithSiblings/child2",child2.getFullPath());
assertSame(child1,parent.getSubregion("child1"));
assertSame(child2,parent.getSubregion("child2"));
Region grandchild1 = context.getBean("/parentWithSiblings/child1/grandChild11",Region.class);
assertEquals("/parentWithSiblings/child1/grandChild11",grandchild1.getFullPath());
}
@SuppressWarnings({ "unused", "rawtypes" })
@Test
public void testComplexNestedRegions() throws Exception {
Region parent = context.getBean("complexNested",Region.class);
Region child1 = context.getBean("/complexNested/child1",Region.class);
Region child2 = context.getBean("/complexNested/child2",Region.class);
Region grandchild1 = context.getBean("/complexNested/child1/grandChild11",Region.class);
SubRegionFactoryBean grandchild1fb = context.getBean("&/complexNested/child1/grandChild11",SubRegionFactoryBean.class);
assertNotNull(grandchild1fb);
RegionAttributes attr = grandchild1fb.create();
assertNotNull(attr);
CacheLoader cl = attr.getCacheLoader();
assertNotNull(cl);
}
}

View File

@@ -5,8 +5,8 @@ log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n
log4j.category.org.springframework.data.gemfire.listener=TRACE
log4j.category.org.springframework.data.gemfire.repository=DEBUG
#log4j.category.org.springframework=DEBUG
log4j.category.org.springframework.data.gemfire=DEBUG
log4j.category.org.springframework.beans.=DEBUG
# for debugging datasource initialization
# log4j.category.test.jdbc=DEBUG

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
default-lazy-init="true"
xmlns:gfe="http://www.springframework.org/schema/gemfire"
xsi:schemaLocation="http://www.springframework.org/schema/gemfire http://www.springframework.org/schema/gemfire/spring-gemfire-1.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<gfe:cache use-bean-factory-locator="false"/>
<gfe:replicated-region id="parent"/>
<bean name="/parent/child" class="org.springframework.data.gemfire.SubRegionFactoryBean">
<property name="parent" ref="parent"/>
<property name="regionName" value="child"/>
</bean>
</beans>

View File

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