diff --git a/docs/src/reference/docbook/reference/cache.xml b/docs/src/reference/docbook/reference/cache.xml
index 1c92b9ca..cff4559a 100644
--- a/docs/src/reference/docbook/reference/cache.xml
+++ b/docs/src/reference/docbook/reference/cache.xml
@@ -118,6 +118,7 @@
message-sync-interval="1"
search-timeout="300"
close="false"
+ lazy-init="true"
>
<gfe:transaction-listener ref="myTransactionListener"/>
@@ -136,6 +137,10 @@
information regarding anything shown in this example, please consult
the GemFire product documentation
+ The close attribute determines if the cache should be closed when the Spring application context is closed.
+ The default is true however for cases in which multiple application contexts use the cache (common in web applications), set this value to false.
+ The lazy-init attribute determines if the cache should be initialized before another bean references it.
+ The default is true however in some cases it may be convenient to set this value to false.
diff --git a/src/main/java/org/springframework/data/gemfire/CacheFactoryBean.java b/src/main/java/org/springframework/data/gemfire/CacheFactoryBean.java
index dda291bd..2dd1ba8f 100644
--- a/src/main/java/org/springframework/data/gemfire/CacheFactoryBean.java
+++ b/src/main/java/org/springframework/data/gemfire/CacheFactoryBean.java
@@ -30,6 +30,7 @@ import org.springframework.beans.factory.BeanFactoryAware;
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.dao.DataAccessException;
import org.springframework.dao.support.PersistenceExceptionTranslator;
@@ -72,9 +73,66 @@ import com.gemstone.gemfire.pdx.PdxSerializer;
* @author Costin Leau
* @author David Turanski
*/
-public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanClassLoaderAware, DisposableBean,
- FactoryBean, PersistenceExceptionTranslator {
-
+public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanClassLoaderAware, InitializingBean,
+ DisposableBean, FactoryBean, PersistenceExceptionTranslator {
+ protected final Log log = LogFactory.getLog(getClass());
+
+ protected Cache cache;
+
+ protected Resource cacheXml;
+
+ protected Properties properties;
+
+ protected ClassLoader beanClassLoader;
+
+ protected GemfireBeanFactoryLocator factoryLocator;
+
+ protected BeanFactory beanFactory;
+
+ protected String beanName;
+
+ protected boolean useBeanFactoryLocator = true;
+
+ protected boolean close = true;
+
+ // PDX options
+ protected Object pdxSerializer;
+
+ protected Boolean pdxPersistent;
+
+ protected Boolean pdxReadSerialized;
+
+ protected Boolean pdxIgnoreUnreadFields;
+
+ protected String pdxDiskStoreName;
+
+ protected Boolean copyOnRead;
+
+ protected Integer lockTimeout;
+
+ protected Integer lockLease;
+
+ protected Integer messageSyncInterval;
+
+ protected Integer searchTimeout;
+
+ protected List transactionListeners;
+
+ protected TransactionWriter transactionWriter;
+
+ protected Float evictionHeapPercentage;
+
+ protected Float criticalHeapPercentage;
+
+ protected DynamicRegionSupport dynamicRegionSupport;
+
+ protected List jndiDataSources;
+
+ // Defined this way for backward compatibility
+ protected Object gatewayConflictResolver;
+
+ protected boolean lazyInitialize = true;
+
/**
* Inner class to avoid a hard dependency on the GemFire 6.6 API.
*
@@ -184,62 +242,6 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
}
}
- protected final Log log = LogFactory.getLog(getClass());
-
- protected Cache cache;
-
- protected Resource cacheXml;
-
- protected Properties properties;
-
- protected ClassLoader beanClassLoader;
-
- protected GemfireBeanFactoryLocator factoryLocator;
-
- protected BeanFactory beanFactory;
-
- protected String beanName;
-
- protected boolean useBeanFactoryLocator = true;
-
- protected boolean close = true;
-
- // PDX options
- protected Object pdxSerializer;
-
- protected Boolean pdxPersistent;
-
- protected Boolean pdxReadSerialized;
-
- protected Boolean pdxIgnoreUnreadFields;
-
- protected String pdxDiskStoreName;
-
- protected Boolean copyOnRead;
-
- protected Integer lockTimeout;
-
- protected Integer lockLease;
-
- protected Integer messageSyncInterval;
-
- protected Integer searchTimeout;
-
- protected List transactionListeners;
-
- protected TransactionWriter transactionWriter;
-
- protected Float evictionHeapPercentage;
-
- protected Float criticalHeapPercentage;
-
- protected DynamicRegionSupport dynamicRegionSupport;
-
- protected List jndiDataSources;
-
- // Defined this way for backward compatibility
- protected Object gatewayConflictResolver;
-
private void init() throws Exception {
if (useBeanFactoryLocator && factoryLocator == null) {
@@ -257,7 +259,7 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
// first look for open caches
String msg = null;
try {
- cache =(Cache)fetchCache();
+ cache = (Cache) fetchCache();
msg = "Retrieved existing";
} catch (CacheClosedException ex) {
@@ -274,13 +276,13 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
}
// fall back to cache creation
- cache = (Cache)createCache(factory);
+ cache = (Cache) createCache(factory);
msg = "Created";
}
if (this.copyOnRead != null) {
cache.setCopyOnRead(this.copyOnRead);
}
-
+
if (lockLease != null) {
cache.setLockLease(lockLease);
}
@@ -299,7 +301,7 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
}
DistributedSystem system = cache.getDistributedSystem();
-
+
DistributedMember member = system.getDistributedMember();
log.info("Connected to Distributed System [" + system.getName() + "=" + member.getId() + "@"
+ member.getHost() + "]");
@@ -392,17 +394,17 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
new PdxOptions((CacheFactory) factory).run();
}
}
-
+
protected Object createFactory(Properties props) {
return new CacheFactory(props);
}
protected GemFireCache fetchCache() {
- return (cache == null)? CacheFactory.getAnyInstance(): cache;
+ return (cache == null) ? CacheFactory.getAnyInstance() : cache;
}
protected GemFireCache createCache(Object factory) {
- return (cache == null)? ((CacheFactory) factory).create() : cache;
+ return (cache == null) ? ((CacheFactory) factory).create() : cache;
}
@Override
@@ -619,7 +621,7 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
public void setCriticalHeapPercentage(Float criticalHeapPercentage) {
this.criticalHeapPercentage = criticalHeapPercentage;
}
-
+
/**
*
* @param close set to false if destroy() should not close the cache
@@ -670,6 +672,13 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
this.jndiDataSources = jndiDataSources;
}
+ /**
+ * @param lazyInitialize set to false to force cache initialization if no other bean references it
+ */
+ public void setLazyInitialize(boolean lazyInitialize) {
+ this.lazyInitialize = lazyInitialize;
+ }
+
/**
* @return the cacheXml
*/
@@ -793,7 +802,7 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
* @return the criticalHeapPercentage
*/
public Float getCriticalHeapPercentage() {
-
+
return criticalHeapPercentage;
}
@@ -817,7 +826,28 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
public Object getGatewayConflictResolver() {
return gatewayConflictResolver;
}
+
+ /**
+ * @return the beanFactoryLocator
+ */
public GemfireBeanFactoryLocator getBeanFactoryLocator() {
return factoryLocator;
}
+
+ /**
+ * return lazyInitialize
+ */
+ public boolean isLazyInitialize() {
+ return lazyInitialize;
+ }
+
+ /* (non-Javadoc)
+ * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
+ */
+ @Override
+ public void afterPropertiesSet() throws Exception {
+ if (!lazyInitialize) {
+ init();
+ }
+ }
}
diff --git a/src/main/java/org/springframework/data/gemfire/RegionLookupFactoryBean.java b/src/main/java/org/springframework/data/gemfire/RegionLookupFactoryBean.java
index 45775a93..5c51dfc2 100644
--- a/src/main/java/org/springframework/data/gemfire/RegionLookupFactoryBean.java
+++ b/src/main/java/org/springframework/data/gemfire/RegionLookupFactoryBean.java
@@ -49,14 +49,15 @@ public class RegionLookupFactoryBean implements FactoryBean>,
Assert.notNull(cache, "Cache property must be set");
name = (!StringUtils.hasText(name) ? beanName : name);
Assert.hasText(name, "Name (or beanName) property must be set");
+ synchronized (cache) {
+ region = cache.getRegion(name);
+ if (region != null) {
+ log.info("Retrieved region [" + name + "] from cache");
+ }
- region = cache.getRegion(name);
- if (region != null) {
- log.info("Retrieved region [" + name + "] from cache");
- }
-
- else {
- region = lookupFallback(cache, name);
+ else {
+ region = lookupFallback(cache, name);
+ }
}
}
diff --git a/src/main/java/org/springframework/data/gemfire/config/CacheParser.java b/src/main/java/org/springframework/data/gemfire/config/CacheParser.java
index 4a82ee2b..ab3c62a6 100644
--- a/src/main/java/org/springframework/data/gemfire/config/CacheParser.java
+++ b/src/main/java/org/springframework/data/gemfire/config/CacheParser.java
@@ -68,6 +68,7 @@ class CacheParser extends AbstractSimpleBeanDefinitionParser {
ParsingUtils.setPropertyValue(element, builder, "critical-heap-percentage");
ParsingUtils.setPropertyValue(element, builder, "eviction-heap-percentage");
ParsingUtils.setPropertyValue(element, builder, "close");
+ ParsingUtils.setPropertyValue(element, builder, "lazy-init","lazyInitialize");
List txListeners = DomUtils.getChildElementsByTagName(element, "transaction-listener");
if (!CollectionUtils.isEmpty(txListeners)) {
diff --git a/src/main/resources/org/springframework/data/gemfire/config/spring-gemfire-1.3.xsd b/src/main/resources/org/springframework/data/gemfire/config/spring-gemfire-1.3.xsd
index 7eb9b5ee..d5c00893 100755
--- a/src/main/resources/org/springframework/data/gemfire/config/spring-gemfire-1.3.xsd
+++ b/src/main/resources/org/springframework/data/gemfire/config/spring-gemfire-1.3.xsd
@@ -241,6 +241,14 @@ JavaDocs for com.gemstone.gemfire.cache.control.ResourceManager for more informa
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.
+ ]]>
+
+
+
+
+
diff --git a/src/test/java/org/springframework/data/gemfire/config/CacheEagerInitTest.java b/src/test/java/org/springframework/data/gemfire/config/CacheEagerInitTest.java
new file mode 100644
index 00000000..f77a6e8e
--- /dev/null
+++ b/src/test/java/org/springframework/data/gemfire/config/CacheEagerInitTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2010-2013 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.assertTrue;
+
+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.CacheFactoryBean;
+import org.springframework.data.gemfire.test.GemfireTestApplicationContextInitializer;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+/**
+ * @author Costin Leau
+ */
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations="/org/springframework/data/gemfire/config/cache-eager-init.xml",
+ initializers=GemfireTestApplicationContextInitializer.class)
+public class CacheEagerInitTest{
+ @Autowired ApplicationContext ctx;
+
+ @Test
+ public void testEagerInit() throws Exception {
+ CacheFactoryBean cfb = (CacheFactoryBean) ctx.getBean("&gemfireCache");
+ cfb.afterPropertiesSet();
+ assertTrue(!cfb.isLazyInitialize());
+ }
+
+}
diff --git a/src/test/java/org/springframework/data/gemfire/test/MockCacheFactoryBean.java b/src/test/java/org/springframework/data/gemfire/test/MockCacheFactoryBean.java
index 552c624f..8a427909 100644
--- a/src/test/java/org/springframework/data/gemfire/test/MockCacheFactoryBean.java
+++ b/src/test/java/org/springframework/data/gemfire/test/MockCacheFactoryBean.java
@@ -24,7 +24,7 @@ import com.gemstone.gemfire.cache.GemFireCache;
*
*/
public class MockCacheFactoryBean extends CacheFactoryBean {
-
+
public MockCacheFactoryBean() {
this.cache = new StubCache();
this.useBeanFactoryLocator = false;
@@ -59,6 +59,7 @@ public class MockCacheFactoryBean extends CacheFactoryBean {
this.transactionListeners = cacheFactoryBean.getTransactionListeners();
this.transactionWriter = cacheFactoryBean.getTransactionWriter();
this.properties = cacheFactoryBean.getProperties();
+ this.lazyInitialize = cacheFactoryBean.isLazyInitialize();
}
}
diff --git a/src/test/resources/org/springframework/data/gemfire/config/cache-eager-init.xml b/src/test/resources/org/springframework/data/gemfire/config/cache-eager-init.xml
new file mode 100644
index 00000000..479f0cdb
--- /dev/null
+++ b/src/test/resources/org/springframework/data/gemfire/config/cache-eager-init.xml
@@ -0,0 +1,9 @@
+
+
+
+
+