diff --git a/src/main/java/org/springframework/data/gemfire/RegionFactoryBean.java b/src/main/java/org/springframework/data/gemfire/RegionFactoryBean.java index 7a7ea4eb..f81c2909 100644 --- a/src/main/java/org/springframework/data/gemfire/RegionFactoryBean.java +++ b/src/main/java/org/springframework/data/gemfire/RegionFactoryBean.java @@ -17,6 +17,7 @@ package org.springframework.data.gemfire; import java.lang.reflect.Field; +import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -28,6 +29,7 @@ import org.springframework.util.ObjectUtils; import org.springframework.util.ReflectionUtils; import com.gemstone.gemfire.cache.AttributesFactory; +import com.gemstone.gemfire.cache.AttributesMutator; import com.gemstone.gemfire.cache.Cache; import com.gemstone.gemfire.cache.CacheClosedException; import com.gemstone.gemfire.cache.CacheListener; @@ -64,6 +66,7 @@ public class RegionFactoryBean extends RegionLookupFactoryBean imple private Scope scope; private DataPolicy dataPolicy; private Region region; + private List> subRegions; @Override @@ -73,7 +76,6 @@ public class RegionFactoryBean extends RegionLookupFactoryBean imple postProcess(region); } - @Override protected Region lookupFallback(GemFireCache cache, String regionName) throws Exception { Assert.isTrue(cache instanceof Cache, "Unable to create regions from " + cache); @@ -85,6 +87,7 @@ public class RegionFactoryBean extends RegionLookupFactoryBean imple final RegionFactory regionFactory = (attributes != null ? c.createRegionFactory(attributes) : c. createRegionFactory()); + if (!ObjectUtils.isEmpty(cacheListeners)) { for (CacheListener listener : cacheListeners) { @@ -110,12 +113,16 @@ public class RegionFactoryBean extends RegionLookupFactoryBean imple // get underlying AttributesFactory postProcess(findAttrFactory(regionFactory)); - + Region reg = regionFactory.create(regionName); log.info("Created new cache region [" + regionName + "]"); if (snapshot != null) { reg.loadSnapshot(snapshot.getInputStream()); } + + if (subRegions != null) { + System.out.println("**********************************************" + subRegions.get(0)); + } return reg; } @@ -225,6 +232,12 @@ public class RegionFactoryBean extends RegionLookupFactoryBean imple this.cacheListeners = cacheListeners; } + public void setSubRegions(List> subRegions) { + log.info("setting subRegions"); + this.subRegions = subRegions; + } + + /** * Sets the cache loader used for the region used by this factory. * Used only when a new region is created.Overrides the settings diff --git a/src/main/java/org/springframework/data/gemfire/SubRegion.java b/src/main/java/org/springframework/data/gemfire/SubRegion.java new file mode 100644 index 00000000..dbb1b68b --- /dev/null +++ b/src/main/java/org/springframework/data/gemfire/SubRegion.java @@ -0,0 +1,37 @@ +package org.springframework.data.gemfire; + +import java.util.List; + +import com.gemstone.gemfire.cache.RegionAttributes; +/** + * + * @author David Turanski + * + * @param + * @param + */ +public class SubRegion { + private final RegionAttributes regionAttributes; + private final String regionName; + private List> subRegions; + + public SubRegion(String regionName, RegionAttributes regionAttributes) { + this.regionAttributes = regionAttributes; + this.regionName = regionName; + } + + public RegionAttributes getRegionAttributes() { + return regionAttributes; + } + + public String getRegionName() { + return regionName; + } + + public List> getSubRegions() { + return subRegions; + } + public void setSubRegions(List> subRegions) { + this.subRegions = subRegions; + } +} diff --git a/src/main/java/org/springframework/data/gemfire/SubRegionFactoryBean.java b/src/main/java/org/springframework/data/gemfire/SubRegionFactoryBean.java new file mode 100644 index 00000000..5c1104dc --- /dev/null +++ b/src/main/java/org/springframework/data/gemfire/SubRegionFactoryBean.java @@ -0,0 +1,47 @@ +package org.springframework.data.gemfire; + +import java.util.List; + +import org.springframework.beans.factory.BeanNameAware; +import org.springframework.beans.factory.FactoryBean; +import org.springframework.beans.factory.InitializingBean; + +import com.gemstone.gemfire.cache.AttributesFactory; + +public class SubRegionFactoryBean extends AttributesFactory implements FactoryBean>, InitializingBean { + private String name; + private SubRegion subRegion; + private String regionName; + private List> subRegions; + + + public void setName(String name) { + this.name = name; + } + + public void setSubRegions(List> subRegions) { + this.subRegions = subRegions; + } + + @Override + public void afterPropertiesSet() throws Exception { + this.subRegion = new SubRegion(name,create()); + this.subRegion.setSubRegions(this.subRegions); + } + + @Override + public SubRegion getObject() throws Exception { + return this.subRegion; + } + + @Override + public Class getObjectType() { + return SubRegion.class; + } + + @Override + public boolean isSingleton() { + return true; + } + +} diff --git a/src/main/java/org/springframework/data/gemfire/config/AliasReplacingBeanDefinitionParser.java b/src/main/java/org/springframework/data/gemfire/config/AliasReplacingBeanDefinitionParser.java index 1184a87c..2ef4259c 100644 --- a/src/main/java/org/springframework/data/gemfire/config/AliasReplacingBeanDefinitionParser.java +++ b/src/main/java/org/springframework/data/gemfire/config/AliasReplacingBeanDefinitionParser.java @@ -21,6 +21,8 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.data.gemfire.RegionFactoryBean; +import org.springframework.data.gemfire.SubRegionFactoryBean; import org.w3c.dom.Element; /** @@ -32,10 +34,20 @@ import org.w3c.dom.Element; */ abstract class AliasReplacingBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { + protected Class getBeanClass(Element element) { + if (element.hasAttribute("subregion")){ + System.out.println("building subregion " + element.getAttribute(NAME_ATTRIBUTE)); + return SubRegionFactoryBean.class; + } else { + return RegionFactoryBean.class; + } + } + @Override protected final void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { + ParsingUtils.addBeanAliasAsMetadata(element, builder); - + doParseInternal(element, parserContext, builder); } diff --git a/src/main/java/org/springframework/data/gemfire/config/ReplicatedRegionParser.java b/src/main/java/org/springframework/data/gemfire/config/ReplicatedRegionParser.java index 13df6b7e..d1e85e3d 100644 --- a/src/main/java/org/springframework/data/gemfire/config/ReplicatedRegionParser.java +++ b/src/main/java/org/springframework/data/gemfire/config/ReplicatedRegionParser.java @@ -18,10 +18,15 @@ 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.RegionFactoryBean; +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; @@ -36,14 +41,15 @@ import com.gemstone.gemfire.cache.Scope; */ class ReplicatedRegionParser extends AliasReplacingBeanDefinitionParser { - protected Class getBeanClass(Element element) { - return RegionFactoryBean.class; - } @Override protected void doParseInternal(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { super.doParse(element, builder); + System.out.println("building class " + + builder.getBeanDefinition().getBeanClassName()); + boolean subRegion = element.hasAttribute("subregion"); + // set the data policy String attr = element.getAttribute("persistent"); if (Boolean.parseBoolean(attr)) { @@ -57,12 +63,15 @@ class ReplicatedRegionParser extends AliasReplacingBeanDefinitionParser { 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")); - + 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); + } // add attributes - BeanDefinitionBuilder attrBuilder = BeanDefinitionBuilder.genericBeanDefinition(RegionAttributesFactoryBean.class); ParsingUtils.parseStatistics(element, attrBuilder); @@ -79,7 +88,10 @@ class ReplicatedRegionParser extends AliasReplacingBeanDefinitionParser { List subElements = DomUtils.getChildElements(element); - // parse nested cache-listener elements + ManagedList subRegions = new ManagedList(); + subRegions.setElementTypeName(SubRegionFactoryBean.class.getName()); + + // parse nested elements for (Element subElement : subElements) { String name = subElement.getLocalName(); @@ -94,6 +106,22 @@ 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); + } + } + + if (!CollectionUtils.isEmpty(subRegions)) { + builder.addPropertyValue("subRegions", subRegions); } } @@ -108,4 +136,11 @@ class ReplicatedRegionParser extends AliasReplacingBeanDefinitionParser { private Object parseCacheWriter(ParserContext parserContext, Element subElement, BeanDefinitionBuilder builder) { 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; + } } \ No newline at end of file diff --git a/src/main/resources/org/springframework/data/gemfire/config/spring-gemfire-1.2.xsd b/src/main/resources/org/springframework/data/gemfire/config/spring-gemfire-1.2.xsd index 60797d8d..a7f4fd02 100644 --- a/src/main/resources/org/springframework/data/gemfire/config/spring-gemfire-1.2.xsd +++ b/src/main/resources/org/springframework/data/gemfire/config/spring-gemfire-1.2.xsd @@ -1,27 +1,16 @@ - - - - - - - - + + + + + + - - - - + + + namespace and its 'prop ]]> - + - + - + - + - + - + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + + - + - + - + - + - - - - + + - + @@ -197,22 +242,16 @@ The name of the bean referred by this declaration. If no reference exists, use a - + - + - - - - - + - - - - - - - - - + + + @@ -252,13 +283,13 @@ other thread for accessing the region and not waiting for it to complete its tas - - - + + - + @@ -276,7 +307,7 @@ use inner bean declarations. Disk storage configuration for the defined region. ]]> - + @@ -329,12 +360,20 @@ Default is false, meaning statistics are disabled. - - + + - + + + + + + + + + - + - + - - + - + - + - + - - + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ]]> - + - - - - - - - + + + + + - - - - - - - + + + + + + + - - - - - - - - - - - - - + ]]> + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + - - - - - + + + + - - - - - + + + + - - - - - + + + + - - - - - + + + + - - - - - + + + + - - - - - - - + + + + + + + + + + + + + + + + + @@ -619,7 +717,7 @@ When the region or cached object expires, it is destroyed locally only. Not supp - + @@ -629,7 +727,7 @@ Entity computing sizes for objects stored into the grid. ]]> - + @@ -671,7 +769,7 @@ performed. - + @@ -693,7 +791,6 @@ reclaim memory. - @@ -721,44 +818,22 @@ The maximum size (in megabytes) of data stored in each directory. Default is 102 - + ]]> - + - + ]]> - - + ]]> @@ -766,8 +841,7 @@ amount of file space will be immediately reserved. - + ]]> @@ -776,12 +850,20 @@ It is considered only for asynchronous writing. The maximum number of operations that can be asynchronously queued. Once this many pending async operations have been queued async ops will begin blocking until some of the queued ops have been flushed to disk. Considered only for asynchronous writing. - ]]> - + ]]> + - + - + @@ -811,13 +893,13 @@ to any key in this region in the CacheServer to be pushed to the client. - - - + + - + @@ -865,7 +947,7 @@ The action to take when performing eviction. - + @@ -887,7 +969,7 @@ cache to differ from other caches. - + - + @@ -935,19 +1017,19 @@ The port number of the connection (between 1 and 65535 inclusive). - + - + - + - + - + - + - + - + @@ -1000,37 +1082,36 @@ Note that in order to instantiate a pool, a GemFire cache needs to be already st The name of the pool definition (by default "gemfire-pool").]]> - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - + - - + @@ -1052,8 +1133,8 @@ The client subscription configuration that is used to control a clients use of s - - + + @@ -1062,146 +1143,145 @@ The client subscription configuration that is used to control a clients use of s - - - + + + - - - - - - - - - - + + + + + + + + + + - + - + - - - - + + + - - - - - - - - - - - - - + + + + + + + + + + + + - - - - - - - - - - + + + + + + + + + - - - - - - - - - - + + + + + + + + + - - - - - + + + + - - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + - - - - - + + + + - - - - - + + + + - - - - - + + + + - - - + + - + - + @@ -1228,30 +1308,29 @@ The name of the bean index definition. If property 'name' is not set, it will be - + - - - - + + + + - - + - + - - + @@ -1275,7 +1353,7 @@ The name of the pool used by the index. Used usually in client scenarios. - + @@ -1284,17 +1362,18 @@ The name of the pool used by the index. Used usually in client scenarios. - + - The reference to a GemfireTemplate. Will default to 'gemfireTemplate'. - + The reference to a GemfireTemplate. + Will default to 'gemfireTemplate'. + - + @@ -1305,5 +1384,42 @@ The name of the pool used by the index. Used usually in client scenarios. - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/java/org/springframework/data/gemfire/SubRegionFactoryBeanTest.java b/src/test/java/org/springframework/data/gemfire/SubRegionFactoryBeanTest.java new file mode 100644 index 00000000..0e387e00 --- /dev/null +++ b/src/test/java/org/springframework/data/gemfire/SubRegionFactoryBeanTest.java @@ -0,0 +1,13 @@ +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(); + } +} diff --git a/src/test/java/org/springframework/data/gemfire/config/ReplicatedRegionNamespaceTest.java b/src/test/java/org/springframework/data/gemfire/config/ReplicatedRegionNamespaceTest.java index 56eaf569..a943bfc0 100644 --- a/src/test/java/org/springframework/data/gemfire/config/ReplicatedRegionNamespaceTest.java +++ b/src/test/java/org/springframework/data/gemfire/config/ReplicatedRegionNamespaceTest.java @@ -18,15 +18,18 @@ 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; @@ -87,4 +90,10 @@ 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); + } } \ No newline at end of file diff --git a/src/test/resources/log4j.properties b/src/test/resources/log4j.properties index 5b8659e2..61dc0074 100644 --- a/src/test/resources/log4j.properties +++ b/src/test/resources/log4j.properties @@ -6,6 +6,7 @@ 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 # for debugging datasource initialization # log4j.category.test.jdbc=DEBUG diff --git a/src/test/resources/org/springframework/data/gemfire/config/replicated-ns.xml b/src/test/resources/org/springframework/data/gemfire/config/replicated-ns.xml index 3fe3436a..a2c3dfa6 100644 --- a/src/test/resources/org/springframework/data/gemfire/config/replicated-ns.xml +++ b/src/test/resources/org/springframework/data/gemfire/config/replicated-ns.xml @@ -28,4 +28,8 @@ + + + + \ No newline at end of file