SGF-434 - Add a durable GemFire client cache test to assert proper behavior by SDG.

This commit is contained in:
John Blum
2015-10-03 18:34:30 -07:00
parent 2344eb521d
commit b52a18579b
22 changed files with 1032 additions and 101 deletions

View File

@@ -78,7 +78,7 @@ import com.gemstone.gemfire.pdx.PdxSerializer;
* @see org.springframework.dao.support.PersistenceExceptionTranslator
*/
@SuppressWarnings("unused")
public class CacheFactoryBean implements BeanClassLoaderAware, BeanFactoryAware, BeanNameAware, FactoryBean<Cache>,
public class CacheFactoryBean implements BeanClassLoaderAware, BeanFactoryAware, BeanNameAware, FactoryBean<GemFireCache>,
InitializingBean, DisposableBean, PersistenceExceptionTranslator {
protected boolean close = true;
@@ -96,7 +96,7 @@ public class CacheFactoryBean implements BeanClassLoaderAware, BeanFactoryAware,
protected Boolean pdxReadSerialized;
protected Boolean useClusterConfiguration;
protected Cache cache;
protected GemFireCache cache;
protected ClassLoader beanClassLoader;
@@ -226,7 +226,7 @@ public class CacheFactoryBean implements BeanClassLoaderAware, BeanFactoryAware,
}
/* (non-Javadoc) */
private Cache init() throws Exception {
private GemFireCache init() throws Exception {
initBeanFactoryLocator();
final ClassLoader currentThreadContextClassLoader = Thread.currentThread().getContextClassLoader();
@@ -497,7 +497,7 @@ public class CacheFactoryBean implements BeanClassLoaderAware, BeanFactoryAware,
Cache localCache = fetchCache();
if (localCache != null && !localCache.isClosed()) {
localCache.close();
close(localCache);
}
this.cache = null;
@@ -509,6 +509,10 @@ public class CacheFactoryBean implements BeanClassLoaderAware, BeanFactoryAware,
}
}
protected void close(GemFireCache cache) {
cache.close();
}
@Override
public DataAccessException translateExceptionIfPossible(RuntimeException e) {
if (e instanceof GemFireException) {
@@ -844,7 +848,7 @@ public class CacheFactoryBean implements BeanClassLoaderAware, BeanFactoryAware,
}
@Override
public Cache getObject() throws Exception {
public GemFireCache getObject() throws Exception {
return init();
}

View File

@@ -23,6 +23,7 @@ import org.springframework.util.ClassUtils;
import com.gemstone.gemfire.cache.CacheFactory;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.client.ClientCacheFactory;
/**
* GemfireUtils is an abstract utility class encapsulating common functionality to access features and capabilities
@@ -32,10 +33,31 @@ import com.gemstone.gemfire.cache.Region;
* @see org.springframework.data.gemfire.util.DistributedSystemUtils
* @since 1.3.3
*/
@SuppressWarnings("unused")
public abstract class GemfireUtils extends DistributedSystemUtils {
public final static String GEMFIRE_VERSION = CacheFactory.getVersion();
public static boolean closeCache() {
try {
CacheFactory.getAnyInstance().close();
return true;
}
catch (Exception ignore) {
return false;
}
}
public static boolean closeClientCache() {
try {
ClientCacheFactory.getAnyInstance().close();
return true;
}
catch (Exception ignore) {
return false;
}
}
public static boolean isGemfireVersionGreaterThanEqual(double expectedVersion) {
double actualVersion = Double.parseDouble(GEMFIRE_VERSION.substring(0, 3));
return actualVersion >= expectedVersion;

View File

@@ -16,10 +16,11 @@
package org.springframework.data.gemfire.client;
import java.io.IOException;
import java.util.Properties;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.data.gemfire.CacheFactoryBean;
import org.springframework.data.gemfire.GemfireUtils;
import org.springframework.data.gemfire.config.GemfireConstants;
@@ -40,19 +41,26 @@ import com.gemstone.gemfire.pdx.PdxSerializer;
* @author Costin Leau
* @author Lyndon Adams
* @author John Blum
* @see org.springframework.context.ApplicationListener
* @see org.springframework.context.event.ContextRefreshedEvent
* @see org.springframework.data.gemfire.CacheFactoryBean
* @see com.gemstone.gemfire.cache.GemFireCache
* @see com.gemstone.gemfire.cache.client.ClientCache
* @see com.gemstone.gemfire.cache.client.ClientCacheFactory
* @see com.gemstone.gemfire.cache.client.Pool
* @see com.gemstone.gemfire.cache.client.PoolManager
* @see com.gemstone.gemfire.distributed.DistributedSystem
*/
@SuppressWarnings("unused")
public class ClientCacheFactoryBean extends CacheFactoryBean {
public class ClientCacheFactoryBean extends CacheFactoryBean implements ApplicationListener<ContextRefreshedEvent> {
protected Boolean keepAlive = false;
protected Boolean readyForEvents = false;
private Pool pool;
private String poolName;
protected String poolName;
@Override
protected void postProcessPropertiesBeforeInitialization(Properties gemfireProperties) {
@@ -213,18 +221,14 @@ public class ClientCacheFactoryBean extends CacheFactoryBean {
/**
* Register for events after Pool and Regions have been created and iff non-durable client...
*
* @param <T> parameterized Class type extension of GemFireCache.
* @param cache the GemFire cache instance to process.
* @return the processed cache instance after ready for events.
* @throws java.io.IOException if an error occurs during post processing.
* @see org.springframework.data.gemfire.CacheFactoryBean#postProcess(com.gemstone.gemfire.cache.GemFireCache)
* @see #readyForEvents(com.gemstone.gemfire.cache.GemFireCache)
* @see com.gemstone.gemfire.cache.GemFireCache
* @param event the ApplicationContextEvent fired when the ApplicationContext is refreshed.
* @see org.springframework.context.Lifecycle#start()
* @see com.gemstone.gemfire.cache.client.ClientCache
* @see #readyForEvents(com.gemstone.gemfire.cache.GemFireCache)
*/
@Override
protected <T extends GemFireCache> T postProcess(T cache) throws IOException {
return readyForEvents(super.postProcess(cache));
public void onApplicationEvent(final ContextRefreshedEvent event) {
readyForEvents(this.cache);
}
/**
@@ -243,6 +247,11 @@ public class ClientCacheFactoryBean extends CacheFactoryBean {
return clientCache;
}
@Override
protected void close(final GemFireCache cache) {
((ClientCache) cache).close(isKeepAlive());
}
@Override
public final void setEnableAutoReconnect(final Boolean enableAutoReconnect) {
throw new UnsupportedOperationException("Auto-reconnect is not supported on ClientCache.");
@@ -258,6 +267,26 @@ public class ClientCacheFactoryBean extends CacheFactoryBean {
return (cache != null ? cache.getClass() : ClientCache.class);
}
/**
* Sets whether the server(s) should keep the durable client's queue alive for the duration of the timeout
* when the client voluntarily disconnects.
*
* @param keepAlive a boolean value indicating to the server to keep the durable client's queues alive.
*/
public void setKeepAlive(Boolean keepAlive) {
this.keepAlive = keepAlive;
}
/**
* Determines whether the server(s) should keep the durable client's queue alive for the duration of the timeout
* when the client voluntarily disconnects.
*
* @return a boolean value indicating whether the server should keep the durable client's queues alive.
*/
public boolean isKeepAlive() {
return Boolean.TRUE.equals(this.keepAlive);
}
/**
* Sets the pool used by this client.
*
@@ -278,6 +307,15 @@ public class ClientCacheFactoryBean extends CacheFactoryBean {
this.poolName = poolName;
}
/**
* Gets the pool name used by this client.
*
* @return the name of the GemFire Pool used by the GemFire Client Cache.
*/
public String getPoolName() {
return poolName;
}
/**
* Set the readyForEvents flag.
*

View File

@@ -49,6 +49,14 @@ import com.gemstone.gemfire.internal.cache.GemFireCacheImpl;
* @author Costin Leau
* @author David Turanski
* @author John Blum
* @see org.springframework.beans.factory.BeanFactory
* @see org.springframework.beans.factory.BeanFactoryAware
* @see org.springframework.beans.factory.DisposableBean
* @see org.springframework.data.gemfire.RegionLookupFactoryBean
* @see com.gemstone.gemfire.cache.GemFireCache
* @see com.gemstone.gemfire.cache.client.ClientCache
* @see com.gemstone.gemfire.cache.client.ClientRegionFactory
* @see com.gemstone.gemfire.cache.client.ClientRegionShortcut
*/
@SuppressWarnings("unused")
public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> implements BeanFactoryAware,
@@ -89,7 +97,7 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
}
@Override
@SuppressWarnings("deprecation")
@SuppressWarnings("all")
protected Region<K, V> lookupFallback(GemFireCache cache, String regionName) throws Exception {
Assert.isTrue(cache instanceof ClientCache, String.format("Unable to create Regions from %1$s!", cache));
@@ -298,24 +306,6 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
public void destroy() throws Exception {
Region<K, V> region = getObject();
try {
if (region != null && !ObjectUtils.isEmpty(interests)) {
for (Interest<K> interest : interests) {
if (interest instanceof RegexInterest) {
region.unregisterInterestRegex((String) interest.getKey());
}
else {
region.unregisterInterest(interest.getKey());
}
}
}
}
// NOTE AdminRegion, LocalDataSet, Proxy Region and RegionCreation all throw UnsupportedOperationException;
// however, should not really happen since Interests are validated at start/registration
catch (UnsupportedOperationException ex) {
log.warn("Cannot unregister cache interests", ex);
}
if (region != null) {
if (close) {
if (!region.getRegionService().isClosed()) {
@@ -326,8 +316,8 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
}
}
}
// TODO I think Region.close and Region.destroyRegion are mutually exclusive; thus, 1 operation (e.g. close)
// does not cancel the other (i.e. destroy). This should just be if, not else if.
// TODO perhaps 'destroy' should take precedence over 'close' since 'destroy' is a functional superset
// of 'close'
else if (destroy) {
region.destroyRegion();
}

View File

@@ -243,18 +243,10 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean, Dis
this.beanName = name;
}
/**
* @param name
* the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @param pool
* the pool to set
*/
public void setPool(Pool pool) {
this.pool = pool;
}

View File

@@ -38,6 +38,7 @@ class ClientCacheParser extends CacheParser {
@Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
super.doParse(element, parserContext, builder);
ParsingUtils.setPropertyValue(element, builder, "keep-alive", "keepAlive");
ParsingUtils.setPropertyValue(element, builder, "pool-name", "poolName");
ParsingUtils.setPropertyValue(element, builder, "ready-for-events");
}