diff --git a/src/main/java/org/springframework/data/gemfire/RegionFactoryBean.java b/src/main/java/org/springframework/data/gemfire/RegionFactoryBean.java index 7895cbe8..27506896 100644 --- a/src/main/java/org/springframework/data/gemfire/RegionFactoryBean.java +++ b/src/main/java/org/springframework/data/gemfire/RegionFactoryBean.java @@ -18,14 +18,9 @@ package org.springframework.data.gemfire; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.springframework.beans.factory.BeanNameAware; import org.springframework.beans.factory.DisposableBean; -import org.springframework.beans.factory.FactoryBean; -import org.springframework.beans.factory.InitializingBean; import org.springframework.core.io.Resource; -import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; -import org.springframework.util.StringUtils; import com.gemstone.gemfire.cache.AttributesFactory; import com.gemstone.gemfire.cache.Cache; @@ -38,19 +33,15 @@ import com.gemstone.gemfire.cache.RegionAttributes; import com.gemstone.gemfire.cache.Scope; /** - * FactoryBean for creating generic Gemfire {@link Region}s. Will try to first locate the region (by name) + * FactoryBean for creating generic GemFire {@link Region}s. Will try to first locate the region (by name) * and, in case none if found, proceed to creating one using the given settings. * * @author Costin Leau */ -public class RegionFactoryBean implements DisposableBean, FactoryBean>, InitializingBean, - BeanNameAware { +public class RegionFactoryBean extends RegionLookupFactoryBean implements DisposableBean { protected final Log log = LogFactory.getLog(getClass()); - private String beanName; - private Cache cache; - private String name; private boolean destroy = false; private Resource snapshot; @@ -61,60 +52,55 @@ public class RegionFactoryBean implements DisposableBean, FactoryBean region; - + @Override public void afterPropertiesSet() throws Exception { - Assert.notNull(cache, "Cache property must be set"); - name = (!StringUtils.hasText(name) ? beanName : name); - Assert.hasText(name, "Name (or beanName) property must be set"); - - // first get cache - region = cache.getRegion(name); - if (region != null) { - log.info("Retrieved region [" + name + "] from cache"); - } - // fall back to cache creation if one is not found - else { - if (attributes != null) - AttributesFactory.validateAttributes(attributes); - - AttributesFactory attrFactory = (attributes != null ? new AttributesFactory(attributes) - : new AttributesFactory()); - if (!ObjectUtils.isEmpty(cacheListeners)) { - for (CacheListener listener : cacheListeners) { - attrFactory.addCacheListener(listener); - } - } - - if (cacheLoader != null) { - attrFactory.setCacheLoader(cacheLoader); - } - - if (cacheWriter != null) { - attrFactory.setCacheWriter(cacheWriter); - } - - if (dataPolicy != null) { - attrFactory.setDataPolicy(dataPolicy); - } - - if (scope != null) { - attrFactory.setScope(scope); - } - - postProcess(attrFactory); - - region = cache.createRegion(name, attrFactory.create()); - log.info("Created new cache region [" + name + "]"); - if (snapshot != null) { - region.loadSnapshot(snapshot.getInputStream()); - } - } - + super.afterPropertiesSet(); + postProcess(region); } + + @Override + protected Region lookupFallback(Cache cache, String regionName) throws Exception { + if (attributes != null) + AttributesFactory.validateAttributes(attributes); + + AttributesFactory attrFactory = (attributes != null ? new AttributesFactory(attributes) + : new AttributesFactory()); + if (!ObjectUtils.isEmpty(cacheListeners)) { + for (CacheListener listener : cacheListeners) { + attrFactory.addCacheListener(listener); + } + } + + if (cacheLoader != null) { + attrFactory.setCacheLoader(cacheLoader); + } + + if (cacheWriter != null) { + attrFactory.setCacheWriter(cacheWriter); + } + + if (dataPolicy != null) { + attrFactory.setDataPolicy(dataPolicy); + } + + if (scope != null) { + attrFactory.setScope(scope); + } + + postProcess(attrFactory); + + Region reg = cache.createRegion(regionName, attrFactory.create()); + log.info("Created new cache region [" + regionName + "]"); + if (snapshot != null) { + reg.loadSnapshot(snapshot.getInputStream()); + } + + return reg; + } + /** * Post-process the attribute factory object used for configuring the region of this factory bean during the initialization process. * The object is already initialized and configured by the factory bean before this method @@ -144,46 +130,6 @@ public class RegionFactoryBean implements DisposableBean, FactoryBean getObject() throws Exception { - return region; - } - - public Class getObjectType() { - return (region != null ? region.getClass() : Region.class); - } - - public boolean isSingleton() { - return true; - } - - public void setBeanName(String beanName) { - this.beanName = beanName; - } - - /** - * Sets the cache used for creating the region. - * - * @see org.springframework.data.gemfire.CacheFactoryBean - * @param cache the cache to set - */ - public void setCache(Cache cache) { - this.cache = cache; - } - - /** - * Sets the name of the cache region. If no cache is found under - * the given name, a new one will be created. - * If no name is given, the beanName will be used. - * - * @see com.gemstone.gemfire.cache.Region#getFullPath() - * @see #setBeanName(String) - * - * @param name the region name - */ - public void setName(String name) { - this.name = name; - } - /** * Indicates whether the region referred by this factory bean, * will be destroyed on shutdown (default false). diff --git a/src/main/java/org/springframework/data/gemfire/RegionLookupFactoryBean.java b/src/main/java/org/springframework/data/gemfire/RegionLookupFactoryBean.java new file mode 100644 index 00000000..5eb8cdfa --- /dev/null +++ b/src/main/java/org/springframework/data/gemfire/RegionLookupFactoryBean.java @@ -0,0 +1,114 @@ +/* + * Copyright 2010 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 org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.BeanInitializationException; +import org.springframework.beans.factory.BeanNameAware; +import org.springframework.beans.factory.FactoryBean; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; + +import com.gemstone.gemfire.cache.Cache; +import com.gemstone.gemfire.cache.Region; + +/** + * Simple FactoryBean for retrieving generic GemFire {@link Region}s. If the region doesn't exist, an exception is thrown. + * + * For declaring and configuring new regions, see {@link RegionFactoryBean}. + * + * @author Costin Leau + */ +public class RegionLookupFactoryBean implements FactoryBean>, InitializingBean, BeanNameAware { + + protected final Log log = LogFactory.getLog(getClass()); + + private String beanName; + private Cache cache; + private String name; + + Region region; + + public void afterPropertiesSet() throws Exception { + Assert.notNull(cache, "Cache property must be set"); + name = (!StringUtils.hasText(name) ? beanName : name); + Assert.hasText(name, "Name (or beanName) property must be set"); + + region = cache.getRegion(name); + if (region != null) { + log.info("Retrieved region [" + name + "] from cache"); + } + + else { + region = lookupFallback(cache, name); + } + } + + /** + * Fall back method in case the named region does not exist. + * By default, this implementation throws an exception. + * + * @param cache GemFire cache + * @param regionName region name + * @throws Exception + */ + protected Region lookupFallback(Cache cache, String regionName) throws Exception { + throw new BeanInitializationException("Cannot find region named " + name + " in cache " + cache); + } + + public Region getObject() throws Exception { + return region; + } + + public Class getObjectType() { + return (region != null ? region.getClass() : Region.class); + } + + public boolean isSingleton() { + return true; + } + + public void setBeanName(String name) { + this.beanName = name; + } + + /** + * Sets the cache used for creating the region. + * + * @see org.springframework.data.gemfire.CacheFactoryBean + * @param cache the cache to set + */ + public void setCache(Cache cache) { + this.cache = cache; + } + + /** + * Sets the name of the cache region. If no cache is found under + * the given name, a new one will be created. + * If no name is given, the beanName will be used. + * + * @see com.gemstone.gemfire.cache.Region#getFullPath() + * @see #setBeanName(String) + * + * @param name the region name + */ + public void setName(String name) { + this.name = name; + } +} \ No newline at end of file diff --git a/src/main/java/org/springframework/data/gemfire/client/ClientRegionFactoryBean.java b/src/main/java/org/springframework/data/gemfire/client/ClientRegionFactoryBean.java index 8201e6a2..3120d77e 100644 --- a/src/main/java/org/springframework/data/gemfire/client/ClientRegionFactoryBean.java +++ b/src/main/java/org/springframework/data/gemfire/client/ClientRegionFactoryBean.java @@ -28,7 +28,7 @@ import com.gemstone.gemfire.cache.Region; import com.gemstone.gemfire.cache.client.Pool; /** - * Client extension for Gemfire regions. + * Client extension for GemFire regions. * * @author Costin Leau */ diff --git a/src/main/java/org/springframework/data/gemfire/config/GemfireNamespaceHandler.java b/src/main/java/org/springframework/data/gemfire/config/GemfireNamespaceHandler.java index f958fb97..8584ad27 100644 --- a/src/main/java/org/springframework/data/gemfire/config/GemfireNamespaceHandler.java +++ b/src/main/java/org/springframework/data/gemfire/config/GemfireNamespaceHandler.java @@ -27,6 +27,7 @@ class GemfireNamespaceHandler extends NamespaceHandlerSupport { public void init() { registerBeanDefinitionParser("cache", new CacheParser()); + registerBeanDefinitionParser("lookup-region", new LookupRegionParser()); registerBeanDefinitionParser("replicated-region", new ReplicatedRegionParser()); registerBeanDefinitionParser("partitioned-region", new PartitionedRegionParser()); registerBeanDefinitionParser("client-region", new ClientRegionParser()); diff --git a/src/main/java/org/springframework/data/gemfire/config/LookupRegionParser.java b/src/main/java/org/springframework/data/gemfire/config/LookupRegionParser.java new file mode 100644 index 00000000..04eb223b --- /dev/null +++ b/src/main/java/org/springframework/data/gemfire/config/LookupRegionParser.java @@ -0,0 +1,48 @@ +/* + * Copyright 2010 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.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; +import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.data.gemfire.RegionFactoryBean; +import org.springframework.util.StringUtils; +import org.w3c.dom.Element; + +/** + * Parser for <lookup-region;gt; definitions. + * + * @author Costin Leau + */ +class LookupRegionParser extends AbstractSingleBeanDefinitionParser { + + protected Class getBeanClass(Element element) { + return RegionFactoryBean.class; + } + + @Override + protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { + 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")); + + } +} diff --git a/src/main/resources/org/springframework/data/gemfire/config/spring-gemfire-1.0.xsd b/src/main/resources/org/springframework/data/gemfire/config/spring-gemfire-1.0.xsd index 617f241d..3de0c655 100644 --- a/src/main/resources/org/springframework/data/gemfire/config/spring-gemfire-1.0.xsd +++ b/src/main/resources/org/springframework/data/gemfire/config/spring-gemfire-1.0.xsd @@ -75,45 +75,14 @@ The name of the bean referred by this declaration. If no reference exists, use a - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -195,6 +210,17 @@ Note: Persistence for partitioned regions is supported only from GemFire 6.5 onw + + + + + + + \ No newline at end of file