diff --git a/src/main/java/org/springframework/data/gemfire/CacheFactoryBean.java b/src/main/java/org/springframework/data/gemfire/CacheFactoryBean.java
index ea8ccaf4..839caa39 100644
--- a/src/main/java/org/springframework/data/gemfire/CacheFactoryBean.java
+++ b/src/main/java/org/springframework/data/gemfire/CacheFactoryBean.java
@@ -17,7 +17,9 @@
package org.springframework.data.gemfire;
import java.io.File;
+import java.io.IOException;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -38,7 +40,6 @@ import org.springframework.dao.DataAccessException;
import org.springframework.dao.support.PersistenceExceptionTranslator;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
-import org.springframework.util.CollectionUtils;
import com.gemstone.gemfire.GemFireCheckedException;
import com.gemstone.gemfire.GemFireException;
@@ -58,24 +59,32 @@ import com.gemstone.gemfire.pdx.PdxSerializable;
import com.gemstone.gemfire.pdx.PdxSerializer;
/**
- * Factory used for configuring a Gemfire Cache manager. Allows either retrieval
- * of an existing, opened cache or the creation of a new one.
- *
+ * FactoryBean used for configuring a Gemfire Cache instance. Allows either the retrieval of an existing
+ * opened Cache instance or the creation of a new Cache instance.
*
* This class implements the
* {@link org.springframework.dao.support.PersistenceExceptionTranslator}
* interface, as auto-detected by Spring's
- * {@link org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor}
- * , for AOP-based translation of native exceptions to Spring
- * DataAccessExceptions. Hence, the presence of this class automatically enables
- * a PersistenceExceptionTranslationPostProcessor to translate GemFire
- * exceptions.
+ * {@link org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor},
+ * for AOP-based translation of native exceptions to Spring DataAccessExceptions. Hence, the presence
+ * of this class automatically enables a PersistenceExceptionTranslationPostProcessor to translate GemFire Exceptions.
*
* @author Costin Leau
* @author David Turanski
+ * @author John Blum
+ * @see org.springframework.beans.factory.BeanClassLoaderAware
+ * @see org.springframework.beans.factory.BeanFactoryAware
+ * @see org.springframework.beans.factory.BeanNameAware
+ * @see org.springframework.beans.factory.DisposableBean
+ * @see org.springframework.beans.factory.FactoryBean
+ * @see org.springframework.beans.factory.InitializingBean
+ * @see org.springframework.dao.support.PersistenceExceptionTranslator
+ * @see com.gemstone.gemfire.cache.Cache
+ * @see com.gemstone.gemfire.cache.CacheFactory
*/
-public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanClassLoaderAware, InitializingBean,
- DisposableBean, FactoryBean, PersistenceExceptionTranslator {
+@SuppressWarnings("unused")
+public class CacheFactoryBean implements BeanClassLoaderAware, BeanFactoryAware, BeanNameAware, FactoryBean,
+ InitializingBean, DisposableBean, PersistenceExceptionTranslator {
protected static final List VALID_JNDI_DATASOURCE_TYPE_NAMES = Collections.unmodifiableList(
Arrays.asList("ManagedDataSource", "PooledDataSource", "SimpleDataSource", "XAPooledDataSource"));
@@ -102,7 +111,7 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
protected Float criticalHeapPercentage;
protected Float evictionHeapPercentage;
- protected GemfireBeanFactoryLocator factoryLocator;
+ protected GemfireBeanFactoryLocator beanFactoryLocator;
protected Integer lockLease;
protected Integer lockTimeout;
@@ -122,12 +131,13 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
protected Resource cacheXml;
protected String beanName;
+ private String cacheResolutionMessagePrefix;
protected String pdxDiskStoreName;
protected TransactionWriter transactionWriter;
public static class DynamicRegionSupport {
- private String diskDir;
+ private String diskDirectory;
private String poolName;
@@ -136,11 +146,11 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
private Boolean registerInterest = Boolean.TRUE;
public String getDiskDir() {
- return diskDir;
+ return diskDirectory;
}
public void setDiskDir(String diskDir) {
- this.diskDir = diskDir;
+ this.diskDirectory = diskDir;
}
public Boolean getPersistent() {
@@ -168,12 +178,11 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
}
public void initializeDynamicRegionFactory() {
- DynamicRegionFactory.Config config = null;
- if (diskDir == null) {
- config = new DynamicRegionFactory.Config(null, poolName, persistent, registerInterest);
- } else {
- config = new DynamicRegionFactory.Config(new File(diskDir), poolName, persistent, registerInterest);
- }
+ File localDiskDirectory = (this.diskDirectory == null ? null : new File(this.diskDirectory));
+
+ DynamicRegionFactory.Config config = new DynamicRegionFactory.Config(localDiskDirectory, poolName,
+ persistent, registerInterest);
+
DynamicRegionFactory.get().open(config);
}
}
@@ -210,7 +219,7 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
private final CacheFactory factory;
- PdxOptions(CacheFactory factory) {
+ private PdxOptions(CacheFactory factory) {
this.factory = factory;
}
@@ -235,111 +244,61 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
}
}
- private void init() throws Exception {
- if (useBeanFactoryLocator && factoryLocator == null) {
- factoryLocator = new GemfireBeanFactoryLocator();
- factoryLocator.setBeanFactory(beanFactory);
- factoryLocator.setBeanName(beanName);
- factoryLocator.afterPropertiesSet();
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
+ */
+ @Override
+ public void afterPropertiesSet() throws Exception {
+ postProcessPropertiesBeforeInitialization(getProperties());
+
+ if (!isLazyInitialize()) {
+ init();
+ }
+ }
+
+ /* (non-Javadoc) */
+ protected void postProcessPropertiesBeforeInitialization(Properties gemfireProperties) {
+ }
+
+ /* (non-Javadoc) */
+ private Cache init() throws Exception {
+ if (useBeanFactoryLocator && beanFactoryLocator == null) {
+ beanFactoryLocator = new GemfireBeanFactoryLocator();
+ beanFactoryLocator.setBeanFactory(beanFactory);
+ beanFactoryLocator.setBeanName(beanName);
+ beanFactoryLocator.afterPropertiesSet();
}
final ClassLoader originalThreadContextClassLoader = Thread.currentThread().getContextClassLoader();
try {
- String messagePrefix;
-
- // use bean ClassLoader to load GemFire Declarable classes
+ // use bean ClassLoader to load Spring configured, GemFire Declarable classes
Thread.currentThread().setContextClassLoader(beanClassLoader);
- try {
- cache = (Cache) fetchCache();
- messagePrefix = "Retrieved existing";
- }
- catch (CacheClosedException ex) {
- initializeDynamicRegionFactory();
-
- Object factory = createFactory(this.properties);
-
- // GemFire 6.6 specific options
- if (isPdxSettingsSpecified()) {
- Assert.isTrue(ClassUtils.isPresent("com.gemstone.gemfire.pdx.PdxSerializer", beanClassLoader),
- "Cannot set PDX options since GemFire 6.6 not detected.");
- applyPdxOptions(factory);
- }
-
- // fall back to cache creation
- cache = (Cache) createCache(factory);
- messagePrefix = "Created new";
- }
-
- if (this.copyOnRead != null) {
- cache.setCopyOnRead(this.copyOnRead);
- }
- if (lockLease != null) {
- cache.setLockLease(lockLease);
- }
- if (lockTimeout != null) {
- cache.setLockTimeout(lockTimeout);
- }
- if (searchTimeout != null) {
- cache.setSearchTimeout(searchTimeout);
- }
- if (messageSyncInterval != null) {
- cache.setMessageSyncInterval(messageSyncInterval);
- }
- if (gatewayConflictResolver != null) {
- cache.setGatewayConflictResolver((GatewayConflictResolver) gatewayConflictResolver);
- }
+ this.cache = postProcess(resolveCache());
DistributedSystem system = cache.getDistributedSystem();
DistributedMember member = system.getDistributedMember();
- log.info(String.format("Connected to Distributed System [%1$s] as Member [%2$s] on Host [%3$s].",
- system.getName(), member.getId(), member.getHost()));
+ log.info(String.format("Connected to Distributed System [%1$s] as Member [%2$s]"
+ .concat("in Group(s) [%3$s] with Role(s) [%4$s] on Host [%5$s] having PID [%6$d]."),
+ system.getName(), member.getId(), member.getGroups(), member.getRoles(), member.getHost(),
+ member.getProcessId()));
- log.info(String.format("%1$s GemFire v.%2$s Cache [%3$s].", messagePrefix, CacheFactory.getVersion(),
- cache.getName()));
+ log.info(String.format("%1$s GemFire v.%2$s Cache [%3$s].", cacheResolutionMessagePrefix,
+ CacheFactory.getVersion(), cache.getName()));
- // load/init cache.xml
- if (cacheXml != null) {
- cache.loadCacheXml(cacheXml.getInputStream());
-
- if (log.isDebugEnabled()) {
- log.debug("Initialized cache from " + cacheXml);
- }
- }
-
- setHeapPercentages();
- registerTransactionListeners();
- registerTransactionWriter();
- registerJndiDataSources();
+ return cache;
}
finally {
Thread.currentThread().setContextClassLoader(originalThreadContextClassLoader);
}
}
- private boolean isPdxSettingsSpecified() {
- return (pdxSerializer != null || pdxPersistent != null || pdxReadSerialized != null
- || pdxIgnoreUnreadFields != null || pdxDiskStoreName != null);
- }
-
/**
- * Sets the PDX properties for the given object. Note this is implementation
- * specific as it depends on the type of the factory passed in.
- *
- * @param factory the GemFire CacheFactory used to apply the PDX configuration settings.
- */
- protected void applyPdxOptions(Object factory) {
- if (factory instanceof CacheFactory) {
- new PdxOptions((CacheFactory) factory).run();
- }
- }
-
- /**
- * If dynamic regions are enabled, create a DynamicRegionFactory before
- * creating the cache
+ * If Dynamic Regions are enabled, create and initialize a DynamicRegionFactory before creating the Cache.
*/
private void initializeDynamicRegionFactory() {
if (dynamicRegionSupport != null) {
@@ -348,82 +307,219 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
}
/**
- * Register all declared transaction listeners
+ * Resolves the GemFire Cache by first attempting to lookup and find an existing Cache instance in the VM;
+ * if an existing Cache could not be found, then this method proceeds in attempting to create a new Cache instance.
+ *
+ * @return the resolved GemFire Cache instance.
+ * @see com.gemstone.gemfire.cache.Cache
+ * @see #fetchCache()
+ * @see #createFactory(java.util.Properties)
+ * @see #initializeFactory(Object)
+ * @see #createCache(Object)
*/
- protected void registerTransactionListeners() {
- if (!CollectionUtils.isEmpty(transactionListeners)) {
- for (TransactionListener transactionListener : transactionListeners) {
- cache.getCacheTransactionManager().addListener(transactionListener);
- }
+ protected Cache resolveCache() {
+ try {
+ cacheResolutionMessagePrefix = "Found existing";
+ return (Cache) fetchCache();
+ }
+ catch (CacheClosedException ex) {
+ cacheResolutionMessagePrefix = "Created new";
+ initializeDynamicRegionFactory();
+ return (Cache) createCache(initializeFactory(createFactory(getProperties())));
}
}
/**
- * Register a transaction writer if declared
+ * Fetches the GemFire Cache by looking up any existing GemFire Cache instance.
+ *
+ * @return the existing GemFire Cache instance if available.
+ * @see com.gemstone.gemfire.cache.GemFireCache
+ * @see com.gemstone.gemfire.cache.CacheFactory#getAnyInstance()
*/
- protected void registerTransactionWriter() {
- if (transactionWriter != null) {
- cache.getCacheTransactionManager().setWriter(transactionWriter);
+ protected GemFireCache fetchCache() {
+ return (cache != null ? cache : CacheFactory.getAnyInstance());
+ }
+
+ /**
+ * Creates a new GemFire cache instance using the provided factory.
+ *
+ * @param factory the appropriate GemFire factory used to create a cache instance.
+ * @return an instance of the GemFire cache.
+ * @see com.gemstone.gemfire.cache.GemFireCache
+ * @see com.gemstone.gemfire.cache.CacheFactory#create()
+ */
+ protected GemFireCache createCache(Object factory) {
+ return (cache != null ? cache : ((CacheFactory) factory).create());
+ }
+
+ /**
+ * Creates an instance of GemFire factory initialized with the given GemFire System Properties
+ * to create an instance of the cache.
+ *
+ * @param gemfireProperties a Properties object containing GemFire System Properties.
+ * @return an instance of a GemFire factory used to create a GemFire cache instance.
+ * @see java.util.Properties
+ * @see com.gemstone.gemfire.cache.CacheFactory
+ */
+ protected Object createFactory(Properties gemfireProperties) {
+ return new CacheFactory(gemfireProperties);
+ }
+
+ /**
+ * Initializes the GemFire factory used to create the GemFire cache instance. Sets PDX options
+ * specified by the user.
+ *
+ * @param factory the GemFire factory used to create an instance of the cache.
+ * @return the initialized GemFire factory.
+ * @see #setPdxOptions(Object)
+ */
+ protected Object initializeFactory(Object factory) {
+ if (isPdxOptionsSpecified()) {
+ Assert.isTrue(ClassUtils.isPresent("com.gemstone.gemfire.pdx.PdxSerializer", beanClassLoader),
+ "Unable set PDX options since GemFire 6.6 or later was not detected.");
+ setPdxOptions(factory);
+ }
+
+ return factory;
+ }
+
+ /**
+ * Determines whether the user specified PDX options.
+ *
+ * @return a boolean value indicating whether the user specified PDX options or not.
+ */
+ protected boolean isPdxOptionsSpecified() {
+ return (pdxSerializer != null || pdxReadSerialized != null || pdxPersistent != null
+ || pdxIgnoreUnreadFields != null || pdxDiskStoreName != null);
+ }
+
+ /**
+ * Sets the PDX properties for the given Cache factory. Note, this is implementation specific
+ * as it depends on the type of Cache factory used to create the Cache.
+ *
+ * @param factory the GemFire CacheFactory used to apply the PDX configuration settings.
+ * @see com.gemstone.gemfire.cache.CacheFactory
+ * @see com.gemstone.gemfire.cache.client.ClientCacheFactory
+ */
+ protected void setPdxOptions(Object factory) {
+ if (factory instanceof CacheFactory) {
+ new PdxOptions((CacheFactory) factory).run();
}
}
- private void registerJndiDataSources() {
- if (jndiDataSources != null) {
- for (JndiDataSource jndiDataSource : jndiDataSources) {
- validate(jndiDataSource);
- JNDIInvoker.mapDatasource(jndiDataSource.getAttributes(), jndiDataSource.getProps());
+ /**
+ * Post processes the GemFire Cache instance by loading any cache.xml, applying settings specified in SDG XML
+ * configuration meta-data, and registering the appropriate Transaction Listeners, Writer and JNDI settings.
+ *
+ * @param cache the GemFire Cache instance to process.
+ * @return the GemFire Cache instance after processing.
+ * @throws IOException if the cache.xml Resource could not be loaded and applied to the Cache instance.
+ * @see com.gemstone.gemfire.cache.Cache#loadCacheXml(java.io.InputStream)
+ * @see #getCacheXml()
+ * @see #setHeapPercentages(com.gemstone.gemfire.cache.Cache)
+ * @see #registerTransactionListeners(com.gemstone.gemfire.cache.Cache)
+ * @see #registerTransactionWriter(com.gemstone.gemfire.cache.Cache)
+ * @see #registerJndiDataSources()
+ */
+ protected Cache postProcess(Cache cache) throws IOException {
+ Resource localCacheXml = getCacheXml();
+
+ // load cache.xml Resource and initialize the Cache
+ if (localCacheXml != null) {
+ if (log.isDebugEnabled()) {
+ log.debug(String.format("initializing Cache with '%1$s'", cacheXml));
}
+
+ cache.loadCacheXml(localCacheXml.getInputStream());
}
+
+ if (this.copyOnRead != null) {
+ cache.setCopyOnRead(this.copyOnRead);
+ }
+ if (gatewayConflictResolver != null) {
+ cache.setGatewayConflictResolver((GatewayConflictResolver) gatewayConflictResolver);
+ }
+ if (lockLease != null) {
+ cache.setLockLease(lockLease);
+ }
+ if (lockTimeout != null) {
+ cache.setLockTimeout(lockTimeout);
+ }
+ if (messageSyncInterval != null) {
+ cache.setMessageSyncInterval(messageSyncInterval);
+ }
+ if (searchTimeout != null) {
+ cache.setSearchTimeout(searchTimeout);
+ }
+
+ setHeapPercentages(cache);
+ registerTransactionListeners(cache);
+ registerTransactionWriter(cache);
+ registerJndiDataSources();
+
+ return cache;
}
- private void validate(final JndiDataSource jndiDataSource) {
- Map attributes = jndiDataSource.getAttributes();
- String typeAttributeValue = attributes.get("type");
- Assert.isTrue(VALID_JNDI_DATASOURCE_TYPE_NAMES.contains(typeAttributeValue),
- String.format("The 'jndi-binding', 'type' [%1$s] is invalid; the 'type' must be one of %2$s.",
- typeAttributeValue, VALID_JNDI_DATASOURCE_TYPE_NAMES));
- }
-
- private void setHeapPercentages() {
+ /* (non-Javadoc) */
+ private void setHeapPercentages(Cache cache) {
if (criticalHeapPercentage != null) {
Assert.isTrue(criticalHeapPercentage > 0.0 && criticalHeapPercentage <= 100.0,
- String.format("Invalid value specified for 'criticalHeapPercentage' (%1$s). Must be > 0.0 and <= 100.0.",
+ String.format("'criticalHeapPercentage' (%1$s) is invalid; must be > 0.0 and <= 100.0",
criticalHeapPercentage));
cache.getResourceManager().setCriticalHeapPercentage(criticalHeapPercentage);
}
if (evictionHeapPercentage != null) {
Assert.isTrue(evictionHeapPercentage > 0.0 && evictionHeapPercentage <= 100.0,
- String.format("Invalid value specified for 'evictionHeapPercentage' (%1$s). Must be > 0.0 and <= 100.0.",
+ String.format("'evictionHeapPercentage' (%1$s) is invalid; must be > 0.0 and <= 100.0",
evictionHeapPercentage));
cache.getResourceManager().setEvictionHeapPercentage(evictionHeapPercentage);
}
}
- protected GemFireCache createCache(Object factory) {
- return (cache != null ? cache : ((CacheFactory) factory).create());
+ /* (non-Javadoc) */
+ private void registerTransactionListeners(Cache cache) {
+ for (TransactionListener transactionListener : nullSafeCollection(transactionListeners)) {
+ cache.getCacheTransactionManager().addListener(transactionListener);
+ }
}
- protected GemFireCache fetchCache() {
- return (cache != null ? cache : CacheFactory.getAnyInstance());
+ /* (non-Javadoc) */
+ private void registerTransactionWriter(Cache cache) {
+ if (transactionWriter != null) {
+ cache.getCacheTransactionManager().setWriter(transactionWriter);
+ }
}
- protected Object createFactory(Properties props) {
- return new CacheFactory(props);
+ /* (non-Javadoc) */
+ private void registerJndiDataSources() {
+ for (JndiDataSource jndiDataSource : nullSafeCollection(jndiDataSources)) {
+ String typeAttributeValue = jndiDataSource.getAttributes().get("type");
+ Assert.isTrue(VALID_JNDI_DATASOURCE_TYPE_NAMES.contains(typeAttributeValue),
+ String.format("'jndi-binding' 'type' [%1$s] is invalid; 'type' must be one of %2$s",
+ typeAttributeValue, VALID_JNDI_DATASOURCE_TYPE_NAMES));
+ JNDIInvoker.mapDatasource(jndiDataSource.getAttributes(), jndiDataSource.getProps());
+ }
+ }
+
+ protected Collection nullSafeCollection(final Collection collection) {
+ return (collection != null ? collection : Collections.emptyList());
}
@Override
public void destroy() throws Exception {
if (close) {
- if (cache != null && !cache.isClosed()) {
- cache.close();
+ Cache localCache = (Cache) fetchCache();
+
+ if (localCache != null && !localCache.isClosed()) {
+ localCache.close();
}
- cache = null;
+ this.cache = null;
- if (factoryLocator != null) {
- factoryLocator.destroy();
- factoryLocator = null;
+ if (beanFactoryLocator != null) {
+ beanFactoryLocator.destroy();
+ beanFactoryLocator = null;
}
}
}
@@ -452,8 +548,7 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
@Override
public Cache getObject() throws Exception {
- init();
- return cache;
+ return init();
}
@Override
@@ -852,7 +947,7 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
* @return the beanFactoryLocator
*/
public GemfireBeanFactoryLocator getBeanFactoryLocator() {
- return factoryLocator;
+ return beanFactoryLocator;
}
/**
@@ -864,13 +959,4 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
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/client/ClientCacheFactoryBean.java b/src/main/java/org/springframework/data/gemfire/client/ClientCacheFactoryBean.java
index 5f16be45..a039de44 100644
--- a/src/main/java/org/springframework/data/gemfire/client/ClientCacheFactoryBean.java
+++ b/src/main/java/org/springframework/data/gemfire/client/ClientCacheFactoryBean.java
@@ -17,7 +17,6 @@
package org.springframework.data.gemfire.client;
import java.net.InetSocketAddress;
-import java.util.List;
import java.util.Properties;
import org.springframework.beans.factory.BeanInitializationException;
@@ -42,25 +41,25 @@ import com.gemstone.gemfire.pdx.PdxSerializer;
* @author Lyndon Adams
* @author John Blum
*/
+@SuppressWarnings("unused")
public class ClientCacheFactoryBean extends CacheFactoryBean {
/**
* Inner class to avoid a hard dependency on the GemFire 6.6 API.
- *
+ *
* @author Costin Leau
*/
private class PdxOptions implements Runnable {
private ClientCacheFactory factory;
- PdxOptions(ClientCacheFactory factory) {
+ private PdxOptions(ClientCacheFactory factory) {
this.factory = factory;
}
public void run() {
if (pdxSerializer != null) {
- Assert.isAssignable(PdxSerializer.class,
- pdxSerializer.getClass(), "Invalid pdx serializer used");
+ Assert.isAssignable(PdxSerializer.class, pdxSerializer.getClass(), "Invalid pdx serializer used");
factory.setPdxSerializer((PdxSerializer) pdxSerializer);
}
if (pdxDiskStoreName != null) {
@@ -75,120 +74,136 @@ public class ClientCacheFactoryBean extends CacheFactoryBean {
if (pdxReadSerialized != null) {
factory.setPdxReadSerialized(pdxReadSerialized);
}
-
+
}
}
- private String poolName;
- private Pool pool;
-
protected Boolean readyForEvents = false;
+ private Pool pool;
+
+ private String poolName;
+
+ @Override
+ protected void postProcessPropertiesBeforeInitialization(Properties gemfireProperties) {
+ }
+
@Override
protected GemFireCache createCache(Object factory) {
- ClientCacheFactory ccf = (ClientCacheFactory) factory;
- initializePool(ccf);
-
- // Now create the cache
- GemFireCache cache = ccf.create();
-
- // Register for events after pool/regions been created and iff non-durable client
+ ClientCacheFactory clientCacheFactory = (ClientCacheFactory) factory;
+
+ initializePool(clientCacheFactory);
+
+ GemFireCache cache = clientCacheFactory.create();
+
+ // register for events after Pool and Regions been created and iff non-durable client...
readyForEvents();
-
- // Return the cache
+
return cache;
}
@Override
- protected Object createFactory(Properties props) {
- return new ClientCacheFactory(props);
+ protected Object createFactory(Properties gemfireProperties) {
+ return new ClientCacheFactory(gemfireProperties);
}
@Override
protected GemFireCache fetchCache() {
return ClientCacheFactory.getAnyInstance();
}
-
- public Properties getProperties() {
- return this.properties;
+
+ /**
+ * Initialize the Pool settings on the ClientCacheFactory.
+ *
+ * @param clientCacheFactory the GemFire ClientCacheFactory used to configure and create a GemFire ClientCache.
+ * @see com.gemstone.gemfire.cache.client.ClientCacheFactory
+ */
+ private void initializePool(ClientCacheFactory clientCacheFactory) {
+ initializeClientCacheFactoryPoolSettings(clientCacheFactory, resolvePool(this.pool));
}
- private void initializePool(ClientCacheFactory ccf) {
- Pool p = pool;
+ /**
+ * Resolves the appropriate GemFire Pool from configuration used to configure the ClientCache.
+ *
+ * @param pool the preferred GemFire Pool to use in the configuration of the ClientCache.
+ * @return the resolved GemFire Pool.
+ * @see com.gemstone.gemfire.cache.client.Pool
+ * @see com.gemstone.gemfire.cache.client.PoolManager#find(String)
+ */
+ private Pool resolvePool(final Pool pool) {
+ Pool localPool = pool;
- if (p == null) {
- if (StringUtils.hasText(poolName)) {
- p = PoolManager.find(poolName);
- }
-
- // Bind this client cache to a pool that hasn't been created yet.
- if (p == null) {
- PoolFactoryBean.connectToTemporaryDs(this.properties);
- }
-
- if (StringUtils.hasText(poolName)) {
+ if (localPool == null) {
+ localPool = PoolManager.find(poolName);
+
+ if (localPool == null) {
try {
-
- getBeanFactory().isTypeMatch(poolName, Pool.class);
- } catch (Exception e) {
- String msg = "No bean found with name " + poolName
- + " of type " + Pool.class.getName();
- if (poolName
- .equals(GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME)) {
- msg += ". A client cache requires a pool";
+ if (StringUtils.hasText(poolName) && getBeanFactory().isTypeMatch(poolName, Pool.class)) {
+ localPool = getBeanFactory().getBean(poolName, Pool.class);
+ }
+ else {
+ localPool = getBeanFactory().getBean(Pool.class);
+ this.poolName = localPool.getName();
}
- throw new BeanInitializationException(msg);
}
- p = getBeanFactory().getBean(poolName, Pool.class);
- } else {
- if (log.isDebugEnabled()) {
- log.debug("Checking for a unique pool");
+ catch (Exception e) {
+ throw new BeanInitializationException(String.format(
+ "No bean of type '%1$s' having name '%2$s' was found.%3$s", Pool.class.getName(), poolName,
+ (GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME.equals(poolName)
+ ? " A client cache requires a pool." : "")), e);
}
- p = getBeanFactory().getBean(Pool.class);
- this.poolName = p.getName();
}
-
}
- if (p != null) {
- // copy the pool settings - this way if the pool is not found, at
- // least the cache will have a similar config
- ccf.setPoolFreeConnectionTimeout(p.getFreeConnectionTimeout());
- ccf.setPoolIdleTimeout(p.getIdleTimeout());
- ccf.setPoolLoadConditioningInterval(p.getLoadConditioningInterval());
- ccf.setPoolMaxConnections(p.getMaxConnections());
- ccf.setPoolMinConnections(p.getMinConnections());
- ccf.setPoolMultiuserAuthentication(p.getMultiuserAuthentication());
- ccf.setPoolPingInterval(p.getPingInterval());
- ccf.setPoolPRSingleHopEnabled(p.getPRSingleHopEnabled());
- ccf.setPoolReadTimeout(p.getReadTimeout());
- ccf.setPoolRetryAttempts(p.getRetryAttempts());
- ccf.setPoolServerGroup(p.getServerGroup());
- ccf.setPoolSocketBufferSize(p.getSocketBufferSize());
- ccf.setPoolStatisticInterval(p.getStatisticInterval());
- ccf.setPoolSubscriptionAckInterval(p.getSubscriptionAckInterval());
- ccf.setPoolSubscriptionEnabled(p.getSubscriptionEnabled());
- ccf.setPoolSubscriptionMessageTrackingTimeout(p
- .getSubscriptionMessageTrackingTimeout());
- ccf.setPoolSubscriptionRedundancy(p.getSubscriptionRedundancy());
- ccf.setPoolThreadLocalConnections(p.getThreadLocalConnections());
+ return localPool;
+ }
- List locators = p.getLocators();
- if (locators != null) {
- for (InetSocketAddress inet : locators) {
- ccf.addPoolLocator(inet.getHostName(), inet.getPort());
- }
+ /**
+ * Copy the Pool settings to the ClientCacheFactory so the ClientCache will have a matching configuration.
+ *
+ * @param clientCacheFactory the GemFire ClientCacheFactory used to create an instance of the ClientCache.
+ * @param pool the GemFire Pool from which to copy the pool settings.
+ * @see com.gemstone.gemfire.cache.client.ClientCacheFactory
+ * @see com.gemstone.gemfire.cache.client.Pool
+ */
+ private void initializeClientCacheFactoryPoolSettings(ClientCacheFactory clientCacheFactory, Pool pool) {
+ if (pool != null) {
+ clientCacheFactory.setPoolFreeConnectionTimeout(pool.getFreeConnectionTimeout());
+ clientCacheFactory.setPoolIdleTimeout(pool.getIdleTimeout());
+ clientCacheFactory.setPoolLoadConditioningInterval(pool.getLoadConditioningInterval());
+ clientCacheFactory.setPoolMaxConnections(pool.getMaxConnections());
+ clientCacheFactory.setPoolMinConnections(pool.getMinConnections());
+ clientCacheFactory.setPoolMultiuserAuthentication(pool.getMultiuserAuthentication());
+ clientCacheFactory.setPoolPingInterval(pool.getPingInterval());
+ clientCacheFactory.setPoolPRSingleHopEnabled(pool.getPRSingleHopEnabled());
+ clientCacheFactory.setPoolReadTimeout(pool.getReadTimeout());
+ clientCacheFactory.setPoolRetryAttempts(pool.getRetryAttempts());
+ clientCacheFactory.setPoolServerGroup(pool.getServerGroup());
+ clientCacheFactory.setPoolSocketBufferSize(pool.getSocketBufferSize());
+ clientCacheFactory.setPoolStatisticInterval(pool.getStatisticInterval());
+ clientCacheFactory.setPoolSubscriptionAckInterval(pool.getSubscriptionAckInterval());
+ clientCacheFactory.setPoolSubscriptionEnabled(pool.getSubscriptionEnabled());
+ clientCacheFactory.setPoolSubscriptionMessageTrackingTimeout(pool.getSubscriptionMessageTrackingTimeout());
+ clientCacheFactory.setPoolSubscriptionRedundancy(pool.getSubscriptionRedundancy());
+ clientCacheFactory.setPoolThreadLocalConnections(pool.getThreadLocalConnections());
+
+ for (InetSocketAddress socketAddress : nullSafeCollection(pool.getLocators())) {
+ clientCacheFactory.addPoolLocator(socketAddress.getHostName(), socketAddress.getPort());
}
- List servers = p.getServers();
- if (servers != null) {
- for (InetSocketAddress inet : servers) {
- ccf.addPoolServer(inet.getHostName(), inet.getPort());
- }
+ for (InetSocketAddress socketAddress : nullSafeCollection(pool.getServers())) {
+ clientCacheFactory.addPoolServer(socketAddress.getHostName(), socketAddress.getPort());
}
}
}
+ @Override
+ protected void setPdxOptions(Object factory) {
+ if (factory instanceof ClientCacheFactory) {
+ new PdxOptions((ClientCacheFactory) factory).run();
+ }
+ }
+
/**
* Inform the GemFire cluster that this client cache is ready to receive events.
*/
@@ -200,7 +215,7 @@ public class ClientCacheFactoryBean extends CacheFactoryBean {
clientCache.readyForEvents();
}
catch (IllegalStateException ignore) {
- // Cannot be called for a non-durable client so exception is thrown.
+ // cannot be called for a non-durable client so exception is thrown
}
}
}
@@ -239,12 +254,5 @@ public class ClientCacheFactoryBean extends CacheFactoryBean {
public Boolean getReadyForEvents(){
return this.readyForEvents;
}
-
- @Override
- protected void applyPdxOptions(Object factory) {
- if (factory instanceof ClientCacheFactory) {
- new PdxOptions((ClientCacheFactory) factory).run();
- }
- }
}
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 49990194..0a38c0c7 100644
--- a/src/main/java/org/springframework/data/gemfire/client/ClientRegionFactoryBean.java
+++ b/src/main/java/org/springframework/data/gemfire/client/ClientRegionFactoryBean.java
@@ -25,6 +25,7 @@ import org.springframework.beans.factory.DisposableBean;
import org.springframework.core.io.Resource;
import org.springframework.data.gemfire.DataPolicyConverter;
import org.springframework.data.gemfire.RegionLookupFactoryBean;
+import org.springframework.data.gemfire.config.GemfireConstants;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
@@ -93,60 +94,58 @@ public class ClientRegionFactoryBean extends RegionLookupFactoryBean
protected Region lookupFallback(GemFireCache cache, String regionName) throws Exception {
Assert.isTrue(cache instanceof ClientCache, String.format("Unable to create regions from %1$s", cache));
- // TODO reference to an internal GemFire class!
if (cache instanceof GemFireCacheImpl) {
Assert.isTrue(((GemFireCacheImpl) cache).isClient(), "A client-cache instance is required.");
}
ClientCache clientCache = (ClientCache) cache;
- ClientRegionFactory factory = clientCache.createClientRegionFactory(resolveClientRegionShortcut());
+ ClientRegionFactory clientRegionFactory = clientCache.createClientRegionFactory(resolveClientRegionShortcut());
// map region attributes onto the client region factory
if (attributes != null) {
- factory.setCloningEnabled(attributes.getCloningEnabled());
- factory.setConcurrencyChecksEnabled(attributes.getConcurrencyChecksEnabled());
- factory.setConcurrencyLevel(attributes.getConcurrencyLevel());
- factory.setCustomEntryIdleTimeout(attributes.getCustomEntryIdleTimeout());
- factory.setCustomEntryTimeToLive(attributes.getCustomEntryTimeToLive());
- factory.setDiskStoreName(attributes.getDiskStoreName());
- factory.setDiskSynchronous(attributes.isDiskSynchronous());
- factory.setEntryIdleTimeout(attributes.getEntryIdleTimeout());
- factory.setEntryTimeToLive(attributes.getEntryTimeToLive());
- factory.setEvictionAttributes(attributes.getEvictionAttributes());
- factory.setInitialCapacity(attributes.getInitialCapacity());
- factory.setKeyConstraint(attributes.getKeyConstraint());
- factory.setLoadFactor(attributes.getLoadFactor());
- factory.setPoolName(attributes.getPoolName());
- factory.setRegionIdleTimeout(attributes.getRegionIdleTimeout());
- factory.setRegionTimeToLive(attributes.getRegionTimeToLive());
- factory.setStatisticsEnabled(attributes.getStatisticsEnabled());
- factory.setValueConstraint(attributes.getValueConstraint());
+ clientRegionFactory.setCloningEnabled(attributes.getCloningEnabled());
+ clientRegionFactory.setConcurrencyChecksEnabled(attributes.getConcurrencyChecksEnabled());
+ clientRegionFactory.setConcurrencyLevel(attributes.getConcurrencyLevel());
+ clientRegionFactory.setCustomEntryIdleTimeout(attributes.getCustomEntryIdleTimeout());
+ clientRegionFactory.setCustomEntryTimeToLive(attributes.getCustomEntryTimeToLive());
+ clientRegionFactory.setDiskStoreName(attributes.getDiskStoreName());
+ clientRegionFactory.setDiskSynchronous(attributes.isDiskSynchronous());
+ clientRegionFactory.setEntryIdleTimeout(attributes.getEntryIdleTimeout());
+ clientRegionFactory.setEntryTimeToLive(attributes.getEntryTimeToLive());
+ clientRegionFactory.setEvictionAttributes(attributes.getEvictionAttributes());
+ clientRegionFactory.setInitialCapacity(attributes.getInitialCapacity());
+ clientRegionFactory.setKeyConstraint(attributes.getKeyConstraint());
+ clientRegionFactory.setLoadFactor(attributes.getLoadFactor());
+ clientRegionFactory.setPoolName(attributes.getPoolName());
+ clientRegionFactory.setRegionIdleTimeout(attributes.getRegionIdleTimeout());
+ clientRegionFactory.setRegionTimeToLive(attributes.getRegionTimeToLive());
+ clientRegionFactory.setStatisticsEnabled(attributes.getStatisticsEnabled());
+ clientRegionFactory.setValueConstraint(attributes.getValueConstraint());
}
- addCacheListeners(factory);
+ addCacheListeners(clientRegionFactory);
if (StringUtils.hasText(poolName)) {
// try to eagerly initialize the pool name, if defined as a bean
if (beanFactory.isTypeMatch(poolName, Pool.class)) {
if (log.isDebugEnabled()) {
- log.debug(String.format("Found bean definition for pool '%1$s'. Eagerly initializing...", poolName));
+ log.debug(String.format("Found bean definition for pool '%1$s'; Eagerly initializing...", poolName));
}
beanFactory.getBean(poolName, Pool.class);
}
- factory.setPoolName(poolName);
+ clientRegionFactory.setPoolName(poolName);
}
- else {
- Pool pool = beanFactory.getBean(Pool.class);
- factory.setPoolName(pool.getName());
+ else if (!isLocal(resolveClientRegionShortcut())) {
+ clientRegionFactory.setPoolName(GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME);
}
if (diskStoreName != null) {
- factory.setDiskStoreName(diskStoreName);
+ clientRegionFactory.setDiskStoreName(diskStoreName);
}
- Region clientRegion = (getParent() != null ? factory.createSubregion(getParent(), regionName)
- : factory.create(regionName));
+ Region clientRegion = (getParent() != null ? clientRegionFactory.createSubregion(getParent(), regionName)
+ : clientRegionFactory.create(regionName));
if (log.isInfoEnabled()) {
if (getParent() != null) {
@@ -165,6 +164,10 @@ public class ClientRegionFactoryBean extends RegionLookupFactoryBean
return clientRegion;
}
+ private boolean isLocal(final ClientRegionShortcut clientRegionShortcut) {
+ return (clientRegionShortcut != null && clientRegionShortcut.name().startsWith("LOCAL"));
+ }
+
protected ClientRegionShortcut resolveClientRegionShortcut() {
ClientRegionShortcut resolvedShortcut = this.shortcut;
diff --git a/src/main/java/org/springframework/data/gemfire/client/PoolFactoryBean.java b/src/main/java/org/springframework/data/gemfire/client/PoolFactoryBean.java
index fa3e9e8a..087c0db6 100644
--- a/src/main/java/org/springframework/data/gemfire/client/PoolFactoryBean.java
+++ b/src/main/java/org/springframework/data/gemfire/client/PoolFactoryBean.java
@@ -18,6 +18,7 @@ package org.springframework.data.gemfire.client;
import java.net.InetSocketAddress;
import java.util.Collection;
+import java.util.Collections;
import java.util.Properties;
import org.apache.commons.logging.Log;
@@ -39,58 +40,64 @@ import com.gemstone.gemfire.distributed.DistributedSystem;
import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem;
/**
- * Factory bean for easy declaration and configuration of a GemFire pool. If a
- * new pool is created, its life-cycle is bound to that of the declaring
- * container.
- *
- * Note that if the pool already exists, it will be returned as is, without any
- * modifications and its life cycle untouched by this factory.
- *
- * @see PoolManager
- * @see PoolFactory
- * @see Pool
- *
+ * FactoryBean for easy declaration and configuration of a GemFire Pool. If a new Pool is created,
+ * its lifecycle is bound to that of the declaring container.
+ *
+ * Note, if the Pool already exists, the existing Pool will be returned as is without any modifications
+ * and its lifecycle will be unaffected by this factory.
+ *
* @author Costin Leau
+ * @author John Blum
+ * @see com.gemstone.gemfire.cache.client.Pool
+ * @see com.gemstone.gemfire.cache.client.PoolFactory
+ * @see com.gemstone.gemfire.cache.client.PoolManager
*/
@SuppressWarnings("unused")
-public class PoolFactoryBean implements FactoryBean, InitializingBean,
- DisposableBean, BeanNameAware, BeanFactoryAware {
+public class PoolFactoryBean implements FactoryBean, InitializingBean, DisposableBean, BeanNameAware,
+ BeanFactoryAware {
private static final Log log = LogFactory.getLog(PoolFactoryBean.class);
- // whether the pool has been created internally or not
- private boolean internalPool = true;
-
- private Pool pool;
-
- // pool settings
- private String beanName;
- private String name;
- private Collection locators;
- private Collection servers;
+ // indicates whether the Pool has been created internally (by this FactoryBean) or not
+ private volatile boolean internalPool = true;
private BeanFactory beanFactory;
+ private Collection locators;
+ private Collection servers;
+
+ private Pool pool;
+
+ private String beanName;
+ private String name;
+
+ // GemFire Pool Configuration Settings
private boolean keepAlive = false;
+ private boolean multiUserAuthentication = PoolFactory.DEFAULT_MULTIUSER_AUTHENTICATION;
+ private boolean prSingleHopEnabled = PoolFactory.DEFAULT_PR_SINGLE_HOP_ENABLED;
+ private boolean subscriptionEnabled = PoolFactory.DEFAULT_SUBSCRIPTION_ENABLED;
+ private boolean threadLocalConnections = PoolFactory.DEFAULT_THREAD_LOCAL_CONNECTIONS;
private int freeConnectionTimeout = PoolFactory.DEFAULT_FREE_CONNECTION_TIMEOUT;
- private long idleTimeout = PoolFactory.DEFAULT_IDLE_TIMEOUT;
private int loadConditioningInterval = PoolFactory.DEFAULT_LOAD_CONDITIONING_INTERVAL;
private int maxConnections = PoolFactory.DEFAULT_MAX_CONNECTIONS;
private int minConnections = PoolFactory.DEFAULT_MIN_CONNECTIONS;
- private boolean multiUserAuthentication = PoolFactory.DEFAULT_MULTIUSER_AUTHENTICATION;
- private long pingInterval = PoolFactory.DEFAULT_PING_INTERVAL;
- private boolean prSingleHopEnabled = PoolFactory.DEFAULT_PR_SINGLE_HOP_ENABLED;
private int readTimeout = PoolFactory.DEFAULT_READ_TIMEOUT;
private int retryAttempts = PoolFactory.DEFAULT_RETRY_ATTEMPTS;
- private String serverGroup = PoolFactory.DEFAULT_SERVER_GROUP;
private int socketBufferSize = PoolFactory.DEFAULT_SOCKET_BUFFER_SIZE;
private int statisticInterval = PoolFactory.DEFAULT_STATISTIC_INTERVAL;
private int subscriptionAckInterval = PoolFactory.DEFAULT_SUBSCRIPTION_ACK_INTERVAL;
- private boolean subscriptionEnabled = PoolFactory.DEFAULT_SUBSCRIPTION_ENABLED;
private int subscriptionMessageTrackingTimeout = PoolFactory.DEFAULT_SUBSCRIPTION_MESSAGE_TRACKING_TIMEOUT;
private int subscriptionRedundancy = PoolFactory.DEFAULT_SUBSCRIPTION_REDUNDANCY;
- private boolean threadLocalConnections = PoolFactory.DEFAULT_THREAD_LOCAL_CONNECTIONS;
+
+ private long idleTimeout = PoolFactory.DEFAULT_IDLE_TIMEOUT;
+ private long pingInterval = PoolFactory.DEFAULT_PING_INTERVAL;
+
+ private String serverGroup = PoolFactory.DEFAULT_SERVER_GROUP;
+
+ public Pool getObject() throws Exception {
+ return pool;
+ }
public Class> getObjectType() {
return (pool != null ? pool.getClass() : Pool.class);
@@ -100,67 +107,36 @@ public class PoolFactoryBean implements FactoryBean, InitializingBean,
return true;
}
- public Pool getObject() throws Exception {
- return pool;
- }
-
public void afterPropertiesSet() throws Exception {
if (!StringUtils.hasText(name)) {
- Assert.hasText(beanName, "the pool name is required");
+ Assert.hasText(beanName, "The Pool name is required!");
name = beanName;
}
- // eagerly initialize cache (if needed)
- if (InternalDistributedSystem.getAnyInstance() == null) {
- Properties properties = null;
- try {
- ClientCacheFactoryBean clientCacheFactoryBean = beanFactory.getBean(ClientCacheFactoryBean.class);
- properties = clientCacheFactoryBean.getProperties();
- }
- catch (Exception ignore) {
- }
-
- connectToTemporaryDs(properties);
-
- }
-
// first check the configured pools
Pool existingPool = PoolManager.find(name);
- if (existingPool != null) {
- pool = existingPool;
- internalPool = false;
- if (log.isDebugEnabled())
- log.debug("Pool '" + name
- + " already exists; using found instance...");
- } else {
- if (log.isDebugEnabled())
- log.debug("No pool named '" + name
- + "' found. Creating a new once...");
- if (CollectionUtils.isEmpty(locators)
- && CollectionUtils.isEmpty(servers)) {
- throw new IllegalArgumentException(
- "at least one locator or server is required");
+ if (existingPool != null) {
+ if (log.isDebugEnabled()) {
+ log.debug(String.format("A Pool with name '%1$s' already exists; using existing Pool.", name));
+ }
+
+ internalPool = false;
+ pool = existingPool;
+ }
+ else {
+ if (log.isDebugEnabled()) {
+ log.debug(String.format("No Pool with name '%1$s' was found. Creating a new Pool...", name));
+ }
+
+ if (CollectionUtils.isEmpty(locators) && CollectionUtils.isEmpty(servers)) {
+ throw new IllegalArgumentException("At least one locator or server is required!");
}
internalPool = true;
PoolFactory poolFactory = PoolManager.createFactory();
- if (!CollectionUtils.isEmpty(locators)) {
- for (InetSocketAddress connection : locators) {
- poolFactory.addLocator(connection.getHostName(),
- connection.getPort());
- }
- }
-
- if (!CollectionUtils.isEmpty(servers)) {
- for (InetSocketAddress connection : servers) {
- poolFactory.addServer(connection.getHostName(),
- connection.getPort());
- }
- }
-
poolFactory.setFreeConnectionTimeout(freeConnectionTimeout);
poolFactory.setIdleTimeout(idleTimeout);
poolFactory.setLoadConditioningInterval(loadConditioningInterval);
@@ -174,13 +150,25 @@ public class PoolFactoryBean implements FactoryBean, InitializingBean,
poolFactory.setServerGroup(serverGroup);
poolFactory.setSocketBufferSize(socketBufferSize);
poolFactory.setStatisticInterval(statisticInterval);
- poolFactory.setSubscriptionEnabled(subscriptionEnabled);
poolFactory.setSubscriptionAckInterval(subscriptionAckInterval);
- poolFactory
- .setSubscriptionMessageTrackingTimeout(subscriptionMessageTrackingTimeout);
+ poolFactory.setSubscriptionEnabled(subscriptionEnabled);
+ poolFactory.setSubscriptionMessageTrackingTimeout(subscriptionMessageTrackingTimeout);
poolFactory.setSubscriptionRedundancy(subscriptionRedundancy);
poolFactory.setThreadLocalConnections(threadLocalConnections);
-
+
+ for (InetSocketAddress connection : nullSafeCollection(locators)) {
+ poolFactory.addLocator(connection.getHostName(), connection.getPort());
+ }
+
+ for (InetSocketAddress connection : nullSafeCollection(servers)) {
+ poolFactory.addServer(connection.getHostName(), connection.getPort());
+ }
+
+ // eagerly initialize ClientCache (if needed)
+ if (InternalDistributedSystem.getAnyInstance() == null) {
+ doDistributedSystemConnect(resolveGemfireProperties());
+ }
+
pool = poolFactory.create(name);
}
}
@@ -190,217 +178,145 @@ public class PoolFactoryBean implements FactoryBean, InitializingBean,
if (!pool.isDestroyed()) {
pool.releaseThreadLocalConnection();
pool.destroy(keepAlive);
+
if (log.isDebugEnabled()) {
- log.debug("Destroyed pool '" + name + "'...");
+ log.debug(String.format("Destroyed Pool '%1$s'.", name));
}
}
}
}
- public void setBeanName(String name) {
- this.beanName = name;
+ /**
+ * A workaround to create a Pool if no ClientCache has been created yet. Initialize a client-like
+ * Distributed System before initializing the Pool.
+ *
+ * @param properties GemFire System Properties.
+ * @see java.util.Properties
+ * @see com.gemstone.gemfire.distributed.DistributedSystem#connect(java.util.Properties)
+ */
+ @SuppressWarnings("deprecation")
+ static void doDistributedSystemConnect(Properties properties) {
+ Properties gemfireProperties = (properties != null ? (Properties) properties.clone() : new Properties());
+ gemfireProperties.setProperty("locators", "");
+ gemfireProperties.setProperty("mcast-port", "0");
+ DistributedSystem.connect(gemfireProperties);
}
- /**
- * @param pool
- * the pool to set
- */
- public void setPool(Pool pool) {
- this.pool = pool;
+ /* (non-Javadoc) */
+ private Collection nullSafeCollection(final Collection list) {
+ return (list != null ? list : Collections.emptyList());
}
- /**
- * @param name
- * the name to set
- */
- public void setName(String name) {
- this.name = name;
- }
-
- /**
- * @param locators
- * the locators to set
- */
- public void setLocators(Collection locators) {
- this.locators = locators;
- }
-
- /**
- * @param servers
- * the servers to set
- */
- public void setServers(Collection servers) {
- this.servers = servers;
- }
-
- /**
- * @param keepAlive
- * the keepAlive to set
- */
- public void setKeepAlive(boolean keepAlive) {
- this.keepAlive = keepAlive;
- }
-
- /**
- * @param freeConnectionTimeout
- * the freeConnectionTimeout to set
- */
- public void setFreeConnectionTimeout(int freeConnectionTimeout) {
- this.freeConnectionTimeout = freeConnectionTimeout;
- }
-
- /**
- * @param idleTimeout
- * the idleTimeout to set
- */
- public void setIdleTimeout(long idleTimeout) {
- this.idleTimeout = idleTimeout;
- }
-
- /**
- * @param loadConditioningInterval
- * the loadConditioningInterval to set
- */
- public void setLoadConditioningInterval(int loadConditioningInterval) {
- this.loadConditioningInterval = loadConditioningInterval;
- }
-
- /**
- * @param maxConnections
- * the maxConnections to set
- */
- public void setMaxConnections(int maxConnections) {
- this.maxConnections = maxConnections;
- }
-
- /**
- * @param minConnections
- * the minConnections to set
- */
- public void setMinConnections(int minConnections) {
- this.minConnections = minConnections;
- }
-
- /**
- * @param pingInterval
- * the pingInterval to set
- */
- public void setPingInterval(long pingInterval) {
- this.pingInterval = pingInterval;
- }
-
- /**
- * @param readTimeout
- * the readTimeout to set
- */
- public void setReadTimeout(int readTimeout) {
- this.readTimeout = readTimeout;
- }
-
- /**
- * @param retryAttempts
- * the retryAttempts to set
- */
- public void setRetryAttempts(int retryAttempts) {
- this.retryAttempts = retryAttempts;
- }
-
- /**
- * @param serverGroup
- * the serverGroup to set
- */
- public void setServerGroup(String serverGroup) {
- this.serverGroup = serverGroup;
- }
-
- /**
- * @param socketBufferSize
- * the socketBufferSize to set
- */
- public void setSocketBufferSize(int socketBufferSize) {
- this.socketBufferSize = socketBufferSize;
- }
-
- /**
- * @param statisticInterval
- * the statisticInterval to set
- */
- public void setStatisticInterval(int statisticInterval) {
- this.statisticInterval = statisticInterval;
- }
-
- /**
- * @param subscriptionAckInterval
- * the subscriptionAckInterval to set
- */
- public void setSubscriptionAckInterval(int subscriptionAckInterval) {
- this.subscriptionAckInterval = subscriptionAckInterval;
- }
-
- /**
- * @param subscriptionEnabled
- * the subscriptionEnabled to set
- */
- public void setSubscriptionEnabled(boolean subscriptionEnabled) {
- this.subscriptionEnabled = subscriptionEnabled;
- }
-
- /**
- * @param subscriptionMessageTrackingTimeout
- * the subscriptionMessageTrackingTimeout to set
- */
- public void setSubscriptionMessageTrackingTimeout(
- int subscriptionMessageTrackingTimeout) {
- this.subscriptionMessageTrackingTimeout = subscriptionMessageTrackingTimeout;
- }
-
- /**
- * @param subscriptionRedundancy
- * the subscriptionRedundancy to set
- */
- public void setSubscriptionRedundancy(int subscriptionRedundancy) {
- this.subscriptionRedundancy = subscriptionRedundancy;
- }
-
- /**
- * @param threadLocalConnections
- * the threadLocalConnections to set
- */
- public void setThreadLocalConnections(boolean threadLocalConnections) {
- this.threadLocalConnections = threadLocalConnections;
+ /* (non-Javadoc) */
+ private Properties resolveGemfireProperties() {
+ try {
+ ClientCacheFactoryBean clientCacheFactoryBean = beanFactory.getBean(ClientCacheFactoryBean.class);
+ return clientCacheFactoryBean.getProperties();
+ }
+ catch (Exception ignore) {
+ return null;
+ }
}
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
- /**
- * @param multiUserAuthentication
- * the multiUserAuthentication to set
- */
+ public void setBeanName(String name) {
+ this.beanName = name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public void setPool(Pool pool) {
+ this.pool = pool;
+ }
+
+ public void setFreeConnectionTimeout(int freeConnectionTimeout) {
+ this.freeConnectionTimeout = freeConnectionTimeout;
+ }
+
+ public void setIdleTimeout(long idleTimeout) {
+ this.idleTimeout = idleTimeout;
+ }
+
+ public void setKeepAlive(boolean keepAlive) {
+ this.keepAlive = keepAlive;
+ }
+
+ public void setLoadConditioningInterval(int loadConditioningInterval) {
+ this.loadConditioningInterval = loadConditioningInterval;
+ }
+
+ public void setLocators(Collection locators) {
+ this.locators = locators;
+ }
+
+ public void setMaxConnections(int maxConnections) {
+ this.maxConnections = maxConnections;
+ }
+
+ public void setMinConnections(int minConnections) {
+ this.minConnections = minConnections;
+ }
+
public void setMultiUserAuthentication(boolean multiUserAuthentication) {
this.multiUserAuthentication = multiUserAuthentication;
}
- /**
- * @param prSingleHopEnabled
- * the prSingleHopEnabled to set
- */
+ public void setPingInterval(long pingInterval) {
+ this.pingInterval = pingInterval;
+ }
+
+ public void setReadTimeout(int readTimeout) {
+ this.readTimeout = readTimeout;
+ }
+
+ public void setRetryAttempts(int retryAttempts) {
+ this.retryAttempts = retryAttempts;
+ }
+
+ public void setServerGroup(String serverGroup) {
+ this.serverGroup = serverGroup;
+ }
+
+ public void setServers(Collection servers) {
+ this.servers = servers;
+ }
+
+ public void setSocketBufferSize(int socketBufferSize) {
+ this.socketBufferSize = socketBufferSize;
+ }
+
+ public void setStatisticInterval(int statisticInterval) {
+ this.statisticInterval = statisticInterval;
+ }
+
public void setPrSingleHopEnabled(boolean prSingleHopEnabled) {
this.prSingleHopEnabled = prSingleHopEnabled;
}
-
- /*
- * A work around to create a pool if no cache has been created yet
- * initialize a client-like Distributed System before initializing
- * the pool
- */
- @SuppressWarnings("deprecation")
- static void connectToTemporaryDs(Properties properties) {
- Properties props = properties != null? (Properties) properties.clone() : new Properties();
- props.setProperty("mcast-port", "0");
- props.setProperty("locators", "");
- DistributedSystem.connect(props);
+
+ public void setSubscriptionAckInterval(int subscriptionAckInterval) {
+ this.subscriptionAckInterval = subscriptionAckInterval;
+ }
+
+ public void setSubscriptionEnabled(boolean subscriptionEnabled) {
+ this.subscriptionEnabled = subscriptionEnabled;
+ }
+
+ public void setSubscriptionMessageTrackingTimeout(
+ int subscriptionMessageTrackingTimeout) {
+ this.subscriptionMessageTrackingTimeout = subscriptionMessageTrackingTimeout;
+ }
+
+ public void setSubscriptionRedundancy(int subscriptionRedundancy) {
+ this.subscriptionRedundancy = subscriptionRedundancy;
+ }
+
+ public void setThreadLocalConnections(boolean threadLocalConnections) {
+ this.threadLocalConnections = threadLocalConnections;
}
}
diff --git a/src/main/java/org/springframework/data/gemfire/config/GemfireConstants.java b/src/main/java/org/springframework/data/gemfire/config/GemfireConstants.java
index 65e73cf7..688fb523 100644
--- a/src/main/java/org/springframework/data/gemfire/config/GemfireConstants.java
+++ b/src/main/java/org/springframework/data/gemfire/config/GemfireConstants.java
@@ -12,15 +12,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package org.springframework.data.gemfire.config;
+
/**
*
* @author David Turanski
- *
+ * @author John Blum
*/
public interface GemfireConstants {
- static final String DEFAULT_GEMFIRE_POOL_NAME = "gemfirePool";
static final String DEFAULT_GEMFIRE_CACHE_NAME = "gemfireCache";
- static final String DEFAULT_GEMFIRE_TXMANAGER_NAME = "gemfireTransactionManager";
static final String DEFAULT_GEMFIRE_FUNCTION_SERVICE_NAME = "gemfireFunctionService";
+ static final String DEFAULT_GEMFIRE_POOL_NAME = "DEFAULT";
+ static final String DEFAULT_GEMFIRE_TXMANAGER_NAME = "gemfireTransactionManager";
}
diff --git a/src/main/java/org/springframework/data/gemfire/config/PoolParser.java b/src/main/java/org/springframework/data/gemfire/config/PoolParser.java
index 4e73ba19..f93eb18a 100644
--- a/src/main/java/org/springframework/data/gemfire/config/PoolParser.java
+++ b/src/main/java/org/springframework/data/gemfire/config/PoolParser.java
@@ -71,30 +71,38 @@ class PoolParser extends AbstractSimpleBeanDefinitionParser {
}
}
- private Object parseServer(Element subElement) {
- return parseConnection(subElement);
+ private BeanDefinition parseConnection(Element element) {
+ BeanDefinitionBuilder inetSocketAddressBuilder = BeanDefinitionBuilder.genericBeanDefinition(
+ InetSocketAddress.class);
+
+ inetSocketAddressBuilder.addConstructorArgValue(element.getAttribute("host"));
+ inetSocketAddressBuilder.addConstructorArgValue(element.getAttribute("port"));
+
+ return inetSocketAddressBuilder.getBeanDefinition();
}
private Object parseLocator(Element subElement) {
return parseConnection(subElement);
}
- private BeanDefinition parseConnection(Element element) {
- BeanDefinitionBuilder defBuilder = BeanDefinitionBuilder.genericBeanDefinition(InetSocketAddress.class);
- defBuilder.addConstructorArgValue(element.getAttribute("host"));
- defBuilder.addConstructorArgValue(element.getAttribute("port"));
- return defBuilder.getBeanDefinition();
+ private Object parseServer(Element subElement) {
+ return parseConnection(subElement);
}
+ /* (non-Javadoc) */
@Override
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext)
- throws BeanDefinitionStoreException {
- String name = super.resolveId(element, definition, parserContext);
- if (!StringUtils.hasText(name)) {
- name = GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME;
- //For backward compatibility
+ throws BeanDefinitionStoreException {
+
+ String id = super.resolveId(element, definition, parserContext);
+
+ if (!StringUtils.hasText(id)) {
+ id = GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME;
+ parserContext.getRegistry().registerAlias(GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME, "gemfirePool");
parserContext.getRegistry().registerAlias(GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME, "gemfire-pool");
}
- return name;
+
+ return id;
}
-}
\ No newline at end of file
+
+}
diff --git a/src/test/java/org/springframework/data/gemfire/client/ClientCacheTest.java b/src/test/java/org/springframework/data/gemfire/client/ClientCacheTest.java
index bfb45a47..3ceec00c 100644
--- a/src/test/java/org/springframework/data/gemfire/client/ClientCacheTest.java
+++ b/src/test/java/org/springframework/data/gemfire/client/ClientCacheTest.java
@@ -24,6 +24,7 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.data.gemfire.config.GemfireConstants;
import org.springframework.data.gemfire.test.GemfireTestApplicationContextInitializer;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -48,7 +49,7 @@ public class ClientCacheTest {
@Test
public void test() {
- assertEquals("gemfirePool", region.getAttributes().getPoolName());
+ assertEquals(GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME, region.getAttributes().getPoolName());
}
@Test
diff --git a/src/test/java/org/springframework/data/gemfire/client/ClientRegionFactoryBeanTest.java b/src/test/java/org/springframework/data/gemfire/client/ClientRegionFactoryBeanTest.java
index 512036b1..bcfb2c11 100644
--- a/src/test/java/org/springframework/data/gemfire/client/ClientRegionFactoryBeanTest.java
+++ b/src/test/java/org/springframework/data/gemfire/client/ClientRegionFactoryBeanTest.java
@@ -21,17 +21,28 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import java.io.InputStream;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
+import org.springframework.core.io.Resource;
import org.springframework.data.gemfire.TestUtils;
import com.gemstone.gemfire.cache.DataPolicy;
+import com.gemstone.gemfire.cache.EvictionAttributes;
+import com.gemstone.gemfire.cache.ExpirationAttributes;
import com.gemstone.gemfire.cache.Region;
+import com.gemstone.gemfire.cache.RegionAttributes;
import com.gemstone.gemfire.cache.client.ClientCache;
import com.gemstone.gemfire.cache.client.ClientRegionFactory;
import com.gemstone.gemfire.cache.client.ClientRegionShortcut;
@@ -56,28 +67,183 @@ public class ClientRegionFactoryBeanTest {
factoryBean = null;
}
- @SuppressWarnings("unchecked")
@Test
- public void testLookupFallbackFailingToUseProvidedShortcut() throws Exception {
+ @SuppressWarnings({ "deprecation", "unchecked" })
+ public void testLookupFallbackUsingDefaultShortcut() throws Exception {
+ final String testRegionName = "TestRegion";
+
+ ClientCache mockClientCache = mock(ClientCache.class);
+ ClientRegionFactory mockClientRegionFactory = mock(ClientRegionFactory.class);
+ Region mockRegion = mock(Region.class);
+
+ when(mockClientCache.createClientRegionFactory(eq(ClientRegionShortcut.LOCAL))).thenReturn(mockClientRegionFactory);
+ when(mockClientRegionFactory.create(eq(testRegionName))).thenReturn(mockRegion);
+
+ RegionAttributes mockRegionAttributes = mock(RegionAttributes.class);
+
+ when(mockRegionAttributes.getCloningEnabled()).thenReturn(false);
+ when(mockRegionAttributes.getConcurrencyChecksEnabled()).thenReturn(true);
+ when(mockRegionAttributes.getConcurrencyLevel()).thenReturn(8);
+ when(mockRegionAttributes.getCustomEntryIdleTimeout()).thenReturn(null);
+ when(mockRegionAttributes.getCustomEntryTimeToLive()).thenReturn(null);
+ when(mockRegionAttributes.getDiskStoreName()).thenReturn("TestDiskStoreOne");
+ when(mockRegionAttributes.isDiskSynchronous()).thenReturn(false);
+ when(mockRegionAttributes.getEntryIdleTimeout()).thenReturn(mock(ExpirationAttributes.class));
+ when(mockRegionAttributes.getEntryTimeToLive()).thenReturn(mock(ExpirationAttributes.class));
+ when(mockRegionAttributes.getEvictionAttributes()).thenReturn(mock(EvictionAttributes.class));
+ when(mockRegionAttributes.getInitialCapacity()).thenReturn(101);
+ when(mockRegionAttributes.getKeyConstraint()).thenReturn(Long.class);
+ when(mockRegionAttributes.getLoadFactor()).thenReturn(0.75f);
+ when(mockRegionAttributes.getPoolName()).thenReturn("TestPoolOne");
+ when(mockRegionAttributes.getRegionIdleTimeout()).thenReturn(mock(ExpirationAttributes.class));
+ when(mockRegionAttributes.getRegionTimeToLive()).thenReturn(mock(ExpirationAttributes.class));
+ when(mockRegionAttributes.getStatisticsEnabled()).thenReturn(true);
+ when(mockRegionAttributes.getValueConstraint()).thenReturn(Number.class);
+
+ BeanFactory mockBeanFactory = mock(BeanFactory.class);
+ Pool mockPool = mock(Pool.class);
+ Resource mockSnapshot = mock(Resource.class, "Snapshot");
+
+ when(mockBeanFactory.isTypeMatch(eq("TestPoolTwo"), eq(Pool.class))).thenReturn(true);
+ when(mockBeanFactory.getBean(eq("TestPoolTwo"))).thenReturn(mockPool);
+ when(mockPool.getName()).thenReturn("TestPoolTwo");
+ when(mockSnapshot.getInputStream()).thenReturn(mock(InputStream.class));
+
+ factoryBean.setAttributes(mockRegionAttributes);
+ factoryBean.setBeanFactory(mockBeanFactory);
+ factoryBean.setDiskStoreName("TestDiskStoreTwo");
+ factoryBean.setPersistent(false);
+ factoryBean.setPoolName("TestPoolTwo");
+ factoryBean.setSnapshot(mockSnapshot);
+ factoryBean.setShortcut(null);
+
+ Region actualRegion = factoryBean.lookupFallback(mockClientCache, testRegionName);
+
+ assertSame(mockRegion, actualRegion);
+
+ verify(mockClientCache, times(1)).createClientRegionFactory(eq(ClientRegionShortcut.LOCAL));
+ verify(mockClientRegionFactory, times(1)).setCloningEnabled(eq(false));
+ verify(mockClientRegionFactory, times(1)).setConcurrencyChecksEnabled(eq(true));
+ verify(mockClientRegionFactory, times(1)).setConcurrencyLevel(eq(8));
+ verify(mockClientRegionFactory, times(1)).setCustomEntryIdleTimeout(null);
+ verify(mockClientRegionFactory, times(1)).setCustomEntryTimeToLive(null);
+ verify(mockClientRegionFactory, times(1)).setDiskStoreName(eq("TestDiskStoreOne"));
+ verify(mockClientRegionFactory, times(1)).setDiskSynchronous(eq(false));
+ verify(mockClientRegionFactory, times(1)).setEntryIdleTimeout(any(ExpirationAttributes.class));
+ verify(mockClientRegionFactory, times(1)).setEntryTimeToLive(any(ExpirationAttributes.class));
+ verify(mockClientRegionFactory, times(1)).setEvictionAttributes(any(EvictionAttributes.class));
+ verify(mockClientRegionFactory, times(1)).setInitialCapacity(eq(101));
+ verify(mockClientRegionFactory, times(1)).setKeyConstraint(eq(Long.class));
+ verify(mockClientRegionFactory, times(1)).setLoadFactor(eq(0.75f));
+ verify(mockClientRegionFactory, times(1)).setPoolName(eq("TestPoolOne"));
+ verify(mockClientRegionFactory, times(1)).setRegionIdleTimeout(any(ExpirationAttributes.class));
+ verify(mockClientRegionFactory, times(1)).setRegionTimeToLive(any(ExpirationAttributes.class));
+ verify(mockClientRegionFactory, times(1)).setStatisticsEnabled(eq(true));
+ verify(mockClientRegionFactory, times(1)).setValueConstraint(eq(Number.class));
+ verify(mockClientRegionFactory, times(1)).setPoolName(eq("TestPoolTwo"));
+ verify(mockClientRegionFactory, times(1)).setDiskStoreName(eq("TestDiskStoreTwo"));
+ verify(mockClientRegionFactory, times(1)).create(eq(testRegionName));
+ verify(mockRegion, times(1)).loadSnapshot(any(InputStream.class));
+ }
+
+ @Test
+ @SuppressWarnings({ "deprecation", "unchecked" })
+ public void testLookupFallbackUsingDefaultPersistentShortcut() throws Exception {
+ ClientCache mockClientCache = mock(ClientCache.class);
+ ClientRegionFactory