SGF-414 - Resolve incompatibility between the DistributedSystem created by the PoolFactoryBean and the DistributedSystem resolved by the ClientCacheFactoryBean when SSL is configured.

This commit is contained in:
John Blum
2015-07-09 18:26:21 -07:00
parent 7303b53419
commit 4f2eb22163
10 changed files with 452 additions and 152 deletions

View File

@@ -38,7 +38,6 @@ import org.springframework.dao.DataAccessException;
import org.springframework.dao.support.PersistenceExceptionTranslator;
import org.springframework.data.gemfire.util.CollectionUtils;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import com.gemstone.gemfire.GemFireCheckedException;
import com.gemstone.gemfire.GemFireException;
@@ -203,40 +202,6 @@ public class CacheFactoryBean implements BeanClassLoaderAware, BeanFactoryAware,
}
}
/**
* Inner class to avoid a hard dependency on the GemFire 6.6 API.
*
* @author Costin Leau
*/
private class PdxOptions implements Runnable {
private final CacheFactory factory;
private PdxOptions(CacheFactory factory) {
this.factory = factory;
}
@Override
public void run() {
if (pdxSerializer != null) {
Assert.isAssignable(PdxSerializer.class, pdxSerializer.getClass(), "Invalid pdx serializer used");
factory.setPdxSerializer((PdxSerializer) pdxSerializer);
}
if (pdxDiskStoreName != null) {
factory.setPdxDiskStore(pdxDiskStoreName);
}
if (pdxIgnoreUnreadFields != null) {
factory.setPdxIgnoreUnreadFields(pdxIgnoreUnreadFields);
}
if (pdxPersistent != null) {
factory.setPdxPersistent(pdxPersistent);
}
if (pdxReadSerialized != null) {
factory.setPdxReadSerialized(pdxReadSerialized);
}
}
}
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
@@ -329,38 +294,39 @@ public class CacheFactoryBean implements BeanClassLoaderAware, BeanFactoryAware,
catch (CacheClosedException ex) {
cacheResolutionMessagePrefix = "Created new";
initDynamicRegionFactory();
return (Cache) createCache(prepareFactory(createFactory(getProperties())));
return (Cache) createCache(prepareFactory(createFactory(resolveProperties())));
}
}
/**
* Fetches the GemFire Cache by looking up any existing GemFire Cache instance.
* Fetches an existing GemFire Cache instance from the CacheFactory.
*
* @param <T> parameterized Class type extension of GemFireCache.
* @return the existing GemFire Cache instance if available.
* @throws com.gemstone.gemfire.cache.CacheClosedException if an existing GemFire Cache instance does not exist.
* @see com.gemstone.gemfire.cache.GemFireCache
* @see com.gemstone.gemfire.cache.CacheFactory#getAnyInstance()
*/
protected GemFireCache fetchCache() {
return (cache != null ? cache : CacheFactory.getAnyInstance());
@SuppressWarnings("unchecked")
protected <T extends GemFireCache> T fetchCache() {
return (T) (cache != null ? cache : CacheFactory.getAnyInstance());
}
/**
* Creates a new GemFire cache instance using the provided factory.
* Resolves the GemFire System properties used to configure the GemFire Cache instance.
*
* @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()
* @return a Properties object containing GemFire System properties used to configure the GemFire Cache instance.
* @see #getProperties()
*/
protected GemFireCache createCache(Object factory) {
return (cache != null ? cache : ((CacheFactory) factory).create());
protected Properties resolveProperties() {
return getProperties();
}
/**
* Creates an instance of GemFire factory initialized with the given GemFire System Properties
* to create an instance of the cache.
* to create an instance of a GemFire cache.
*
* @param gemfireProperties a Properties object containing GemFire System Properties.
* @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
@@ -373,19 +339,31 @@ public class CacheFactoryBean implements BeanClassLoaderAware, BeanFactoryAware,
* 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)
* @param factory the GemFire factory used to create an instance of the GemFire cache.
* @return the initialized GemFire cache factory.
* @see #isPdxOptionsSpecified()
*/
protected Object prepareFactory(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);
}
CacheFactory cacheFactory = (CacheFactory) factory;
//return (isCacheXmlAvailable() ? ((CacheFactory) factory).set(
// DistributionConfig.CACHE_XML_FILE_NAME, getCacheXmlFile().getAbsolutePath()) : factory);
if (pdxSerializer != null) {
Assert.isAssignable(PdxSerializer.class, pdxSerializer.getClass(), "Invalid pdx serializer used");
cacheFactory.setPdxSerializer((PdxSerializer) pdxSerializer);
}
if (pdxDiskStoreName != null) {
cacheFactory.setPdxDiskStore(pdxDiskStoreName);
}
if (pdxIgnoreUnreadFields != null) {
cacheFactory.setPdxIgnoreUnreadFields(pdxIgnoreUnreadFields);
}
if (pdxPersistent != null) {
cacheFactory.setPdxPersistent(pdxPersistent);
}
if (pdxReadSerialized != null) {
cacheFactory.setPdxReadSerialized(pdxReadSerialized);
}
}
return factory;
}
@@ -401,17 +379,17 @@ public class CacheFactoryBean implements BeanClassLoaderAware, BeanFactoryAware,
}
/**
* 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.
* Creates a new GemFire cache instance using the provided factory.
*
* @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
* @param <T> parameterized Class type extension of GemFireCache.
* @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 void setPdxOptions(Object factory) {
if (factory instanceof CacheFactory) {
new PdxOptions((CacheFactory) factory).run();
}
@SuppressWarnings("unchecked")
protected <T extends GemFireCache> T createCache(Object factory) {
return (T) (cache != null ? cache : ((CacheFactory) factory).create());
}
/**
@@ -423,12 +401,12 @@ public class CacheFactoryBean implements BeanClassLoaderAware, BeanFactoryAware,
* @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 #setHeapPercentages(com.gemstone.gemfire.cache.GemFireCache)
* @see #registerTransactionListeners(com.gemstone.gemfire.cache.GemFireCache)
* @see #registerTransactionWriter(com.gemstone.gemfire.cache.GemFireCache)
* @see #registerJndiDataSources()
*/
protected Cache postProcess(Cache cache) throws IOException {
protected <T extends GemFireCache> T postProcess(T cache) throws IOException {
Resource localCacheXml = getCacheXml();
// load cache.xml Resource and initialize the Cache
@@ -444,19 +422,19 @@ public class CacheFactoryBean implements BeanClassLoaderAware, BeanFactoryAware,
cache.setCopyOnRead(this.copyOnRead);
}
if (gatewayConflictResolver != null) {
cache.setGatewayConflictResolver((GatewayConflictResolver) gatewayConflictResolver);
((Cache) cache).setGatewayConflictResolver((GatewayConflictResolver) gatewayConflictResolver);
}
if (lockLease != null) {
cache.setLockLease(lockLease);
((Cache) cache).setLockLease(lockLease);
}
if (lockTimeout != null) {
cache.setLockTimeout(lockTimeout);
((Cache) cache).setLockTimeout(lockTimeout);
}
if (messageSyncInterval != null) {
cache.setMessageSyncInterval(messageSyncInterval);
((Cache) cache).setMessageSyncInterval(messageSyncInterval);
}
if (searchTimeout != null) {
cache.setSearchTimeout(searchTimeout);
((Cache) cache).setSearchTimeout(searchTimeout);
}
setHeapPercentages(cache);
@@ -468,7 +446,7 @@ public class CacheFactoryBean implements BeanClassLoaderAware, BeanFactoryAware,
}
/* (non-Javadoc) */
private void setHeapPercentages(Cache cache) {
private void setHeapPercentages(GemFireCache cache) {
if (criticalHeapPercentage != null) {
Assert.isTrue(criticalHeapPercentage > 0.0 && criticalHeapPercentage <= 100.0,
String.format("'criticalHeapPercentage' (%1$s) is invalid; must be > 0.0 and <= 100.0",
@@ -485,14 +463,14 @@ public class CacheFactoryBean implements BeanClassLoaderAware, BeanFactoryAware,
}
/* (non-Javadoc) */
private void registerTransactionListeners(Cache cache) {
private void registerTransactionListeners(GemFireCache cache) {
for (TransactionListener transactionListener : CollectionUtils.nullSafeCollection(transactionListeners)) {
cache.getCacheTransactionManager().addListener(transactionListener);
}
}
/* (non-Javadoc) */
private void registerTransactionWriter(Cache cache) {
private void registerTransactionWriter(GemFireCache cache) {
if (transactionWriter != null) {
cache.getCacheTransactionManager().setWriter(transactionWriter);
}

View File

@@ -18,19 +18,21 @@ package org.springframework.data.gemfire;
import java.util.concurrent.ConcurrentMap;
import org.springframework.data.gemfire.util.DistributedSystemUtils;
import org.springframework.util.ClassUtils;
import com.gemstone.gemfire.cache.CacheFactory;
import com.gemstone.gemfire.cache.Region;
/**
* The GemfireUtils class is a utility class encapsulating common functionality to access features and capabilities
* GemfireUtils is an abstract utility class encapsulating common functionality to access features and capabilities
* of GemFire based on version and other configuration meta-data.
*
* @author John Blum
* @see org.springframework.data.gemfire.util.DistributedSystemUtils
* @since 1.3.3
*/
public abstract class GemfireUtils {
public abstract class GemfireUtils extends DistributedSystemUtils {
public final static String GEMFIRE_VERSION = CacheFactory.getVersion();

View File

@@ -22,65 +22,34 @@ import java.util.Properties;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.data.gemfire.CacheFactoryBean;
import org.springframework.data.gemfire.GemfireUtils;
import org.springframework.data.gemfire.config.GemfireConstants;
import org.springframework.data.gemfire.util.CollectionUtils;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.GemFireCache;
import com.gemstone.gemfire.cache.client.ClientCache;
import com.gemstone.gemfire.cache.client.ClientCacheFactory;
import com.gemstone.gemfire.cache.client.Pool;
import com.gemstone.gemfire.cache.client.PoolManager;
import com.gemstone.gemfire.distributed.DistributedSystem;
import com.gemstone.gemfire.pdx.PdxSerializer;
/**
* FactoryBean dedicated to creating client caches (caches for client JVMs).
* Acts an utility class (as client caches are a subset with a particular
* configuration of the generic cache).
* FactoryBean dedicated to creating GemFire client caches.
*
* @author Costin Leau
* @author Lyndon Adams
* @author John Blum
* @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
*/
@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;
private PdxOptions(ClientCacheFactory factory) {
this.factory = factory;
}
public void run() {
if (pdxSerializer != null) {
Assert.isAssignable(PdxSerializer.class, pdxSerializer.getClass(), "Invalid pdx serializer used");
factory.setPdxSerializer((PdxSerializer) pdxSerializer);
}
if (pdxDiskStoreName != null) {
factory.setPdxDiskStore(pdxDiskStoreName);
}
if (pdxIgnoreUnreadFields != null) {
factory.setPdxIgnoreUnreadFields(pdxIgnoreUnreadFields);
}
if (pdxPersistent != null) {
factory.setPdxPersistent(pdxPersistent);
}
if (pdxReadSerialized != null) {
factory.setPdxReadSerialized(pdxReadSerialized);
}
}
}
protected Boolean readyForEvents = false;
private Pool pool;
@@ -91,21 +60,111 @@ public class ClientCacheFactoryBean extends CacheFactoryBean {
protected void postProcessPropertiesBeforeInitialization(Properties gemfireProperties) {
}
/**
* Fetches an existing GemFire ClientCache instance from the ClientCacheFactory.
*
* @param <T> is Class type extension of GemFireCache.
* @return the existing GemFire ClientCache instance if available.
* @throws com.gemstone.gemfire.cache.CacheClosedException if an existing GemFire Cache instance does not exist.
* @throws java.lang.IllegalStateException if the GemFire cache instance is not a ClientCache.
* @see com.gemstone.gemfire.cache.GemFireCache
* @see com.gemstone.gemfire.cache.client.ClientCacheFactory#getAnyInstance()
*/
@Override
protected GemFireCache fetchCache() {
return ClientCacheFactory.getAnyInstance();
@SuppressWarnings("unchecked")
protected <T extends GemFireCache> T fetchCache() {
return (T) ClientCacheFactory.getAnyInstance();
}
/**
* Resolves the GemFire System properties used to configure the GemFire ClientCache instance.
*
* @return a Properties object containing GemFire System properties used to configure
* the GemFire ClientCache instance.
*/
@Override
protected GemFireCache createCache(Object factory) {
return initializePool((ClientCacheFactory) factory).create();
protected Properties resolveProperties() {
Properties gemfireProperties = super.resolveProperties();
DistributedSystem distributedSystem = getDistributedSystem();
if (GemfireUtils.isConnected(distributedSystem)) {
Properties distributedSystemProperties = (Properties) distributedSystem.getProperties().clone();
distributedSystemProperties.putAll(gemfireProperties);
gemfireProperties = distributedSystemProperties;
}
return gemfireProperties;
}
/* (non-Javadoc) */
<T extends DistributedSystem> T getDistributedSystem() {
return GemfireUtils.getDistributedSystem();
}
/**
* Creates an instance of GemFire factory initialized with the given GemFire System Properties
* to create an instance of a GemFire 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.client.ClientCacheFactory
*/
@Override
protected Object createFactory(Properties gemfireProperties) {
return new ClientCacheFactory(gemfireProperties);
}
/**
* Initializes the GemFire factory used to create the GemFire client cache instance. Sets PDX options
* specified by the user.
*
* @param factory the GemFire factory used to create an instance of the GemFire client cache.
* @return the initialized GemFire client cache factory.
* @see #isPdxOptionsSpecified()
*/
@Override
protected Object prepareFactory(final Object factory) {
if (isPdxOptionsSpecified()) {
ClientCacheFactory clientCacheFactory = (ClientCacheFactory) factory;
if (pdxSerializer != null) {
Assert.isAssignable(PdxSerializer.class, pdxSerializer.getClass(), "Invalid pdx serializer used");
clientCacheFactory.setPdxSerializer((PdxSerializer) pdxSerializer);
}
if (pdxDiskStoreName != null) {
clientCacheFactory.setPdxDiskStore(pdxDiskStoreName);
}
if (pdxIgnoreUnreadFields != null) {
clientCacheFactory.setPdxIgnoreUnreadFields(pdxIgnoreUnreadFields);
}
if (pdxPersistent != null) {
clientCacheFactory.setPdxPersistent(pdxPersistent);
}
if (pdxReadSerialized != null) {
clientCacheFactory.setPdxReadSerialized(pdxReadSerialized);
}
}
return factory;
}
/**
* Creates a new GemFire cache instance using the provided factory.
*
* @param <T> parameterized Class type extension of GemFireCache.
* @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.client.ClientCacheFactory#create()
*/
@Override
@SuppressWarnings("unchecked")
protected <T extends GemFireCache> T createCache(Object factory) {
return (T) initializePool((ClientCacheFactory) factory).create();
}
/**
* Initialize the Pool settings on the ClientCacheFactory.
*
@@ -113,7 +172,7 @@ public class ClientCacheFactoryBean extends CacheFactoryBean {
* @see com.gemstone.gemfire.cache.client.ClientCacheFactory
*/
private ClientCacheFactory initializePool(ClientCacheFactory clientCacheFactory) {
return initializeClientCacheFactoryPool(clientCacheFactory, resolvePool(this.pool));
return initializeClientCacheFactory(clientCacheFactory, resolvePool(this.pool));
}
/**
@@ -160,7 +219,7 @@ public class ClientCacheFactoryBean extends CacheFactoryBean {
* @see com.gemstone.gemfire.cache.client.ClientCacheFactory
* @see com.gemstone.gemfire.cache.client.Pool
*/
private ClientCacheFactory initializeClientCacheFactoryPool(ClientCacheFactory clientCacheFactory, Pool pool) {
private ClientCacheFactory initializeClientCacheFactory(ClientCacheFactory clientCacheFactory, Pool pool) {
if (pool != null) {
clientCacheFactory.setPoolFreeConnectionTimeout(pool.getFreeConnectionTimeout());
clientCacheFactory.setPoolIdleTimeout(pool.getIdleTimeout());
@@ -193,44 +252,37 @@ public class ClientCacheFactoryBean extends CacheFactoryBean {
return clientCacheFactory;
}
/**
* 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
* @see com.gemstone.gemfire.cache.client.ClientCache
*/
@Override
protected void setPdxOptions(Object factory) {
if (factory instanceof ClientCacheFactory) {
new PdxOptions((ClientCacheFactory) factory).run();
}
protected <T extends GemFireCache> T postProcess(T cache) throws IOException {
return readyForEvents(super.postProcess(cache));
}
/**
* Inform the GemFire cluster that this client cache is ready to receive events.
*/
private void readyForEvents(){
ClientCache clientCache = ClientCacheFactory.getAnyInstance();
private <T extends GemFireCache> T readyForEvents(T clientCache) {
if (Boolean.TRUE.equals(getReadyForEvents()) && !clientCache.isClosed()) {
try {
clientCache.readyForEvents();
((ClientCache) clientCache).readyForEvents();
}
catch (IllegalStateException ignore) {
// cannot be called for a non-durable client so exception is thrown
}
}
}
/**
* Register for events after Pool and Regions have been created and iff non-durable client...
*
* @param cache the GemFire Cache instance to process.
* @return the processed GemFire Cache instance after ready for events.
* @throws IOException if an error occurs during post processing.
* @see org.springframework.data.gemfire.CacheFactoryBean#postProcess(com.gemstone.gemfire.cache.Cache)
* @see #readyForEvents()
* @see com.gemstone.gemfire.cache.Cache
*/
@Override
protected Cache postProcess(final Cache cache) throws IOException {
Cache localCache = super.postProcess(cache);
readyForEvents();
return localCache;
return clientCache;
}
@Override

View File

@@ -0,0 +1,40 @@
/*
* 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.util;
import com.gemstone.gemfire.distributed.DistributedSystem;
import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem;
/**
* DistributedSystemUtils is an abstract utility class for working with the GemFire DistributedSystem.
*
* @author John Blum
* @see com.gemstone.gemfire.distributed.DistributedSystem
* @since 1.7.0
*/
public abstract class DistributedSystemUtils {
@SuppressWarnings("unchecked")
public static <T extends DistributedSystem> T getDistributedSystem() {
return (T) InternalDistributedSystem.getAnyInstance();
}
public static boolean isConnected(DistributedSystem distributedSystem) {
return (distributedSystem != null && distributedSystem.isConnected());
}
}