+ added basic lookup factory bean
+ refactored existing schema
+ added namespace parsers
+ added integration tests
This commit is contained in:
costin
2010-09-15 18:39:09 +03:00
parent b6897115c3
commit 1d422f5d8f
8 changed files with 285 additions and 140 deletions

View File

@@ -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<K, V> implements DisposableBean, FactoryBean<Region<K, V>>, InitializingBean,
BeanNameAware {
public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> 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<K, V> implements DisposableBean, FactoryBean<Regi
private Scope scope;
private DataPolicy dataPolicy;
private Region<K, V> 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<K, V> attrFactory = (attributes != null ? new AttributesFactory<K, V>(attributes)
: new AttributesFactory<K, V>());
if (!ObjectUtils.isEmpty(cacheListeners)) {
for (CacheListener<K, V> 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<K, V> lookupFallback(Cache cache, String regionName) throws Exception {
if (attributes != null)
AttributesFactory.validateAttributes(attributes);
AttributesFactory<K, V> attrFactory = (attributes != null ? new AttributesFactory<K, V>(attributes)
: new AttributesFactory<K, V>());
if (!ObjectUtils.isEmpty(cacheListeners)) {
for (CacheListener<K, V> 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<K, V> 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<K, V> implements DisposableBean, FactoryBean<Regi
region = null;
}
public Region<K, V> 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).

View File

@@ -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<K, V> implements FactoryBean<Region<K, V>>, InitializingBean, BeanNameAware {
protected final Log log = LogFactory.getLog(getClass());
private String beanName;
private Cache cache;
private String name;
Region<K, V> 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<K, V> lookupFallback(Cache cache, String regionName) throws Exception {
throw new BeanInitializationException("Cannot find region named " + name + " in cache " + cache);
}
public Region<K, V> 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;
}
}

View File

@@ -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
*/

View File

@@ -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());

View File

@@ -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 &lt;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"));
}
}