Creates an AbstractCacheFactoryBean class hierarchy.

Create the org.springframework.data.gemfire.AbstractBasicCacheFactoryBean class.

Create the org.springframework.data.gemfire.AbstractPdxConfigurableCacheFactoryBean class, extending AbstractBasicCacheFactoryBean.

Refactor org.springframework.data.gemfire.CacheFactoryBean to (indirectly ) extend AbstractBasicCacheFactoryBean.

Resolves gh-493.
This commit is contained in:
John Blum
2021-03-09 15:52:25 -08:00
parent 15d597e917
commit a795930817
7 changed files with 1548 additions and 1159 deletions

View File

@@ -0,0 +1,736 @@
/*
* Copyright 2020 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
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.gemfire;
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalStateException;
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newRuntimeException;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Optional;
import java.util.Properties;
import org.apache.geode.GemFireCheckedException;
import org.apache.geode.GemFireException;
import org.apache.geode.cache.Cache;
import org.apache.geode.cache.CacheFactory;
import org.apache.geode.cache.GemFireCache;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.client.ClientCache;
import org.apache.geode.cache.client.ClientCacheFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.Phased;
import org.springframework.core.io.Resource;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
import org.springframework.dao.support.PersistenceExceptionTranslator;
import org.springframework.data.gemfire.client.ClientCacheFactoryBean;
import org.springframework.data.gemfire.config.annotation.ClientCacheConfigurer;
import org.springframework.data.gemfire.config.annotation.PeerCacheConfigurer;
import org.springframework.data.gemfire.support.AbstractFactoryBeanSupport;
import org.springframework.data.gemfire.support.GemfireBeanFactoryLocator;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* Abstract base class for {@link CacheFactoryBean} and {@link ClientCacheFactoryBean} classes
* used to create Apache Geode peer {@link Cache} and {@link ClientCache} instances, respectively.
*
* This class implements Spring's {@link PersistenceExceptionTranslator} interface and is auto-detected by Spring's
* {@link PersistenceExceptionTranslationPostProcessor} to enable AOP-based translation of native Apache Geode
* {@link RuntimeException RuntimeExceptions} to Spring's {@link DataAccessException} hierarchy. Therefore,
* the presence of this class automatically enables a {@link PersistenceExceptionTranslationPostProcessor}
* to translate Apache Geode {@link RuntimeException RuntimeExceptions} appropriately.
*
* Importantly, this class encapsulates configure applicable to tuning Apache Geode in response to JVM Heap memory.
* Since Apache Geode stores data in-memory, on the JVM Heap, it is important that Aapche Geode be tuned to monitor
* the JVM Heap and respond accordingly to memory pressure, by evicting data and issuing warnings when the JVM Heap
* reaches critical mass.
*
* @author John Blum
* @see java.io.File
* @see java.util.Properties
* @see org.apache.geode.cache.Cache
* @see org.apache.geode.cache.CacheFactory
* @see org.apache.geode.cache.GemFireCache
* @see org.apache.geode.cache.Region
* @see org.apache.geode.cache.client.ClientCache
* @see org.apache.geode.cache.client.ClientCacheFactory
* @see org.springframework.beans.factory.BeanFactory
* @see org.springframework.beans.factory.DisposableBean
* @see org.springframework.beans.factory.FactoryBean
* @see org.springframework.beans.factory.InitializingBean
* @see org.springframework.context.Phased
* @see org.springframework.core.io.Resource
* @see org.springframework.dao.DataAccessException
* @see org.springframework.dao.support.PersistenceExceptionTranslator
* @see org.springframework.data.gemfire.CacheFactoryBean
* @see org.springframework.data.gemfire.client.ClientCacheFactoryBean
* @see org.springframework.data.gemfire.config.annotation.ClientCacheConfigurer
* @see org.springframework.data.gemfire.config.annotation.PeerCacheConfigurer
* @see org.springframework.data.gemfire.support.AbstractFactoryBeanSupport
* @see org.springframework.data.gemfire.support.GemfireBeanFactoryLocator
* @since 2.5.0
*/
public abstract class AbstractBasicCacheFactoryBean extends AbstractFactoryBeanSupport<GemFireCache>
implements DisposableBean, InitializingBean, PersistenceExceptionTranslator, Phased {
private boolean close = true;
private boolean useBeanFactoryLocator = false;
private int phase = -1;
private Boolean copyOnRead;
private CacheFactoryInitializer<?> cacheFactoryInitializer;
private Float criticalHeapPercentage;
private Float criticalOffHeapPercentage;
private Float evictionHeapPercentage;
private Float evictionOffHeapPercentage;
private GemfireBeanFactoryLocator beanFactoryLocator;
private GemFireCache cache;
private Properties properties;
private Resource cacheXml;
/**
* Gets a reference to the configured {@link GemfireBeanFactoryLocator} used to resolve Spring bean references
* in Apache Geode native configuration metadata (e.g. {@literal cache.xml}).
*
* @param beanFactoryLocator reference to the configured {@link GemfireBeanFactoryLocator}.
* @see org.springframework.data.gemfire.support.GemfireBeanFactoryLocator
*/
protected void setBeanFactoryLocator(@Nullable GemfireBeanFactoryLocator beanFactoryLocator) {
this.beanFactoryLocator = beanFactoryLocator;
}
/**
* Returns a reference to the configured {@link GemfireBeanFactoryLocator} used to resolve Spring bean references
* in Apache Geode native configuration metadata (e.g. {@literal cache.xml}).
*
* @return a reference to the configured {@link GemfireBeanFactoryLocator}.
* @see org.springframework.data.gemfire.support.GemfireBeanFactoryLocator
*/
public @Nullable GemfireBeanFactoryLocator getBeanFactoryLocator() {
return this.beanFactoryLocator;
}
/**
* Sets a reference to the constructed, configured an initialized {@link GemFireCache} instance created by
* this cache {@link FactoryBean}.
*
* @param cache {@link GemFireCache} created by this {@link FactoryBean}.
* @see org.apache.geode.cache.GemFireCache
*/
protected void setCache(@Nullable GemFireCache cache) {
this.cache = cache;
}
/**
* Returns a reference to the constructed, configured an initialized {@link GemFireCache} instance created by
* this cache {@link FactoryBean}.
*
* @return a reference to the {@link GemFireCache} created by this {@link FactoryBean}.
* @see org.apache.geode.cache.GemFireCache
*/
@SuppressWarnings("unchecked")
public @Nullable <T extends GemFireCache> T getCache() {
return (T) this.cache;
}
/**
* Set the {@link CacheFactoryInitializer} called by this {@link FactoryBean} to initialize the Apache Geode
* cache factory used to create the cache constructed by this {@link FactoryBean}.
*
* @param cacheFactoryInitializer {@link CacheFactoryInitializer} called to initialize the cache factory.
* @see org.springframework.data.gemfire.CacheFactoryBean.CacheFactoryInitializer
*/
@SuppressWarnings("rawtypes")
public void setCacheFactoryInitializer(@Nullable CacheFactoryInitializer cacheFactoryInitializer) {
this.cacheFactoryInitializer = cacheFactoryInitializer;
}
/**
* Return the {@link CacheFactoryInitializer} called by this {@link FactoryBean} to initialize the Apache Geode
* cache factory used to create the cache constructed by this {@link FactoryBean}.
*
* @return the {@link CacheFactoryInitializer} called to initialize the cache factory.
* @see org.springframework.data.gemfire.CacheFactoryBean.CacheFactoryInitializer
*/
@SuppressWarnings("rawtypes")
public @Nullable CacheFactoryInitializer getCacheFactoryInitializer() {
return this.cacheFactoryInitializer;
}
/**
* Sets a reference to an (optional) Apache Geode native {@literal cache.xml} {@link Resource}.
*
* @param cacheXml reference to an (optional) Apache Geode native {@literal cache.xml} {@link Resource}.
* @see org.springframework.core.io.Resource
*/
public void setCacheXml(@Nullable Resource cacheXml) {
this.cacheXml = cacheXml;
}
/**
* Returns a reference to an (optional) Apache Geode native {@literal cache.xml} {@link Resource}.
*
* @return a reference to an (optional) Apache Geode native {@literal cache.xml} {@link Resource}.
* @see org.springframework.core.io.Resource
*/
public @Nullable Resource getCacheXml() {
return this.cacheXml;
}
/**
* Determines whether the {@literal cache.xml} {@link File} is present.
*
* @return boolean value indicating whether a {@literal cache.xml} {@link File} is present.
* @see org.springframework.core.io.Resource#isFile()
* @see #getCacheXml()
*/
@SuppressWarnings("unused")
protected boolean isCacheXmlAvailable() {
Resource cacheXml = getCacheXml();
return cacheXml != null && cacheXml.isFile();
}
/**
* Returns the Apache Geode native {@literal cache.xml} {@link Resource} as a {@link File}.
*
* @return the Apache Geode native {@literal cache.xml} {@link Resource} as a {@link File}.
* @throws IllegalStateException if the {@link Resource} is not a valid {@link File} in the file system
* or a general problem exists accessing or reading the {@link File}.
* @see org.springframework.core.io.Resource
* @see java.io.File
* @see #getCacheXml()
*/
@SuppressWarnings("unused")
protected File getCacheXmlFile() {
try {
return getCacheXml().getFile();
}
catch (Throwable cause) {
throw newIllegalStateException(cause, "Resource [%s] is not resolvable as a file", getCacheXml());
}
}
/**
* Returns a boolean value used to determine whether the cache will be closed on shutdown of the Spring application.
*
* @return a boolean value used to determine whether the cache will be closed on shutdown of the Spring application.
*/
public boolean isClose() {
return this.close;
}
/**
* Sets a boolean value used to determine whether the cache should be closed on shutdown of the Spring application.
*
* @param close boolean value used to determine whether the cache will be closed on shutdown
* of the Spring application.
*/
public void setClose(boolean close) {
this.close = close;
}
/**
* Sets the {@link GemFireCache#getCopyOnRead()} property of the {@link GemFireCache cache}.
*
* @param copyOnRead a {@link Boolean value} indicating whether {@link Object objects}
* stored in the {@link GemFireCache cache} are copied on read (i.e. {@link Region#get(Object)}.
*/
public void setCopyOnRead(@Nullable Boolean copyOnRead) {
this.copyOnRead = copyOnRead;
}
/**
* Returns the configuration of the {@link GemFireCache#getCopyOnRead()} property on the {@link GemFireCache cache}.
*
* @return a {@link Boolean value} indicating whether {@link Object objects}
* stored in the {@link GemFireCache cache} are copied on read (i.e. {@link Region#get(Object)}.
*/
public @Nullable Boolean getCopyOnRead() {
return this.copyOnRead;
}
/**
* Determines whether {@link Object objects} stored in the {@link GemFireCache cache} are copied
* when read (i.e. {@link Region#get(Object)}.
*
* @return a boolean value indicating whether {@link Object objects} stored in the {@link GemFireCache cache}
* are copied on read (i.e. {@link Region#get(Object)}.
*/
public boolean isCopyOnRead() {
return Boolean.TRUE.equals(this.copyOnRead);
}
/**
* Set the Cache's critical heap percentage attribute.
*
* @param criticalHeapPercentage floating point value indicating the critical heap percentage.
*/
public void setCriticalHeapPercentage(@Nullable Float criticalHeapPercentage) {
this.criticalHeapPercentage = criticalHeapPercentage;
}
/**
* @return the criticalHeapPercentage
*/
public Float getCriticalHeapPercentage() {
return this.criticalHeapPercentage;
}
/**
* Set the cache's critical off-heap percentage property.
*
* @param criticalOffHeapPercentage floating point value indicating the critical off-heap percentage.
*/
public void setCriticalOffHeapPercentage(@Nullable Float criticalOffHeapPercentage) {
this.criticalOffHeapPercentage = criticalOffHeapPercentage;
}
/**
* @return the criticalOffHeapPercentage
*/
public Float getCriticalOffHeapPercentage() {
return this.criticalOffHeapPercentage;
}
/**
* Set the Cache's eviction heap percentage attribute.
*
* @param evictionHeapPercentage float-point value indicating the Cache's heap use percentage to trigger eviction.
*/
public void setEvictionHeapPercentage(Float evictionHeapPercentage) {
this.evictionHeapPercentage = evictionHeapPercentage;
}
/**
* @return the evictionHeapPercentage
*/
public Float getEvictionHeapPercentage() {
return this.evictionHeapPercentage;
}
/**
* Set the cache's eviction off-heap percentage property.
*
* @param evictionOffHeapPercentage float-point value indicating the percentage of off-heap use triggering eviction.
*/
public void setEvictionOffHeapPercentage(Float evictionOffHeapPercentage) {
this.evictionOffHeapPercentage = evictionOffHeapPercentage;
}
/**
* @return the evictionOffHeapPercentage
*/
public Float getEvictionOffHeapPercentage() {
return this.evictionOffHeapPercentage;
}
/**
* Returns the cache object reference created by this cache {@link FactoryBean}.
*
* @return the cache object reference created by this cache {@link FactoryBean}.
* @see org.springframework.beans.factory.FactoryBean#getObject()
* @see org.apache.geode.cache.GemFireCache
* @see #doGetObject()
* @see #getCache()
*/
@Override
public GemFireCache getObject() throws Exception {
return Optional.<GemFireCache>ofNullable(getCache()).orElseGet(this::doGetObject);
}
protected abstract GemFireCache doGetObject();
/**
* Returns the {@link Class type} of {@link GemFireCache} produced by this cache {@link FactoryBean}.
*
* @return the {@link Class type} type of {@link GemFireCache} produced by this cache {@link FactoryBean}.
* @see org.springframework.beans.factory.FactoryBean#getObjectType()
*/
@Override
public Class<? extends GemFireCache> getObjectType() {
GemFireCache cache = getCache();
return cache != null ? cache.getClass() : doGetObjectType();
}
protected Class<? extends GemFireCache> doGetObjectType() {
return GemFireCache.class;
}
/**
* Set the lifecycle phase for this cache bean in the Spring container.
*
* @param phase {@link Integer#TYPE} value used as the lifecycle phase for this cache bean in the Spring container.
* @see org.springframework.context.Phased#getPhase()
*/
protected void setPhase(int phase) {
this.phase = phase;
}
/**
* Returns the configured lifecycle phase for this cache bean in the Spring container.
*
* @return an {@link Integer#TYPE} used as the lifecycle phase for this cache bean in the Spring container.
* @see org.springframework.context.Phased#getPhase()
*/
@Override
public int getPhase() {
return this.phase;
}
/**
* Sets and then returns a reference to Apache Geode {@link Properties} used to configure the cache.
*
* @param properties reference to Apache Geode {@link Properties} used to configure the cache.
* @return a reference to Apache Geode {@link Properties} used to configure the cache.
* @see #setProperties(Properties)
* @see #getProperties()
* @see java.util.Properties
*/
public Properties setAndGetProperties(@Nullable Properties properties) {
setProperties(properties);
return getProperties();
}
/**
* Sets the Apache Geode {@link Properties} used to configure the cache.
*
* @param properties reference to Apache Geode {@link Properties} used to configure the cache.
* @see java.util.Properties
*/
public void setProperties(@Nullable Properties properties) {
this.properties = properties;
}
/**
* Returns a reference to the Apache Geode {@link Properties} used to configure the cache.
*
* @return a reference to Apache Geode {@link Properties}.
* @see java.util.Properties
*/
public @Nullable Properties getProperties() {
return this.properties;
}
/**
* Determines whether the {@link GemfireBeanFactoryLocator} has been enabled.
*
* @return a boolean value indicating whether the {@link GemfireBeanFactoryLocator} has been enabled.
* @see org.springframework.data.gemfire.support.GemfireBeanFactoryLocator
*/
public boolean isUseBeanFactoryLocator() {
return this.useBeanFactoryLocator;
}
/**
* Sets a boolean value used to determine whether to enable the {@link GemfireBeanFactoryLocator}.
*
* @param use boolean value used to determine whether to enable the {@link GemfireBeanFactoryLocator}.
* @see org.springframework.data.gemfire.support.GemfireBeanFactoryLocator
*/
public void setUseBeanFactoryLocator(boolean use) {
this.useBeanFactoryLocator = use;
}
/**
* Initializes this cache {@link FactoryBean} after all properties for this cache bean have been set
* by the Spring container.
*
* @throws Exception if initialization fails.
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
* @see #applyCacheConfigurers()
* @see #initBeanFactoryLocator()
*/
@Override
public void afterPropertiesSet() throws Exception {
applyCacheConfigurers();
initBeanFactoryLocator();
}
/**
* Applies any user-defined cache configurers (e.g. {@link ClientCacheConfigurer} or {@link PeerCacheConfigurer})
* to this cache {@link FactoryBean} before cache construction, configuration and initialization.
*/
protected abstract void applyCacheConfigurers();
/**
* Null-safe method used to close the {@link GemFireCache} by calling {@link GemFireCache#close()}
* iff the cache is not already closed.
*
* @param cache {@link GemFireCache} to close.
* @see org.apache.geode.cache.GemFireCache#isClosed()
* @see org.apache.geode.cache.GemFireCache#close()
*/
protected void close(@Nullable GemFireCache cache) {
Optional.ofNullable(cache)
.filter(it -> !it.isClosed())
.ifPresent(GemFireCache::close);
setCache(null);
}
/**
* Destroys the cache bean on Spring Container shutdown.
*
* @see org.springframework.beans.factory.DisposableBean#destroy()
* @see #destroyBeanFactoryLocator()
* @see #close(GemFireCache)
* @see #isClose()
*/
@Override
public void destroy() {
if (isClose()) {
close(fetchCache());
destroyBeanFactoryLocator();
}
}
/**
* Destroys the {@link GemfireBeanFactoryLocator}.
*
* @see org.springframework.data.gemfire.support.GemfireBeanFactoryLocator#destroy()
*/
protected void destroyBeanFactoryLocator() {
Optional.ofNullable(getBeanFactoryLocator())
.ifPresent(GemfireBeanFactoryLocator::destroy);
setBeanFactoryLocator(null);
}
private boolean isHeapPercentageValid(@NonNull Float heapPercentage) {
return heapPercentage >= 0.0f && heapPercentage <= 100.0f;
}
protected GemFireCache configureHeapPercentages(GemFireCache cache) {
Optional.ofNullable(getCriticalHeapPercentage()).ifPresent(criticalHeapPercentage -> {
Assert.isTrue(isHeapPercentageValid(criticalHeapPercentage), String.format(
"criticalHeapPercentage [%s] is not valid; must be >= 0.0 and <= 100.0", criticalHeapPercentage));
cache.getResourceManager().setCriticalHeapPercentage(criticalHeapPercentage);
});
Optional.ofNullable(getEvictionHeapPercentage()).ifPresent(evictionHeapPercentage -> {
Assert.isTrue(isHeapPercentageValid(evictionHeapPercentage), String.format(
"evictionHeapPercentage [%s] is not valid; must be >= 0.0 and <= 100.0", evictionHeapPercentage));
cache.getResourceManager().setEvictionHeapPercentage(evictionHeapPercentage);
});
return cache;
}
protected GemFireCache configureOffHeapPercentages(GemFireCache cache) {
Optional.ofNullable(getCriticalOffHeapPercentage()).ifPresent(criticalOffHeapPercentage -> {
Assert.isTrue(isHeapPercentageValid(criticalOffHeapPercentage), String.format(
"criticalOffHeapPercentage [%s] is not valid; must be >= 0.0 and <= 100.0", criticalOffHeapPercentage));
cache.getResourceManager().setCriticalOffHeapPercentage(criticalOffHeapPercentage);
});
Optional.ofNullable(getEvictionOffHeapPercentage()).ifPresent(evictionOffHeapPercentage -> {
Assert.isTrue(isHeapPercentageValid(evictionOffHeapPercentage), String.format(
"evictionOffHeapPercentage [%s] is not valid; must be >= 0.0 and <= 100.0", evictionOffHeapPercentage));
cache.getResourceManager().setEvictionOffHeapPercentage(evictionOffHeapPercentage);
});
return cache;
}
/**
* Fetches an existing cache instance from the Apache Geode cache factory.
*
* @param <T> parameterized {@link Class} type extending {@link GemFireCache}.
* @return an existing cache instance if available.
* @throws org.apache.geode.cache.CacheClosedException if an existing cache instance does not exist.
* @see org.apache.geode.cache.client.ClientCacheFactory#getAnyInstance()
* @see org.apache.geode.cache.CacheFactory#getAnyInstance()
* @see org.apache.geode.cache.GemFireCache
* @see #doFetchCache()
* @see #getCache()
*/
protected <T extends GemFireCache> T fetchCache() {
T cache = getCache();
return cache != null ? cache : doFetchCache();
}
protected abstract <T extends GemFireCache> T doFetchCache();
/**
* Initializes the {@link GemfireBeanFactoryLocator} if {@link #isUseBeanFactoryLocator()} returns {@literal true}
* and an existing {@link #getBeanFactoryLocator()} is not already present.
*
* @see org.springframework.data.gemfire.support.GemfireBeanFactoryLocator#newBeanFactoryLocator(BeanFactory, String)
* @see #isUseBeanFactoryLocator()
* @see #getBeanFactoryLocator()
* @see #getBeanFactory()
* @see #getBeanName()
*/
protected void initBeanFactoryLocator() {
if (isUseBeanFactoryLocator() && getBeanFactoryLocator() == null) {
setBeanFactoryLocator(GemfireBeanFactoryLocator.newBeanFactoryLocator(getBeanFactory(), getBeanName()));
}
}
/**
* Initializes the given {@link CacheFactory} or {@link ClientCacheFactory}
* with the configured {@link CacheFactoryInitializer}.
*
* @param factory {@link CacheFactory} or {@link ClientCacheFactory} to initialize.
* @return the initialized {@link CacheFactory} or {@link ClientCacheFactory}.
* @see org.springframework.data.gemfire.CacheFactoryBean.CacheFactoryInitializer#initialize(Object)
* @see org.apache.geode.cache.client.ClientCacheFactory
* @see org.apache.geode.cache.CacheFactory
* @see #getCacheFactoryInitializer()
*/
@Nullable
@SuppressWarnings("unchecked")
protected Object initializeFactory(Object factory) {
return Optional.ofNullable(getCacheFactoryInitializer())
.map(cacheFactoryInitializer -> cacheFactoryInitializer.initialize(factory))
.orElse(factory);
}
/**
* Loads the configured {@literal cache.xml} to initialize the cache.
*
* @param <T> parameterized {@link Class} type extending {@link GemFireCache}.
* @param cache cache instance to initialized with {@literal cache.xml}.
* @return the given cache instance.
* @throws RuntimeException if the configured {@literal cache.xml} file could not be loaded.
* @see org.apache.geode.cache.GemFireCache#loadCacheXml(InputStream)
*/
protected <T extends GemFireCache> T loadCacheXml(T cache) {
// Load the cache.xml file (Resource) and initialize the cache
Optional.ofNullable(getCacheXml()).ifPresent(cacheXml -> {
try {
logDebug("Initializing cache with [%s]", cacheXml);
cache.loadCacheXml(cacheXml.getInputStream());
}
catch (IOException cause) {
throw newRuntimeException(cause, "Failed to load cache.xml [%s]", cacheXml);
}
});
return cache;
}
/**
* Resolves the Apache Geode {@link Properties} used to configure the {@link Cache}.
*
* @return the resolved Apache Geode {@link Properties} used to configure the {@link Cache}.
* @see #setAndGetProperties(Properties)
* @see #getProperties()
*/
protected Properties resolveProperties() {
return Optional.ofNullable(getProperties())
.orElseGet(() -> setAndGetProperties(new Properties()));
}
/**
* Translates the thrown Apache Geode {@link RuntimeException} to a corresponding {@link Exception} from Spring's
* generic {@link DataAccessException} hierarchy if possible.
*
* @param exception the Apache Geode {@link RuntimeException} to translate.
* @return the translated Spring {@link DataAccessException} or {@literal null}
* if the Apache Geode {@link RuntimeException} could not be translated.
* @see org.springframework.dao.support.PersistenceExceptionTranslator#translateExceptionIfPossible(RuntimeException)
* @see org.springframework.dao.DataAccessException
*/
@Override
public DataAccessException translateExceptionIfPossible(@Nullable RuntimeException exception) {
if (exception instanceof IllegalArgumentException) {
DataAccessException wrapped = GemfireCacheUtils.convertQueryExceptions(exception);
// ignore conversion if generic exception is returned
if (!(wrapped instanceof GemfireSystemException)) {
return wrapped;
}
}
if (exception instanceof GemFireException) {
return GemfireCacheUtils.convertGemfireAccessException((GemFireException) exception);
}
if (exception.getCause() instanceof GemFireException) {
return GemfireCacheUtils.convertGemfireAccessException((GemFireException) exception.getCause());
}
if (exception.getCause() instanceof GemFireCheckedException) {
return GemfireCacheUtils.convertGemfireAccessException((GemFireCheckedException) exception.getCause());
}
return null;
}
/**
* Callback interface for initializing either a {@link CacheFactory} or a {@link ClientCacheFactory} instance,
* which is used to create an instance of {@link GemFireCache}.
*
* @see org.apache.geode.cache.CacheFactory
* @see org.apache.geode.cache.client.ClientCacheFactory
*/
@FunctionalInterface
public interface CacheFactoryInitializer<T> {
/**
* Initialize the given cache factory.
*
* @param cacheFactory cache factory to initialize.
* @return the given cache factory.
* @see org.apache.geode.cache.CacheFactory
* @see org.apache.geode.cache.client.ClientCacheFactory
*/
T initialize(T cacheFactory);
}
}

View File

@@ -0,0 +1,209 @@
/*
* Copyright 2020 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
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.gemfire;
import java.util.Optional;
import org.apache.geode.cache.Cache;
import org.apache.geode.cache.DiskStore;
import org.apache.geode.cache.GemFireCache;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.client.ClientCache;
import org.apache.geode.pdx.PdxSerializer;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;
/**
* Abstract base class encapsulating PDX configuration metadata applied to both Apache Geode {@link ClientCache}
* and {@literal peer} {@link Cache} instances.
*
* @author John Blum
* @see org.apache.geode.cache.Cache
* @see org.apache.geode.cache.GemFireCache
* @see org.apache.geode.cache.Region
* @see org.apache.geode.cache.client.ClientCache
* @see org.apache.geode.pdx.PdxSerializer
* @see org.springframework.data.gemfire.AbstractBasicCacheFactoryBean
* @since 2.5.0
*/
public abstract class AbstractPdxConfigurableCacheFactoryBean extends AbstractBasicCacheFactoryBean {
private Boolean pdxIgnoreUnreadFields;
private Boolean pdxPersistent;
private Boolean pdxReadSerialized;
private PdxSerializer pdxSerializer;
private String pdxDiskStoreName;
/**
* Sets the {@link String name} of the Apache Geode {@link DiskStore} used to store PDX metadata.
*
* @param pdxDiskStoreName {@link String name} for the PDX {@link DiskStore}.
* @see org.apache.geode.cache.CacheFactory#setPdxDiskStore(String)
* @see org.apache.geode.cache.DiskStore#getName()
*/
public void setPdxDiskStoreName(@Nullable String pdxDiskStoreName) {
this.pdxDiskStoreName = pdxDiskStoreName;
}
/**
* Gets the {@link String name} of the Apache Geode {@link DiskStore} used to store PDX metadata.
*
* @return the {@link String name} of the PDX {@link DiskStore}.
* @see org.apache.geode.cache.GemFireCache#getPdxDiskStore()
* @see org.apache.geode.cache.DiskStore#getName()
*/
public @Nullable String getPdxDiskStoreName() {
return this.pdxDiskStoreName;
}
/**
* Configures whether PDX will ignore unread fields when deserializing PDX bytes back to an {@link Object}.
*
* Defaults to {@literal false}.
*
* @param pdxIgnoreUnreadFields {@link Boolean} value controlling ignoring unread fields.
* @see org.apache.geode.cache.CacheFactory#setPdxIgnoreUnreadFields(boolean)
*/
public void setPdxIgnoreUnreadFields(@Nullable Boolean pdxIgnoreUnreadFields) {
this.pdxIgnoreUnreadFields = pdxIgnoreUnreadFields;
}
/**
* Gets the configuration determining whether PDX will ignore unread fields when deserializing PDX bytes
* back to an {@link Object}.
*
* Defaults to {@literal false}.
*
* @return a {@link Boolean} value controlling ignoring unread fields.
* @see org.apache.geode.cache.GemFireCache#getPdxIgnoreUnreadFields()
*/
public @Nullable Boolean getPdxIgnoreUnreadFields() {
return this.pdxIgnoreUnreadFields;
}
/**
* Configures whether {@link Class type} metadata for {@link Object objects} serialized to PDX
* will be persisted to disk.
*
* @param pdxPersistent {@link Boolean} value controlling whether PDX {@link Class type} metadata
* will be persisted to disk.
* @see org.apache.geode.cache.CacheFactory#setPdxPersistent(boolean)
*/
public void setPdxPersistent(@Nullable Boolean pdxPersistent) {
this.pdxPersistent = pdxPersistent;
}
/**
* Gets the configuration determining whether {@link Class type} metadata for {@link Object objects} serialized
* to PDX will be persisted to disk.
*
* @return a {@link Boolean} value controlling whether PDX {@link Class type} metadata will be persisted to disk.
* @see org.apache.geode.cache.GemFireCache#getPdxPersistent()
*/
public @Nullable Boolean getPdxPersistent() {
return this.pdxPersistent;
}
/**
* Configures whether {@link Object objects} stored in the Apache Geode {@link GemFireCache cache} as PDX
* will be read back as PDX bytes or (deserialized) as an {@link Object} when {@link Region#get(Object)}
* is called.
*
* @param pdxReadSerialized {@link Boolean} value controlling the PDX read serialized function.
* @see org.apache.geode.cache.CacheFactory#setPdxReadSerialized(boolean)
*/
public void setPdxReadSerialized(@Nullable Boolean pdxReadSerialized) {
this.pdxReadSerialized = pdxReadSerialized;
}
/**
* Gets the configuration determining whether {@link Object objects} stored in the Apache Geode
* {@link GemFireCache cache} as PDX will be read back as PDX bytes or (deserialized) as an {@link Object}
* when {@link Region#get(Object)} is called.
*
* @return a {@link Boolean} value controlling the PDX read serialized function.
* @see org.apache.geode.cache.GemFireCache#getPdxReadSerialized()
*/
public @Nullable Boolean getPdxReadSerialized() {
return this.pdxReadSerialized;
}
/**
* Configures a reference to {@link PdxSerializer} used by this cache to de/serialize {@link Object objects}
* stored in the cache and distributed/transferred across the distributed system as PDX bytes.
*
* @param serializer {@link PdxSerializer} used by this cache to de/serialize {@link Object objects} as PDX.
* @see org.apache.geode.cache.CacheFactory#setPdxSerializer(PdxSerializer)
* @see org.apache.geode.pdx.PdxSerializer
*/
public void setPdxSerializer(@Nullable PdxSerializer serializer) {
this.pdxSerializer = serializer;
}
/**
* Get a reference to the configured {@link PdxSerializer} used by this cache to de/serialize {@link Object objects}
* stored in the cache and distributed/transferred across the distributed system as PDX bytes.
*
* @return a reference to the configured {@link PdxSerializer}.
* @see org.apache.geode.cache.GemFireCache#getPdxSerializer()
* @see org.apache.geode.pdx.PdxSerializer
*/
public @Nullable PdxSerializer getPdxSerializer() {
return this.pdxSerializer;
}
/**
* Configures the cache to use PDX serialization.
*
* @param pdxConfigurer {@link PdxConfigurer} used to configure the cache with PDX serialization.
* @return the {@link PdxConfigurer#getTarget()}.
*/
protected <T> T configurePdx(PdxConfigurer<T> pdxConfigurer) {
Optional.ofNullable(getPdxDiskStoreName())
.filter(StringUtils::hasText)
.ifPresent(pdxConfigurer::setDiskStoreName);
Optional.ofNullable(getPdxIgnoreUnreadFields()).ifPresent(pdxConfigurer::setIgnoreUnreadFields);
Optional.ofNullable(getPdxPersistent()).ifPresent(pdxConfigurer::setPersistent);
Optional.ofNullable(getPdxReadSerialized()).ifPresent(pdxConfigurer::setReadSerialized);
Optional.ofNullable(getPdxSerializer()).ifPresent(pdxConfigurer::setSerializer);
return pdxConfigurer.getTarget();
}
public interface PdxConfigurer<T> {
T getTarget();
PdxConfigurer<T> setDiskStoreName(String diskStoreName);
PdxConfigurer<T> setIgnoreUnreadFields(Boolean ignoreUnreadFields);
PdxConfigurer<T> setPersistent(Boolean persistent);
PdxConfigurer<T> setReadSerialized(Boolean readSerialized);
PdxConfigurer<T> setSerializer(PdxSerializer pdxSerializer);
}
}

View File

@@ -16,9 +16,7 @@
package org.springframework.data.gemfire.client;
import static java.util.stream.StreamSupport.stream;
import static org.springframework.data.gemfire.util.ArrayUtils.nullSafeArray;
import static org.springframework.data.gemfire.util.CollectionUtils.nullSafeCollection;
import static org.springframework.data.gemfire.util.CollectionUtils.nullSafeIterable;
import java.net.InetSocketAddress;
import java.util.Arrays;
@@ -27,6 +25,8 @@ import java.util.List;
import java.util.Optional;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Supplier;
import java.util.stream.StreamSupport;
import org.apache.geode.cache.CacheClosedException;
import org.apache.geode.cache.GemFireCache;
@@ -35,6 +35,7 @@ import org.apache.geode.cache.client.ClientCacheFactory;
import org.apache.geode.cache.client.Pool;
import org.apache.geode.cache.client.SocketFactory;
import org.apache.geode.distributed.DistributedSystem;
import org.apache.geode.pdx.PdxSerializer;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.context.ApplicationContext;
@@ -50,9 +51,12 @@ import org.springframework.data.gemfire.config.annotation.ClientCacheConfigurer;
import org.springframework.data.gemfire.config.xml.GemfireConstants;
import org.springframework.data.gemfire.support.ConnectionEndpoint;
import org.springframework.data.gemfire.support.ConnectionEndpointList;
import org.springframework.data.gemfire.util.ArrayUtils;
import org.springframework.data.gemfire.util.CollectionUtils;
import org.springframework.data.gemfire.util.SpringUtils;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
@@ -67,12 +71,14 @@ import org.springframework.util.StringUtils;
* @see org.apache.geode.cache.client.ClientCache
* @see org.apache.geode.cache.client.ClientCacheFactory
* @see org.apache.geode.cache.client.Pool
* @see org.apache.geode.cache.client.SocketFactory
* @see org.apache.geode.distributed.DistributedSystem
* @see org.apache.geode.pdx.PdxSerializer
* @see org.springframework.beans.factory.BeanFactory
* @see org.springframework.beans.factory.FactoryBean
* @see org.springframework.context.ApplicationContext
* @see org.springframework.context.ApplicationListener
* @see org.springframework.context.event.ApplicationContextEvent
* @see org.springframework.context.event.ContextRefreshedEvent
* @see org.springframework.data.gemfire.CacheFactoryBean
* @see org.springframework.data.gemfire.config.annotation.ClientCacheConfigurer
@@ -90,8 +96,8 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
private Boolean subscriptionEnabled;
private Boolean threadLocalConnections;
private ConnectionEndpointList locators = new ConnectionEndpointList();
private ConnectionEndpointList servers = new ConnectionEndpointList();
private final ConnectionEndpointList locators = new ConnectionEndpointList();
private final ConnectionEndpointList servers = new ConnectionEndpointList();
private Integer durableClientTimeout;
private Integer freeConnectionTimeout;
@@ -129,7 +135,7 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
/**
* Applies the composite {@link ClientCacheConfigurer ClientCacheConfigurers}
* to this {@link ClientCacheFactoryBean}.
* to this {@link ClientCacheFactoryBean} before the {@link ClientCache} is created.
*
* @see #getCompositeClientCacheConfigurer()
* @see #applyClientCacheConfigurers(ClientCacheConfigurer...)
@@ -140,21 +146,21 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
}
/**
* Null-safe operation to apply the given array of {@link ClientCacheConfigurer ClientCacheConfigurers}
* to this {@link ClientCacheFactoryBean}.
* Applies the array of {@link ClientCacheConfigurer ClientCacheConfigurers} to this {@link ClientCacheFactoryBean}
* before the {@link ClientCache} is created.
*
* @param clientCacheConfigurers array of {@link ClientCacheConfigurer ClientCacheConfigurers} applied to
* this {@link ClientCacheFactoryBean}.
* @param clientCacheConfigurers array of {@link ClientCacheConfigurer ClientCacheConfigurers}
* applied to this {@link ClientCacheFactoryBean}.
* @see org.springframework.data.gemfire.config.annotation.ClientCacheConfigurer
* @see #applyClientCacheConfigurers(Iterable)
*/
protected void applyClientCacheConfigurers(ClientCacheConfigurer... clientCacheConfigurers) {
applyClientCacheConfigurers(Arrays.asList(nullSafeArray(clientCacheConfigurers, ClientCacheConfigurer.class)));
applyClientCacheConfigurers(Arrays.asList(ArrayUtils.nullSafeArray(clientCacheConfigurers, ClientCacheConfigurer.class)));
}
/**
* Null-safe operation to apply the given {@link Iterable} of {@link ClientCacheConfigurer ClientCacheConfigurers}
* to this {@link ClientCacheFactoryBean}.
* Apples the {@link Iterable} of {@link ClientCacheConfigurer ClientCacheConfigurers}
* to this {@link ClientCacheFactoryBean} before the {@link ClientCache} is created.
*
* @param clientCacheConfigurers {@link Iterable} of {@link ClientCacheConfigurer ClientCacheConfigurers}
* applied to this {@link ClientCacheFactoryBean}.
@@ -162,7 +168,7 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
* @see java.lang.Iterable
*/
protected void applyClientCacheConfigurers(Iterable<ClientCacheConfigurer> clientCacheConfigurers) {
stream(nullSafeIterable(clientCacheConfigurers).spliterator(), false)
StreamSupport.stream(CollectionUtils.nullSafeIterable(clientCacheConfigurers).spliterator(), false)
.forEach(clientCacheConfigurer -> clientCacheConfigurer.configure(getBeanName(), this));
}
@@ -178,23 +184,39 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
*/
@Override
@SuppressWarnings("unchecked")
protected <T extends GemFireCache> T fetchCache() {
return (T) Optional.ofNullable(getCache()).orElseGet(ClientCacheFactory::getAnyInstance);
protected <T extends GemFireCache> T doFetchCache() {
return (T) ClientCacheFactory.getAnyInstance();
}
/**
* Resolves the Pivotal GemFire/Apache Geode {@link Properties} used to configure the {@link ClientCache}.
* Returns the {@link Class type} of {@link GemFireCache} constructed by this {@link ClientCacheFactoryBean}.
*
* @return the resolved Pivotal GemFire/Apache Geode {@link Properties} used to configure the {@link ClientCache}.
* @see org.apache.geode.distributed.DistributedSystem#getProperties()
* @see #getDistributedSystem()
* Returns {@link ClientCache} {@link Class}.
*
* @return the {@link Class type} of {@link GemFireCache} constructed by this {@link ClientCacheFactoryBean}.
* @see org.springframework.beans.factory.FactoryBean#getObjectType()
*/
@Override
protected Properties resolveProperties() {
public Class<? extends GemFireCache> doGetObjectType() {
return ClientCache.class;
}
/**
* Resolves the Apache Geode {@link Properties} used to configure the {@link ClientCache}.
*
* @return the resolved Apache Geode {@link Properties} used to configure the {@link ClientCache}.
* @see org.apache.geode.distributed.DistributedSystem#getProperties()
*/
@Override
protected @NonNull Properties resolveProperties() {
return resolveProperties(GemfireUtils::getDistributedSystem);
}
@NonNull Properties resolveProperties(@NonNull Supplier<DistributedSystem> distributeSystemSupplier) {
Properties gemfireProperties = super.resolveProperties();
DistributedSystem distributedSystem = getDistributedSystem();
DistributedSystem distributedSystem = distributeSystemSupplier.get();
if (GemfireUtils.isConnected(distributedSystem)) {
Properties distributedSystemProperties = (Properties) distributedSystem.getProperties().clone();
@@ -208,80 +230,60 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
}
/**
* Returns the {@link DistributedSystem} formed from cache initialization.
*
* @param <T> {@link Class} type of the {@link DistributedSystem}.
* @return an instance of the {@link DistributedSystem}.
* @see org.apache.geode.distributed.DistributedSystem
*/
<T extends DistributedSystem> T getDistributedSystem() {
return GemfireUtils.getDistributedSystem();
}
/**
* Constructs a new instance of {@link ClientCacheFactory} initialized with the given Pivotal GemFire/Apache Geode
* {@link Properties} used to construct, configure and initialize an instance of a {@link ClientCache}.
* Constructs a new instance of {@link ClientCacheFactory} initialized with the given Apache Geode {@link Properties}
* used to construct, configure and initialize a new {@link ClientCache} instance.
*
* @param gemfireProperties {@link Properties} used by the {@link ClientCacheFactory}
* to configure the {@link ClientCache}.
* @return a new instance of {@link ClientCacheFactory} initialized with
* the given Pivotal GemFire/Apache Geode {@link Properties}.
* @return a new instance of {@link ClientCacheFactory} initialized with the given Apache Geode {@link Properties}.
* @see org.apache.geode.cache.client.ClientCacheFactory
* @see java.util.Properties
*/
@Override
protected Object createFactory(Properties gemfireProperties) {
protected @NonNull Object createFactory(@NonNull Properties gemfireProperties) {
return new ClientCacheFactory(gemfireProperties);
}
/**
* Configures the {@link ClientCacheFactory} used to create the {@link ClientCache}.
*
* Sets PDX options specified by the user.
*
* Sets Pool options specified by the user.
*
* @param factory {@link ClientCacheFactory} used to create the {@link ClientCache}.
* @return the configured {@link ClientCacheFactory}.
* @see #configurePdx(ClientCacheFactory)
* @see org.apache.geode.cache.client.ClientCacheFactory
* @see #configurePool(ClientCacheFactory)
* @see #configurePdx(PdxConfigurer)
*/
@Override
protected Object configureFactory(Object factory) {
protected @NonNull Object configureFactory(@NonNull Object factory) {
return configurePool(configurePdx((ClientCacheFactory) factory));
}
/**
* Configure PDX for the {@link ClientCacheFactory}.
* Configures the {@link ClientCache} to use PDX serialization.
*
* @param clientCacheFactory {@link ClientCacheFactory} used to configure PDX.
* @return the given {@link ClientCacheFactory}
* @param clientCacheFactory {@link ClientCacheFactory} to configure with PDX.
* @return the given {@link ClientCacheFactory}.
* @see org.springframework.data.gemfire.client.ClientCacheFactoryBean.ClientCacheFactoryToPdxConfigurerAdapter
* @see org.apache.geode.cache.client.ClientCacheFactory
* @see #configurePdx(PdxConfigurer)
*/
ClientCacheFactory configurePdx(ClientCacheFactory clientCacheFactory) {
protected @NonNull ClientCacheFactory configurePdx(@NonNull ClientCacheFactory clientCacheFactory) {
Optional.ofNullable(getPdxSerializer()).ifPresent(clientCacheFactory::setPdxSerializer);
PdxConfigurer<ClientCacheFactory> pdxConfigurer =
ClientCacheFactoryToPdxConfigurerAdapter.from(clientCacheFactory);
Optional.ofNullable(getPdxDiskStoreName()).filter(StringUtils::hasText)
.ifPresent(clientCacheFactory::setPdxDiskStore);
Optional.ofNullable(getPdxIgnoreUnreadFields()).ifPresent(clientCacheFactory::setPdxIgnoreUnreadFields);
Optional.ofNullable(getPdxPersistent()).ifPresent(clientCacheFactory::setPdxPersistent);
Optional.ofNullable(getPdxReadSerialized()).ifPresent(clientCacheFactory::setPdxReadSerialized);
return clientCacheFactory;
return configurePdx(pdxConfigurer);
}
/**
* Configure the {@literal DEFAULT} {@link Pool} configuration settings with the {@link ClientCacheFactory}
* using a given {@link Pool} instance or a named {@link Pool}.
* Configure the {@literal DEFAULT} {@link Pool} of the {@link ClientCacheFactory} using a given {@link Pool}
* instance or a named {@link Pool} instance.
*
* @param clientCacheFactory {@link ClientCacheFactory} use to configure the {@literal DEFAULT} {@link Pool}.
* @param clientCacheFactory {@link ClientCacheFactory} used to configure the {@literal DEFAULT} {@link Pool}.
* @see org.apache.geode.cache.client.ClientCacheFactory
* @see org.apache.geode.cache.client.Pool
*/
ClientCacheFactory configurePool(ClientCacheFactory clientCacheFactory) {
protected @NonNull ClientCacheFactory configurePool(@NonNull ClientCacheFactory clientCacheFactory) {
DefaultableDelegatingPoolAdapter pool =
DefaultableDelegatingPoolAdapter.from(DelegatingPoolAdapter.from(resolvePool())).preferDefault();
@@ -346,7 +348,7 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
* @see #findPool(String)
* @see #isPoolNameResolvable(String)
*/
Pool resolvePool() {
protected Pool resolvePool() {
Pool pool = getPool();
@@ -370,17 +372,6 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
return pool;
}
String resolvePoolName() {
return Optional.ofNullable(getPoolName())
.filter(StringUtils::hasText)
.orElse(GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME);
}
Pool findPool(String name) {
return getPoolResolver().resolve(name);
}
private boolean isPoolNameResolvable(String poolName) {
return Optional.ofNullable(poolName)
@@ -388,13 +379,29 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
.isPresent();
}
String resolvePoolName() {
return Optional.ofNullable(getPoolName())
.filter(StringUtils::hasText)
.orElseGet(this::getDefaultPoolName);
}
String getDefaultPoolName() {
return GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME;
}
Pool findPool(String name) {
return getPoolResolver().resolve(name);
}
/**
* Creates a new {@link ClientCache} instance using the provided factory.
* Creates a new {@link ClientCache} instance using the provided {@link ClientCacheFactory factory}.
*
* @param <T> parameterized {@link Class} type extension of {@link GemFireCache}.
* @param <T> parameterized {@link Class} type extending {@link GemFireCache}.
* @param factory instance of {@link ClientCacheFactory}.
* @return a new instance of {@link ClientCache} created by the provided factory.
* @see org.apache.geode.cache.client.ClientCacheFactory#create()
* @see org.apache.geode.cache.client.ClientCache
* @see org.apache.geode.cache.GemFireCache
*/
@Override
@@ -420,7 +427,7 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
this.<ClientCache>fetchCache().readyForEvents();
}
catch (IllegalStateException | CacheClosedException ignore) {
// Thrown when ClientCache.readyForEvents() is called on a non-durable client
// Exceptions are thrown when ClientCache.readyForEvents() is called on a non-durable client
// or the ClientCache is closing.
}
}
@@ -438,34 +445,6 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
((ClientCache) cache).close(isKeepAlive());
}
/**
* @inheritDoc
*/
@Override
protected void setCache(GemFireCache cache) {
super.setCache(cache);
}
/**
* @inheritDoc
*/
@Override
protected <T extends GemFireCache> T getCache() {
return super.getCache();
}
/**
* Returns the {@link Class} type of the {@link GemFireCache} produced by this {@link ClientCacheFactoryBean}.
*
* @return the {@link Class} type of the {@link GemFireCache} produced by this {@link ClientCacheFactoryBean}.
* @see org.springframework.beans.factory.FactoryBean#getObjectType()
*/
@Override
@SuppressWarnings({ "rawtypes", "unchecked" })
public Class<? extends GemFireCache> getObjectType() {
return Optional.ofNullable(getCache()).map(Object::getClass).orElse((Class) ClientCache.class);
}
public void addLocators(ConnectionEndpoint... locators) {
this.locators.add(locators);
}
@@ -492,7 +471,7 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
* @see #setClientCacheConfigurers(List)
*/
public void setClientCacheConfigurers(ClientCacheConfigurer... clientCacheConfigurers) {
setClientCacheConfigurers(Arrays.asList(nullSafeArray(clientCacheConfigurers, ClientCacheConfigurer.class)));
setClientCacheConfigurers(Arrays.asList(ArrayUtils.nullSafeArray(clientCacheConfigurers, ClientCacheConfigurer.class)));
}
/**
@@ -504,7 +483,7 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
* @see org.springframework.data.gemfire.config.annotation.ClientCacheConfigurer
*/
public void setClientCacheConfigurers(List<ClientCacheConfigurer> peerCacheConfigurers) {
this.clientCacheConfigurers = Optional.ofNullable(peerCacheConfigurers).orElseGet(Collections::emptyList);
this.clientCacheConfigurers = peerCacheConfigurers != null ? peerCacheConfigurers : Collections.emptyList();
}
/**
@@ -766,9 +745,9 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
}
/**
* Gets the user-specified value for the readyForEvents property.
* Gets the user-configured value for deciding that this client is ready to receive events from the server(s).
*
* @return a boolean value indicating the state of the 'readyForEvents' property.
* @return a {@link Boolean} indicating whether this client is ready to receive events from the server(s).
*/
public Boolean getReadyForEvents(){
return this.readyForEvents;
@@ -786,17 +765,8 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
Boolean readyForEvents = getReadyForEvents();
if (readyForEvents != null) {
return Boolean.TRUE.equals(readyForEvents);
}
else {
try {
return GemfireUtils.isDurable(fetchCache());
}
catch (Throwable ignore) {
return false;
}
}
return readyForEvents != null ? Boolean.TRUE.equals(readyForEvents)
: SpringUtils.safeGetValue(() -> GemfireUtils.isDurable(fetchCache()), false);
}
public void setRetryAttempts(Integer retryAttempts) {
@@ -910,11 +880,60 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
@Override
public final void setUseClusterConfiguration(Boolean useClusterConfiguration) {
throw new UnsupportedOperationException("Cluster-based Configuration is not applicable for clients");
throw new UnsupportedOperationException("Cluster-based Configuration does not apply to clients");
}
@Override
public final Boolean getUseClusterConfiguration() {
return Boolean.FALSE;
}
public static class ClientCacheFactoryToPdxConfigurerAdapter implements PdxConfigurer<ClientCacheFactory> {
public static ClientCacheFactoryToPdxConfigurerAdapter from(@NonNull ClientCacheFactory clientCacheFactory) {
return new ClientCacheFactoryToPdxConfigurerAdapter(clientCacheFactory);
}
private final ClientCacheFactory cacheFactory;
protected ClientCacheFactoryToPdxConfigurerAdapter(@NonNull ClientCacheFactory cacheFactory) {
Assert.notNull(cacheFactory, "ClientCacheFactory must not be null");
this.cacheFactory = cacheFactory;
}
@Override
public @NonNull ClientCacheFactory getTarget() {
return this.cacheFactory;
}
@Override
public @NonNull PdxConfigurer<ClientCacheFactory> setDiskStoreName(String diskStoreName) {
getTarget().setPdxDiskStore(diskStoreName);
return this;
}
@Override
public @NonNull PdxConfigurer<ClientCacheFactory> setIgnoreUnreadFields(Boolean ignoreUnreadFields) {
getTarget().setPdxIgnoreUnreadFields(ignoreUnreadFields);
return this;
}
@Override
public @NonNull PdxConfigurer<ClientCacheFactory> setPersistent(Boolean persistent) {
getTarget().setPdxPersistent(persistent);
return this;
}
@Override
public @NonNull PdxConfigurer<ClientCacheFactory> setReadSerialized(Boolean readSerialized) {
getTarget().setPdxReadSerialized(readSerialized);
return this;
}
@Override
public @NonNull PdxConfigurer<ClientCacheFactory> setSerializer(PdxSerializer pdxSerializer) {
getTarget().setPdxSerializer(pdxSerializer);
return this;
}
}
}

View File

@@ -13,42 +13,39 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.gemfire;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.hamcrest.Matchers.sameInstance;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.data.Offset.offset;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.ArgumentMatchers.same;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.withSettings;
import java.io.InputStream;
import java.util.Collections;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicBoolean;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.apache.geode.cache.Cache;
import org.apache.geode.cache.CacheClosedException;
@@ -63,44 +60,35 @@ import org.apache.geode.distributed.DistributedMember;
import org.apache.geode.distributed.DistributedSystem;
import org.apache.geode.pdx.PdxSerializer;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.core.io.Resource;
import org.springframework.data.gemfire.config.annotation.PeerCacheConfigurer;
import org.springframework.data.gemfire.support.GemfireBeanFactoryLocator;
/**
* Unit tests for {@link CacheFactoryBean}.
* Unit Tests for {@link CacheFactoryBean}.
*
* @author John Blum
* @author Patrick Johnson
* @see java.io.InputStream
* @see java.util.Properties
* @see org.junit.Test
* @see org.junit.runner.RunWith
* @see org.mockito.Mock
* @see org.mockito.Mockito
* @see org.mockito.junit.MockitoJUnitRunner
* @see org.apache.geode.cache.Cache
* @see org.apache.geode.cache.CacheFactory
* @see org.apache.geode.cache.CacheTransactionManager
* @see org.apache.geode.cache.GemFireCache
* @see org.apache.geode.cache.control.ResourceManager
* @see org.apache.geode.cache.util.GatewayConflictResolver
* @see org.apache.geode.distributed.DistributedMember
* @see org.apache.geode.distributed.DistributedSystem
* @see org.apache.geode.pdx.PdxSerializer
* @see org.springframework.beans.factory.BeanFactory
* @see org.springframework.core.io.Resource
* @see org.springframework.data.gemfire.CacheFactoryBean
* @see org.springframework.data.gemfire.support.GemfireBeanFactoryLocator
* @since 1.7.0
*/
@RunWith(MockitoJUnitRunner.class)
public class CacheFactoryBeanTest {
public class CacheFactoryBeanUnitTests {
@Mock
private Cache mockCache;
@@ -114,7 +102,10 @@ public class CacheFactoryBeanTest {
InOrder orderVerifier = inOrder(cacheFactoryBean);
orderVerifier.verify(cacheFactoryBean, times(1)).afterPropertiesSet();
orderVerifier.verify(cacheFactoryBean, times(1)).applyCacheConfigurers();
orderVerifier.verify(cacheFactoryBean, times(1)).getCompositePeerCacheConfigurer();
orderVerifier.verify(cacheFactoryBean, times(1)).applyPeerCacheConfigurers(isA(PeerCacheConfigurer.class));
orderVerifier.verify(cacheFactoryBean, times(1)).initBeanFactoryLocator();
}
@@ -127,11 +118,12 @@ public class CacheFactoryBeanTest {
Properties gemfireProperties = cacheFactoryBean.getProperties();
assertThat(gemfireProperties.size(), is(equalTo(2)));
assertThat(gemfireProperties.containsKey("disable-auto-reconnect"), is(true));
assertThat(gemfireProperties.containsKey("use-cluster-configuration"), is(true));
assertThat(gemfireProperties.getProperty("disable-auto-reconnect"), is(equalTo("true")));
assertThat(gemfireProperties.getProperty("use-cluster-configuration"), is(equalTo("false")));
assertThat(gemfireProperties).isNotNull();
assertThat(gemfireProperties).hasSize(2);
assertThat(gemfireProperties.containsKey("disable-auto-reconnect")).isTrue();
assertThat(gemfireProperties.containsKey("use-cluster-configuration")).isTrue();
assertThat(gemfireProperties.getProperty("disable-auto-reconnect")).isEqualTo("true");
assertThat(gemfireProperties.getProperty("use-cluster-configuration")).isEqualTo("false");
}
@Test
@@ -145,11 +137,12 @@ public class CacheFactoryBeanTest {
Properties gemfireProperties = cacheFactoryBean.getProperties();
assertThat(gemfireProperties.size(), is(equalTo(2)));
assertThat(gemfireProperties.containsKey("disable-auto-reconnect"), is(true));
assertThat(gemfireProperties.containsKey("use-cluster-configuration"), is(true));
assertThat(gemfireProperties.getProperty("disable-auto-reconnect"), is(equalTo("true")));
assertThat(gemfireProperties.getProperty("use-cluster-configuration"), is(equalTo("false")));
assertThat(gemfireProperties).isNotNull();
assertThat(gemfireProperties).hasSize(2);
assertThat(gemfireProperties.containsKey("disable-auto-reconnect")).isTrue();
assertThat(gemfireProperties.containsKey("use-cluster-configuration")).isTrue();
assertThat(gemfireProperties.getProperty("disable-auto-reconnect")).isEqualTo("true");
assertThat(gemfireProperties.getProperty("use-cluster-configuration")).isEqualTo("false");
}
@Test
@@ -163,11 +156,12 @@ public class CacheFactoryBeanTest {
Properties gemfireProperties = cacheFactoryBean.getProperties();
assertThat(gemfireProperties.size(), is(equalTo(2)));
assertThat(gemfireProperties.containsKey("disable-auto-reconnect"), is(true));
assertThat(gemfireProperties.containsKey("use-cluster-configuration"), is(true));
assertThat(gemfireProperties.getProperty("disable-auto-reconnect"), is(equalTo("false")));
assertThat(gemfireProperties.getProperty("use-cluster-configuration"), is(equalTo("true")));
assertThat(gemfireProperties).isNotNull();
assertThat(gemfireProperties).hasSize(2);
assertThat(gemfireProperties.containsKey("disable-auto-reconnect")).isTrue();
assertThat(gemfireProperties.containsKey("use-cluster-configuration")).isTrue();
assertThat(gemfireProperties.getProperty("disable-auto-reconnect")).isEqualTo("false");
assertThat(gemfireProperties.getProperty("use-cluster-configuration")).isEqualTo("true");
}
@Test
@@ -181,11 +175,12 @@ public class CacheFactoryBeanTest {
Properties gemfireProperties = cacheFactoryBean.getProperties();
assertThat(gemfireProperties.size(), is(equalTo(2)));
assertThat(gemfireProperties.containsKey("disable-auto-reconnect"), is(true));
assertThat(gemfireProperties.containsKey("use-cluster-configuration"), is(true));
assertThat(gemfireProperties.getProperty("disable-auto-reconnect"), is(equalTo("true")));
assertThat(gemfireProperties.getProperty("use-cluster-configuration"), is(equalTo("true")));
assertThat(gemfireProperties).isNotNull();
assertThat(gemfireProperties).hasSize(2);
assertThat(gemfireProperties.containsKey("disable-auto-reconnect")).isTrue();
assertThat(gemfireProperties.containsKey("use-cluster-configuration")).isTrue();
assertThat(gemfireProperties.getProperty("disable-auto-reconnect")).isEqualTo("true");
assertThat(gemfireProperties.getProperty("use-cluster-configuration")).isEqualTo("true");
}
@Test
@@ -199,44 +194,52 @@ public class CacheFactoryBeanTest {
Properties gemfireProperties = cacheFactoryBean.getProperties();
assertThat(gemfireProperties.size(), is(equalTo(2)));
assertThat(gemfireProperties.containsKey("disable-auto-reconnect"), is(true));
assertThat(gemfireProperties.containsKey("use-cluster-configuration"), is(true));
assertThat(gemfireProperties.getProperty("disable-auto-reconnect"), is(equalTo("false")));
assertThat(gemfireProperties.getProperty("use-cluster-configuration"), is(equalTo("false")));
assertThat(gemfireProperties).isNotNull();
assertThat(gemfireProperties).hasSize(2);
assertThat(gemfireProperties.containsKey("disable-auto-reconnect")).isTrue();
assertThat(gemfireProperties.containsKey("use-cluster-configuration")).isTrue();
assertThat(gemfireProperties.getProperty("disable-auto-reconnect")).isEqualTo("false");
assertThat(gemfireProperties.getProperty("use-cluster-configuration")).isEqualTo("false");
}
@Test
public void getObjectCallsInit() throws Exception {
AtomicBoolean initCalled = new AtomicBoolean(false);
Cache mockCache = mock(Cache.class);
CacheFactoryBean cacheFactoryBean = new CacheFactoryBean() {
@Override Cache init() {
initCalled.set(true);
return mockCache;
}
};
CacheFactoryBean cacheFactoryBean = spy(new CacheFactoryBean());
assertThat(cacheFactoryBean.getObject(), is(sameInstance(mockCache)));
assertThat(initCalled.get(), is(true));
doReturn(mockCache).when(cacheFactoryBean).init();
verifyZeroInteractions(mockCache);
assertThat(cacheFactoryBean.getObject()).isSameAs(mockCache);
verify(cacheFactoryBean, times(1)).getObject();
verify(cacheFactoryBean, times(1)).getCache();
verify(cacheFactoryBean, times(1)).doGetObject();
verify(cacheFactoryBean, times(1)).init();
verifyNoMoreInteractions(cacheFactoryBean);
verifyNoInteractions(mockCache);
}
@Test
public void getObjectReturnsExistingCache() throws Exception {
Cache mockCache = mock(Cache.class);
CacheFactoryBean cacheFactoryBean = new CacheFactoryBean();
CacheFactoryBean cacheFactoryBean = spy(new CacheFactoryBean());
cacheFactoryBean.setCache(mockCache);
assertThat(cacheFactoryBean.getObject(), is(sameInstance(mockCache)));
assertThat(cacheFactoryBean.<Cache>getCache()).isSameAs(mockCache);
assertThat(cacheFactoryBean.getObject()).isSameAs(mockCache);
verifyZeroInteractions(mockCache);
verify(cacheFactoryBean, times(1)).getObject();
verify(cacheFactoryBean, never()).doGetObject();
verify(cacheFactoryBean, never()).init();
verifyNoInteractions(mockCache);
}
@Test
@@ -285,17 +288,18 @@ public class CacheFactoryBeanTest {
Properties gemfireProperties = new Properties();
CacheFactoryBean cacheFactoryBean = new CacheFactoryBean() {
CacheFactoryBean cacheFactoryBean = spy(new CacheFactoryBean());
@Override
protected Object createFactory(Properties actualGemfireProperties) {
doAnswer(invocation -> {
assertThat(actualGemfireProperties, is(equalTo(gemfireProperties)));
assertThat(getBeanClassLoader(), is(equalTo(ClassLoader.getSystemClassLoader())));
Properties gemfirePropertiesArgument = invocation.getArgument(0);
return mockCacheFactory;
}
};
assertThat(gemfirePropertiesArgument).isEqualTo(gemfireProperties);
assertThat(cacheFactoryBean.getBeanClassLoader()).isEqualTo(ClassLoader.getSystemClassLoader());
return mockCacheFactory;
}).when(cacheFactoryBean).createFactory(isA(Properties.class));
cacheFactoryBean.setBeanClassLoader(ClassLoader.getSystemClassLoader());
cacheFactoryBean.setBeanFactory(mockBeanFactory);
@@ -326,15 +330,15 @@ public class CacheFactoryBeanTest {
cacheFactoryBean.afterPropertiesSet();
cacheFactoryBean.init();
assertThat(Thread.currentThread().getContextClassLoader(), is(sameInstance(expectedThreadContextClassLoader)));
assertThat(Thread.currentThread().getContextClassLoader()).isSameAs(expectedThreadContextClassLoader);
GemfireBeanFactoryLocator beanFactoryLocator = cacheFactoryBean.getBeanFactoryLocator();
assertThat(beanFactoryLocator, is(notNullValue()));
assertThat(beanFactoryLocator).isNotNull();
BeanFactory beanFactoryReference = beanFactoryLocator.useBeanFactory("TestGemFireCache");
assertThat(beanFactoryReference, is(sameInstance(mockBeanFactory)));
assertThat(beanFactoryReference).isSameAs(mockBeanFactory);
verify(mockBeanFactory, times(1)).getAliases(anyString());
verify(mockCacheFactory, times(1)).setPdxDiskStore(eq("TestPdxDiskStore"));
@@ -365,58 +369,59 @@ public class CacheFactoryBeanTest {
Cache mockCache = mock(Cache.class);
CacheFactoryBean cacheFactoryBean = new CacheFactoryBean() {
CacheFactoryBean cacheFactoryBean = spy(new CacheFactoryBean());
@Override @SuppressWarnings("unchecked ")
protected <T extends GemFireCache> T fetchCache() {
return (T) mockCache;
}
};
doReturn(mockCache).when(cacheFactoryBean).fetchCache();
assertThat(cacheFactoryBean.resolveCache(), is(sameInstance(mockCache)));
assertThat(cacheFactoryBean.<GemFireCache>resolveCache()).isSameAs(mockCache);
verifyZeroInteractions(mockCache);
verifyNoInteractions(mockCache);
}
@Test
public void resolveCacheCreatesCacheWhenFetchCacheThrowsCacheClosedException() {
Cache mockCache = mock(Cache.class);
CacheFactory mockCacheFactory = mock(CacheFactory.class);
when(mockCacheFactory.create()).thenReturn(mockCache);
doReturn(mockCache).when(mockCacheFactory).create();
CacheFactoryBean cacheFactoryBean = new CacheFactoryBean() {
@Override protected <T extends GemFireCache> T fetchCache() {
throw new CacheClosedException("test");
}
CacheFactoryBean cacheFactoryBean = spy(new CacheFactoryBean());
@Override
protected Object createFactory(final Properties gemfireProperties) {
assertThat(gemfireProperties, is(sameInstance(getProperties())));
return mockCacheFactory;
}
};
doThrow(new CacheClosedException("TEST")).when(cacheFactoryBean).fetchCache();
assertThat(cacheFactoryBean.resolveCache(), is(equalTo(mockCache)));
doAnswer(invocation -> {
Properties gemfireProperties = invocation.getArgument(0);
assertThat(gemfireProperties).isSameAs(cacheFactoryBean.getProperties());
return mockCacheFactory;
}).when(cacheFactoryBean).createFactory(isA(Properties.class));
assertThat(cacheFactoryBean.<GemFireCache>resolveCache()).isEqualTo(mockCache);
verify(mockCacheFactory, times(1)).create();
verifyZeroInteractions(mockCache);
verifyNoInteractions(mockCache);
}
@Test
public void fetchExistingCache() {
Cache mockCache = mock(Cache.class);
CacheFactoryBean cacheFactoryBean = new CacheFactoryBean();
cacheFactoryBean.setCache(mockCache);
Cache actualCache = cacheFactoryBean.fetchCache();
assertThat(actualCache, is(sameInstance(mockCache)));
assertThat(actualCache).isSameAs(mockCache);
verifyZeroInteractions(mockCache);
verifyNoInteractions(mockCache);
}
@Test
@@ -428,7 +433,7 @@ public class CacheFactoryBeanTest {
cacheFactoryBean.setProperties(gemfireProperties);
assertThat(cacheFactoryBean.resolveProperties(), is(sameInstance(gemfireProperties)));
assertThat(cacheFactoryBean.resolveProperties()).isSameAs(gemfireProperties);
}
@Test
@@ -440,8 +445,8 @@ public class CacheFactoryBeanTest {
Properties gemfireProperties = cacheFactoryBean.resolveProperties();
assertThat(gemfireProperties, is(notNullValue()));
assertThat(gemfireProperties.isEmpty(), is(true));
assertThat(gemfireProperties).isNotNull();
assertThat(gemfireProperties.isEmpty()).isTrue();
}
@Test
@@ -451,20 +456,20 @@ public class CacheFactoryBeanTest {
Object cacheFactoryReference = new CacheFactoryBean().createFactory(gemfireProperties);
assertThat(cacheFactoryReference, is(instanceOf(CacheFactory.class)));
assertThat(gemfireProperties.isEmpty(), is(true));
assertThat(cacheFactoryReference).isInstanceOf(CacheFactory.class);
assertThat(gemfireProperties.isEmpty()).isTrue();
CacheFactory cacheFactory = (CacheFactory) cacheFactoryReference;
cacheFactory.set("name", "TestCreateCacheFactory");
assertThat(gemfireProperties.containsKey("name"), is(true));
assertThat(gemfireProperties.getProperty("name"), is(equalTo("TestCreateCacheFactory")));
assertThat(gemfireProperties.containsKey("name")).isTrue();
assertThat(gemfireProperties.getProperty("name")).isEqualTo("TestCreateCacheFactory");
}
@Test
@SuppressWarnings("unchecked")
public void initializesFactoryWitCacheFactoryInitializer() {
public void initializesFactoryWithCacheFactoryInitializer() {
CacheFactory mockCacheFactory = mock(CacheFactory.class);
@@ -475,25 +480,24 @@ public class CacheFactoryBeanTest {
cacheFactoryBean.setCacheFactoryInitializer(mockCacheFactoryInitializer);
assertThat(cacheFactoryBean.getCacheFactoryInitializer(), is(equalTo(mockCacheFactoryInitializer)));
assertThat(cacheFactoryBean.initializeFactory(mockCacheFactory), is(sameInstance(mockCacheFactory)));
assertThat(cacheFactoryBean.getCacheFactoryInitializer()).isEqualTo(mockCacheFactoryInitializer);
assertThat(cacheFactoryBean.initializeFactory(mockCacheFactory)).isSameAs(mockCacheFactory);
verify(mockCacheFactoryInitializer, times(1)).initialize(eq(mockCacheFactory));
verifyZeroInteractions(mockCacheFactory);
verifyNoInteractions(mockCacheFactory);
}
@Test
public void initializeFactoryWhenNoCacheFactoryInitializerIsPresentIsNullSafe() {
public void initializesFactoryWhenNoCacheFactoryInitializerIsPresentIsNullSafe() {
CacheFactory mockCacheFactory = mock(CacheFactory.class);
CacheFactoryBean cacheFactoryBean = new CacheFactoryBean();
assertThat(cacheFactoryBean.getCacheFactoryInitializer(),
is(nullValue(CacheFactoryBean.CacheFactoryInitializer.class)));
assertThat(cacheFactoryBean.initializeFactory(mockCacheFactory), is(sameInstance(mockCacheFactory)));
assertThat(cacheFactoryBean.getCacheFactoryInitializer()).isNull();
assertThat(cacheFactoryBean.initializeFactory(mockCacheFactory)).isSameAs(mockCacheFactory);
verifyZeroInteractions(mockCacheFactory);
verifyNoInteractions(mockCacheFactory);
}
@Test
@@ -501,38 +505,46 @@ public class CacheFactoryBeanTest {
CacheFactory mockCacheFactory = mock(CacheFactory.class);
assertThat(new CacheFactoryBean().configureFactory(mockCacheFactory), is(sameInstance(mockCacheFactory)));
CacheFactoryBean cacheFactoryBean = new CacheFactoryBean();
assertThat(cacheFactoryBean.configureFactory(mockCacheFactory)).isSameAs(mockCacheFactory);
verify(mockCacheFactory, never()).setPdxDiskStore(any(String.class));
verify(mockCacheFactory, never()).setPdxIgnoreUnreadFields(any(Boolean.class));
verify(mockCacheFactory, never()).setPdxPersistent(any(Boolean.class));
verify(mockCacheFactory, never()).setPdxReadSerialized(any(Boolean.class));
verify(mockCacheFactory, never()).setPdxSerializer(any(PdxSerializer.class));
verifyNoInteractions(mockCacheFactory);
}
@Test
public void configureFactoryWithSpecificPdxOptions() {
CacheFactory mockCacheFactory = mock(CacheFactory.class);
CacheFactoryBean cacheFactoryBean = new CacheFactoryBean();
cacheFactoryBean.setPdxSerializer(mock(PdxSerializer.class));
cacheFactoryBean.setPdxReadSerialized(true);
cacheFactoryBean.setPdxIgnoreUnreadFields(false);
CacheFactory mockCacheFactory = mock(CacheFactory.class);
assertThat(cacheFactoryBean.configureFactory(mockCacheFactory), is(sameInstance(mockCacheFactory)));
assertThat(cacheFactoryBean.configureFactory(mockCacheFactory)).isSameAs(mockCacheFactory);
verify(mockCacheFactory, never()).setPdxDiskStore(any(String.class));
verify(mockCacheFactory, times(1)).setPdxIgnoreUnreadFields(eq(false));
verify(mockCacheFactory, never()).setPdxPersistent(any(Boolean.class));
verify(mockCacheFactory, times(1)).setPdxReadSerialized(eq(true));
verify(mockCacheFactory, times(1)).setPdxSerializer(any(PdxSerializer.class));
verifyNoMoreInteractions(mockCacheFactory);
}
@Test
public void configureFactoryWithAllPdxOptions() {
CacheFactory mockCacheFactory = mock(CacheFactory.class);
CacheFactoryBean cacheFactoryBean = new CacheFactoryBean();
cacheFactoryBean.setPdxDiskStoreName("testPdxDiskStoreName");
@@ -541,15 +553,15 @@ public class CacheFactoryBeanTest {
cacheFactoryBean.setPdxReadSerialized(true);
cacheFactoryBean.setPdxSerializer(mock(PdxSerializer.class));
CacheFactory mockCacheFactory = mock(CacheFactory.class);
assertThat(cacheFactoryBean.configureFactory(mockCacheFactory), is(sameInstance(mockCacheFactory)));
assertThat(cacheFactoryBean.configureFactory(mockCacheFactory)).isSameAs(mockCacheFactory);
verify(mockCacheFactory, times(1)).setPdxDiskStore(eq("testPdxDiskStoreName"));
verify(mockCacheFactory, times(1)).setPdxIgnoreUnreadFields(eq(false));
verify(mockCacheFactory, times(1)).setPdxPersistent(eq(true));
verify(mockCacheFactory, times(1)).setPdxReadSerialized(eq(true));
verify(mockCacheFactory, times(1)).setPdxSerializer(any(PdxSerializer.class));
verifyNoMoreInteractions(mockCacheFactory);
}
@Test
@@ -560,15 +572,18 @@ public class CacheFactoryBeanTest {
org.apache.geode.security.SecurityManager mockSecurityManager =
mock(org.apache.geode.security.SecurityManager.class);
doReturn(mockCacheFactory).when(mockCacheFactory).setSecurityManager(eq(mockSecurityManager));
CacheFactoryBean cacheFactoryBean = new CacheFactoryBean();
cacheFactoryBean.setSecurityManager(mockSecurityManager);
assertThat(cacheFactoryBean.getSecurityManager(), is(sameInstance(mockSecurityManager)));
assertThat(cacheFactoryBean.configureFactory(mockCacheFactory), is(sameInstance(mockCacheFactory)));
assertThat(cacheFactoryBean.getSecurityManager()).isSameAs(mockSecurityManager);
assertThat(cacheFactoryBean.configureFactory(mockCacheFactory)).isSameAs(mockCacheFactory);
verify(mockCacheFactory, times(1)).setSecurityManager(eq(mockSecurityManager));
verifyZeroInteractions(mockSecurityManager);
verifyNoMoreInteractions(mockCacheFactory);
verifyNoInteractions(mockSecurityManager);
}
@Test
@@ -576,35 +591,38 @@ public class CacheFactoryBeanTest {
CacheFactory mockCacheFactory = mock(CacheFactory.class);
when(mockCacheFactory.create()).thenReturn(mockCache);
doReturn(this.mockCache).when(mockCacheFactory).create();
CacheFactoryBean cacheFactoryBean = new CacheFactoryBean();
Cache actualCache = cacheFactoryBean.createCache(mockCacheFactory);
assertThat(actualCache, is(equalTo(mockCache)));
assertThat(actualCache).isEqualTo(this.mockCache);
verify(mockCacheFactory, times(1)).create();
verifyZeroInteractions(mockCache);
verifyNoMoreInteractions(mockCacheFactory);
verifyNoInteractions(this.mockCache);
}
@Test(expected = IllegalArgumentException.class)
public void postProcessCacheWithInvalidCriticalHeapPercentage() {
try {
CacheFactoryBean cacheFactoryBean = new CacheFactoryBean();
cacheFactoryBean.setCriticalHeapPercentage(200.0f);
cacheFactoryBean.postProcess(mockCache);
cacheFactoryBean.postProcess(this.mockCache);
}
catch (IllegalArgumentException expected) {
assertEquals("criticalHeapPercentage [200.0] is not valid; must be >= 0.0 and <= 100.0",
expected.getMessage());
assertThat(expected).hasMessage("criticalHeapPercentage [200.0] is not valid; must be >= 0.0 and <= 100.0");
assertThat(expected).hasNoCause();
throw expected;
}
finally {
verifyZeroInteractions(mockCache);
verifyNoInteractions(this.mockCache);
}
}
@@ -612,19 +630,21 @@ public class CacheFactoryBeanTest {
public void postProcessCacheWithInvalidCriticalOffHeapPercentage() {
try {
CacheFactoryBean cacheFactoryBean = new CacheFactoryBean();
cacheFactoryBean.setCriticalOffHeapPercentage(200.0f);
cacheFactoryBean.postProcess(mockCache);
cacheFactoryBean.postProcess(this.mockCache);
}
catch (IllegalArgumentException expected) {
assertEquals("criticalOffHeapPercentage [200.0] is not valid; must be >= 0.0 and <= 100.0",
expected.getMessage());
assertThat(expected).hasMessage("criticalOffHeapPercentage [200.0] is not valid; must be >= 0.0 and <= 100.0");
assertThat(expected).hasNoCause();
throw expected;
}
finally {
verifyZeroInteractions(mockCache);
verifyNoInteractions(this.mockCache);
}
}
@@ -632,19 +652,21 @@ public class CacheFactoryBeanTest {
public void postProcessCacheWithInvalidEvictionHeapPercentage() {
try {
CacheFactoryBean cacheFactoryBean = new CacheFactoryBean();
cacheFactoryBean.setEvictionHeapPercentage(-75.0f);
cacheFactoryBean.postProcess(mockCache);
cacheFactoryBean.postProcess(this.mockCache);
}
catch (IllegalArgumentException expected) {
assertEquals("evictionHeapPercentage [-75.0] is not valid; must be >= 0.0 and <= 100.0",
expected.getMessage());
assertThat(expected).hasMessage("evictionHeapPercentage [-75.0] is not valid; must be >= 0.0 and <= 100.0");
assertThat(expected).hasNoCause();
throw expected;
}
finally {
verifyZeroInteractions(mockCache);
verifyNoInteractions(this.mockCache);
}
}
@@ -652,62 +674,59 @@ public class CacheFactoryBeanTest {
public void postProcessCacheWithInvalidEvictionOffHeapPercentage() {
try {
CacheFactoryBean cacheFactoryBean = new CacheFactoryBean();
cacheFactoryBean.setEvictionOffHeapPercentage(-75.0f);
cacheFactoryBean.postProcess(mockCache);
cacheFactoryBean.postProcess(this.mockCache);
}
catch (IllegalArgumentException expected) {
assertEquals("evictionOffHeapPercentage [-75.0] is not valid; must be >= 0.0 and <= 100.0",
expected.getMessage());
assertThat(expected).hasMessage("evictionOffHeapPercentage [-75.0] is not valid; must be >= 0.0 and <= 100.0");
assertThat(expected).hasNoCause();
throw expected;
}
finally {
verifyZeroInteractions(mockCache);
verifyNoInteractions(this.mockCache);
}
}
@Test
@SuppressWarnings("unchecked")
public void getObjectType() {
assertThat(new CacheFactoryBean().getObjectType(), is(equalTo(Cache.class)));
public void getObjectTypeEqualsCacheClass() {
assertThat(new CacheFactoryBean().getObjectType()).isEqualTo(Cache.class);
}
@Test
public void getObjectTypeWithExistingCache() {
public void getObjectTypeEqualsCacheInstanceType() {
Cache mockCache = mock(Cache.class);
CacheFactoryBean cacheFactoryBean = new CacheFactoryBean();
cacheFactoryBean.setCache(mockCache);
assertThat(cacheFactoryBean.getObjectType(), is(equalTo((Class) mockCache.getClass())));
assertThat(cacheFactoryBean.<GemFireCache>getCache()).isEqualTo(mockCache);
assertThat(cacheFactoryBean.getObjectType()).isEqualTo(mockCache.getClass());
}
@Test
public void isSingleton() {
assertTrue(new CacheFactoryBean().isSingleton());
assertThat(new CacheFactoryBean().isSingleton()).isTrue();
}
@Test
@SuppressWarnings("unchecked")
public void destroy() throws Exception {
AtomicBoolean fetchCacheCalled = new AtomicBoolean(false);
Cache mockCache = mock(Cache.class, "GemFireCache");
GemfireBeanFactoryLocator mockGemfireBeanFactoryLocator = mock(GemfireBeanFactoryLocator.class);
when(mockCache.isClosed()).thenReturn(false);
doReturn(false).when(mockCache).isClosed();
CacheFactoryBean cacheFactoryBean = spy(new CacheFactoryBean());
doAnswer(invocation -> {
fetchCacheCalled.set(true);
return mockCache;
}).when(cacheFactoryBean).fetchCache();
doReturn(mockCache).when(cacheFactoryBean).fetchCache();
GemfireBeanFactoryLocator mockGemfireBeanFactoryLocator = mock(GemfireBeanFactoryLocator.class);
doReturn(mockGemfireBeanFactoryLocator).when(cacheFactoryBean).getBeanFactoryLocator();
@@ -715,52 +734,70 @@ public class CacheFactoryBeanTest {
cacheFactoryBean.setUseBeanFactoryLocator(true);
cacheFactoryBean.destroy();
assertThat(fetchCacheCalled.get(), is(true));
verify(cacheFactoryBean, times(1)).destroy();
verify(cacheFactoryBean, times(1)).isClose();
verify(cacheFactoryBean, times(1)).fetchCache();
verify(cacheFactoryBean, times(1)).close(eq(mockCache));
verify(cacheFactoryBean, times(1)).destroyBeanFactoryLocator();
verify(mockCache, times(1)).isClosed();
verify(mockCache, times(1)).close();
verify(mockGemfireBeanFactoryLocator, times(1)).destroy();
verifyNoMoreInteractions(mockCache, mockGemfireBeanFactoryLocator);
}
@Test
@SuppressWarnings("unchecked")
public void destroyWhenCacheIsNull() throws Exception {
AtomicBoolean fetchCacheCalled = new AtomicBoolean(false);
public void destroyWhenCacheIsNull() {
CacheFactoryBean cacheFactoryBean = spy(new CacheFactoryBean());
doAnswer(invocation -> {
fetchCacheCalled.set(true);
return null;
}).when(cacheFactoryBean).fetchCache();
doReturn(null).when(cacheFactoryBean).fetchCache();
cacheFactoryBean.setClose(true);
cacheFactoryBean.setUseBeanFactoryLocator(true);
cacheFactoryBean.destroy();
assertTrue(fetchCacheCalled.get());
verify(cacheFactoryBean, times(1)).destroy();
verify(cacheFactoryBean, times(1)).isClose();
verify(cacheFactoryBean, times(1)).fetchCache();
verify(cacheFactoryBean, times(1)).close(isNull());
verify(cacheFactoryBean, times(1)).destroyBeanFactoryLocator();
}
@Test
@SuppressWarnings("unchecked")
public void destroyWhenCloseIsFalse() throws Exception {
public void destroyWhenCloseIsFalse() {
CacheFactoryBean cacheFactoryBean = new CacheFactoryBean();
CacheFactoryBean cacheFactoryBean = spy(new CacheFactoryBean());
cacheFactoryBean.setClose(false);
cacheFactoryBean.setUseBeanFactoryLocator(false);
cacheFactoryBean.destroy();
verify(cacheFactoryBean, times(1)).isClose();
verify(cacheFactoryBean, never()).fetchCache();
verify(cacheFactoryBean, never()).close(any());
verify(cacheFactoryBean, never()).destroyBeanFactoryLocator();
}
@Test
public void closeCache() {
GemFireCache mockCache = mock(GemFireCache.class, "testCloseCache.MockCache");
GemFireCache mockCache = mock(GemFireCache.class);
new CacheFactoryBean().close(mockCache);
CacheFactoryBean cacheFactoryBean = new CacheFactoryBean();
cacheFactoryBean.setCache(mockCache);
assertThat(cacheFactoryBean.<GemFireCache>getCache()).isEqualTo(mockCache);
cacheFactoryBean.close(mockCache);
assertThat(cacheFactoryBean.<GemFireCache>getCache()).isNull();
verify(mockCache, times(1)).isClosed();
verify(mockCache, times(1)).close();
verifyNoMoreInteractions(mockCache);
}
@Test
@@ -769,15 +806,19 @@ public class CacheFactoryBeanTest {
BeanFactory mockBeanFactory = mock(BeanFactory.class, "SpringBeanFactory");
GatewayConflictResolver mockGatewayConflictResolver = mock(GatewayConflictResolver.class, "GemFireGatewayConflictResolver");
GatewayConflictResolver mockGatewayConflictResolver =
mock(GatewayConflictResolver.class, "GemFireGatewayConflictResolver");
PdxSerializer mockPdxSerializer = mock(PdxSerializer.class, "GemFirePdxSerializer");
PdxSerializer mockPdxSerializer =
mock(PdxSerializer.class, "GemFirePdxSerializer");
Resource mockCacheXml = mock(Resource.class, "GemFireCacheXml");
TransactionListener mockTransactionListener = mock(TransactionListener.class, "GemFireTransactionListener");
TransactionListener mockTransactionListener =
mock(TransactionListener.class, "GemFireTransactionListener");
TransactionWriter mockTransactionWriter = mock(TransactionWriter.class, "GemFireTransactionWriter");
TransactionWriter mockTransactionWriter =
mock(TransactionWriter.class, "GemFireTransactionWriter");
Properties gemfireProperties = new Properties();
@@ -811,36 +852,36 @@ public class CacheFactoryBeanTest {
cacheFactoryBean.setTransactionWriter(mockTransactionWriter);
cacheFactoryBean.setUseClusterConfiguration(true);
assertEquals(Thread.currentThread().getContextClassLoader(), cacheFactoryBean.getBeanClassLoader());
assertSame(mockBeanFactory, cacheFactoryBean.getBeanFactory());
assertNull(cacheFactoryBean.getBeanFactoryLocator());
assertEquals("TestCache", cacheFactoryBean.getBeanName());
assertSame(mockCacheXml, cacheFactoryBean.getCacheXml());
assertSame(gemfireProperties, cacheFactoryBean.getProperties());
assertTrue(Boolean.FALSE.equals(TestUtils.readField("useBeanFactoryLocator", cacheFactoryBean)));
assertTrue(Boolean.FALSE.equals(TestUtils.readField("close", cacheFactoryBean)));
assertTrue(cacheFactoryBean.getCopyOnRead());
assertEquals(0.95f, cacheFactoryBean.getCriticalHeapPercentage(), 0.0f);
assertEquals(0.99f, cacheFactoryBean.getCriticalOffHeapPercentage(), 0.0f);
assertTrue(cacheFactoryBean.getEnableAutoReconnect());
assertEquals(0.70f, cacheFactoryBean.getEvictionHeapPercentage(), 0.0f);
assertEquals(0.80f, cacheFactoryBean.getEvictionOffHeapPercentage(), 0.0f);
assertSame(mockGatewayConflictResolver, cacheFactoryBean.getGatewayConflictResolver());
assertNotNull(cacheFactoryBean.getJndiDataSources());
assertEquals(1, cacheFactoryBean.getJndiDataSources().size());
assertEquals(15000, cacheFactoryBean.getLockLease().intValue());
assertEquals(5000, cacheFactoryBean.getLockTimeout().intValue());
assertEquals(10000, cacheFactoryBean.getMessageSyncInterval().intValue());
assertSame(mockPdxSerializer, cacheFactoryBean.getPdxSerializer());
assertFalse(cacheFactoryBean.getPdxReadSerialized());
assertTrue(cacheFactoryBean.getPdxPersistent());
assertTrue(cacheFactoryBean.getPdxIgnoreUnreadFields());
assertEquals("TestPdxDiskStore", cacheFactoryBean.getPdxDiskStoreName());
assertEquals(30000, cacheFactoryBean.getSearchTimeout().intValue());
assertNotNull(cacheFactoryBean.getTransactionListeners());
assertEquals(1, cacheFactoryBean.getTransactionListeners().size());
assertSame(mockTransactionListener, cacheFactoryBean.getTransactionListeners().get(0));
assertSame(mockTransactionWriter, cacheFactoryBean.getTransactionWriter());
assertTrue(cacheFactoryBean.getUseClusterConfiguration());
assertThat(cacheFactoryBean.getBeanClassLoader()).isEqualTo(Thread.currentThread().getContextClassLoader());
assertThat(cacheFactoryBean.getBeanFactory()).isSameAs(mockBeanFactory);
assertThat(cacheFactoryBean.getBeanFactoryLocator()).isNull();
assertThat(cacheFactoryBean.getBeanName()).isEqualTo("TestCache");
assertThat(cacheFactoryBean.getCacheXml()).isSameAs(mockCacheXml);
assertThat(cacheFactoryBean.getProperties()).isSameAs(gemfireProperties);
assertThat(Boolean.FALSE.equals(TestUtils.readField("useBeanFactoryLocator", cacheFactoryBean))).isTrue();
assertThat(Boolean.FALSE.equals(TestUtils.readField("close", cacheFactoryBean))).isTrue();
assertThat(cacheFactoryBean.getCopyOnRead()).isTrue();
assertThat(cacheFactoryBean.getCriticalHeapPercentage()).isCloseTo(0.95f, offset(0.0f));
assertThat(cacheFactoryBean.getCriticalOffHeapPercentage()).isCloseTo(0.99f, offset(0.0f));
assertThat(cacheFactoryBean.getEnableAutoReconnect()).isTrue();
assertThat(cacheFactoryBean.getEvictionHeapPercentage()).isCloseTo(0.70f, offset(0.0f));
assertThat(cacheFactoryBean.getEvictionOffHeapPercentage()).isCloseTo(0.80f, offset(0.0f));
assertThat(cacheFactoryBean.getGatewayConflictResolver()).isSameAs(mockGatewayConflictResolver);
assertThat(cacheFactoryBean.getJndiDataSources()).isNotNull();
assertThat(cacheFactoryBean.getJndiDataSources().size()).isEqualTo(1);
assertThat(cacheFactoryBean.getLockLease().intValue()).isEqualTo(15000);
assertThat(cacheFactoryBean.getLockTimeout().intValue()).isEqualTo(5000);
assertThat(cacheFactoryBean.getMessageSyncInterval().intValue()).isEqualTo(10000);
assertThat(cacheFactoryBean.getPdxSerializer()).isSameAs(mockPdxSerializer);
assertThat(cacheFactoryBean.getPdxReadSerialized()).isFalse();
assertThat(cacheFactoryBean.getPdxPersistent()).isTrue();
assertThat(cacheFactoryBean.getPdxIgnoreUnreadFields()).isTrue();
assertThat(cacheFactoryBean.getPdxDiskStoreName()).isEqualTo("TestPdxDiskStore");
assertThat(cacheFactoryBean.getSearchTimeout().intValue()).isEqualTo(30000);
assertThat(cacheFactoryBean.getTransactionListeners()).isNotNull();
assertThat(cacheFactoryBean.getTransactionListeners().size()).isEqualTo(1);
assertThat(cacheFactoryBean.getTransactionListeners().get(0)).isSameAs(mockTransactionListener);
assertThat(cacheFactoryBean.getTransactionWriter()).isSameAs(mockTransactionWriter);
assertThat(cacheFactoryBean.getUseClusterConfiguration()).isTrue();
}
}

View File

@@ -21,6 +21,7 @@ import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
@@ -29,13 +30,14 @@ import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import java.net.InetSocketAddress;
import java.util.Arrays;
import java.util.Collections;
import java.util.Optional;
import java.util.Properties;
import java.util.function.Supplier;
import org.junit.Test;
@@ -73,7 +75,7 @@ import org.springframework.data.gemfire.util.DistributedSystemUtils;
* @see org.springframework.data.gemfire.client.ClientCacheFactoryBean
* @since 1.7.0
*/
public class ClientCacheFactoryBeanTest {
public class ClientCacheFactoryBeanUnitTests {
private Properties createProperties(String key, String value) {
return addProperty(null, key, value);
@@ -81,7 +83,7 @@ public class ClientCacheFactoryBeanTest {
private Properties addProperty(Properties properties, String key, String value) {
properties = Optional.ofNullable(properties).orElseGet(Properties::new);
properties = properties != null ? properties : new Properties();
properties.setProperty(key, value);
return properties;
@@ -101,12 +103,13 @@ public class ClientCacheFactoryBeanTest {
ClientCache mockClientCache = mock(ClientCache.class);
ClientCacheFactoryBean clientCacheFactoryBean = new ClientCacheFactoryBean();
ClientCacheFactoryBean clientCacheFactoryBean = spy(new ClientCacheFactoryBean());
clientCacheFactoryBean.setCache(mockClientCache);
doReturn(mockClientCache).when(clientCacheFactoryBean).getCache();
assertThat(clientCacheFactoryBean.getObjectType()).isNotEqualTo(ClientCache.class);
assertThat(clientCacheFactoryBean.getObjectType()).isEqualTo(mockClientCache.getClass());
assertThat(ClientCache.class).isAssignableFrom(clientCacheFactoryBean.getObjectType());
}
@Test
@@ -114,6 +117,24 @@ public class ClientCacheFactoryBeanTest {
assertThat(new ClientCacheFactoryBean().isSingleton()).isTrue();
}
@Test
@SuppressWarnings("unchecked")
public void resolvePropertiesCallsResolvePropertiesWithSupplier() {
ClientCacheFactoryBean clientCacheFactoryBean = spy(new ClientCacheFactoryBean());
Properties properties = createProperties("key", "test");
doReturn(properties).when(clientCacheFactoryBean).resolveProperties(isA(Supplier.class));
assertThat(clientCacheFactoryBean.resolveProperties()).isEqualTo(properties);
verify(clientCacheFactoryBean, times(1)).resolveProperties();
verify(clientCacheFactoryBean, times(1)).resolveProperties(isA(Supplier.class));
verifyNoMoreInteractions(clientCacheFactoryBean);
}
@Test
public void resolvePropertiesWhenDistributedSystemIsConnected() {
@@ -122,64 +143,63 @@ public class ClientCacheFactoryBeanTest {
DistributedSystem mockDistributedSystem = mock(DistributedSystem.class);
when(mockDistributedSystem.isConnected()).thenReturn(true);
when(mockDistributedSystem.getProperties()).thenReturn(distributedSystemProperties);
doReturn(true).when(mockDistributedSystem).isConnected();
doReturn(distributedSystemProperties).when(mockDistributedSystem).getProperties();
ClientCacheFactoryBean clientCacheFactoryBean = spy(new ClientCacheFactoryBean());
doReturn(mockDistributedSystem).when(clientCacheFactoryBean).getDistributedSystem();
clientCacheFactoryBean.setProperties(gemfireProperties);
Properties resolvedProperties = clientCacheFactoryBean.resolveProperties();
Properties resolvedProperties = clientCacheFactoryBean.resolveProperties(() -> mockDistributedSystem);
assertThat(resolvedProperties).isNotNull();
assertThat(resolvedProperties).isNotSameAs(gemfireProperties);
assertThat(resolvedProperties).isNotSameAs(distributedSystemProperties);
assertThat(resolvedProperties.size()).isEqualTo(2);
assertThat(resolvedProperties.containsKey(DistributedSystemUtils.DURABLE_CLIENT_ID_PROPERTY_NAME)).isFalse();
assertThat(resolvedProperties.containsKey(DistributedSystemUtils.DURABLE_CLIENT_TIMEOUT_PROPERTY_NAME))
.isFalse();
assertThat(resolvedProperties.containsKey(DistributedSystemUtils.DURABLE_CLIENT_TIMEOUT_PROPERTY_NAME)).isFalse();
assertThat(resolvedProperties.getProperty("gf")).isEqualTo("test");
assertThat(resolvedProperties.getProperty("ds")).isEqualTo("mock");
assertThat(resolvedProperties.size()).isEqualTo(2);
verify(mockDistributedSystem, times(1)).isConnected();
verify(mockDistributedSystem, times(1)).getProperties();
verifyNoMoreInteractions(mockDistributedSystem);
}
@Test
public void resolvePropertiesWhenDistributedSystemIsConnectedAndClientIsDurable() {
Properties gemfireProperties = DistributedSystemUtils.configureDurableClient(
createProperties("gf", "test"), "123", 600);
Properties gemfireProperties = DistributedSystemUtils
.configureDurableClient(createProperties("gf", "test"), "123", 600);
Properties distributedSystemProperties = DistributedSystemUtils.configureDurableClient(
createProperties("ds", "mock"), "987", 300);
Properties distributedSystemProperties = DistributedSystemUtils
.configureDurableClient(createProperties("ds", "mock"), "987", 300);
DistributedSystem mockDistributedSystem = mock(DistributedSystem.class);
when(mockDistributedSystem.isConnected()).thenReturn(true);
when(mockDistributedSystem.getProperties()).thenReturn(distributedSystemProperties);
doReturn(true).when(mockDistributedSystem).isConnected();
doReturn(distributedSystemProperties).when(mockDistributedSystem).getProperties();
ClientCacheFactoryBean clientCacheFactoryBean = spy(new ClientCacheFactoryBean());
doReturn(mockDistributedSystem).when(clientCacheFactoryBean).getDistributedSystem();
clientCacheFactoryBean.setProperties(gemfireProperties);
Properties resolvedProperties = clientCacheFactoryBean.resolveProperties();
Properties resolvedProperties = clientCacheFactoryBean.resolveProperties(() -> mockDistributedSystem);
assertThat(resolvedProperties).isNotNull();
assertThat(resolvedProperties).isNotSameAs(gemfireProperties);
assertThat(resolvedProperties).isNotSameAs(distributedSystemProperties);
assertThat(resolvedProperties.size()).isEqualTo(4);
assertThat(resolvedProperties.getProperty("gf")).isEqualTo("test");
assertThat(resolvedProperties.getProperty("ds")).isEqualTo("mock");
assertThat(resolvedProperties.getProperty(DistributedSystemUtils.DURABLE_CLIENT_ID_PROPERTY_NAME)).isEqualTo("123");
assertThat(resolvedProperties.getProperty(DistributedSystemUtils.DURABLE_CLIENT_TIMEOUT_PROPERTY_NAME)).isEqualTo("600");
assertThat(resolvedProperties.size()).isEqualTo(4);
verify(mockDistributedSystem, times(1)).isConnected();
verify(mockDistributedSystem, times(1)).getProperties();
verifyNoMoreInteractions(mockDistributedSystem);
}
@Test
@@ -190,21 +210,21 @@ public class ClientCacheFactoryBeanTest {
DistributedSystem mockDistributedSystem = mock(DistributedSystem.class);
when(mockDistributedSystem.isConnected()).thenReturn(false);
when(mockDistributedSystem.getProperties()).thenReturn(distributedSystemProperties);
doReturn(false).when(mockDistributedSystem).isConnected();
doReturn(distributedSystemProperties).when(mockDistributedSystem).getProperties();
ClientCacheFactoryBean clientCacheFactoryBean = spy(new ClientCacheFactoryBean());
doReturn(mockDistributedSystem).when(clientCacheFactoryBean).getDistributedSystem();
clientCacheFactoryBean.setProperties(gemfireProperties);
Properties resolvedProperties = clientCacheFactoryBean.resolveProperties();
Properties resolvedProperties = clientCacheFactoryBean.resolveProperties(() -> mockDistributedSystem);
assertThat(resolvedProperties).isSameAs(gemfireProperties);
verify(mockDistributedSystem, times(1)).isConnected();
verify(mockDistributedSystem, never()).getProperties();
verifyNoMoreInteractions(mockDistributedSystem);
}
@Test
@@ -212,22 +232,17 @@ public class ClientCacheFactoryBeanTest {
Properties gemfireProperties = createProperties("gf", "test");
assertThat(gemfireProperties.size()).isEqualTo(1);
ClientCacheFactoryBean clientCacheFactoryBean = spy(new ClientCacheFactoryBean());
doReturn(null).when(clientCacheFactoryBean).getDistributedSystem();
clientCacheFactoryBean.setDurableClientId("123");
clientCacheFactoryBean.setProperties(gemfireProperties);
Properties resolvedProperties = clientCacheFactoryBean.resolveProperties();
Properties resolvedProperties = clientCacheFactoryBean.resolveProperties(() -> null);
assertThat(resolvedProperties).isSameAs(gemfireProperties);
assertThat(resolvedProperties.size()).isEqualTo(2);
assertThat(resolvedProperties.getProperty("gf")).isEqualTo("test");
assertThat(resolvedProperties.getProperty(DistributedSystemUtils.DURABLE_CLIENT_ID_PROPERTY_NAME))
.isEqualTo("123");
assertThat(resolvedProperties.getProperty(DistributedSystemUtils.DURABLE_CLIENT_ID_PROPERTY_NAME)).isEqualTo("123");
assertThat(resolvedProperties.size()).isEqualTo(2);
}
@Test
@@ -242,14 +257,14 @@ public class ClientCacheFactoryBeanTest {
ClientCacheFactory clientCacheFactory = (ClientCacheFactory) clientCacheFactoryReference;
clientCacheFactory.set("testCase", "TestCreateClientCacheFactory");
clientCacheFactory.set("testKey", "testValue");
assertThat(gemfireProperties.containsKey("testCase")).isTrue();
assertThat(gemfireProperties.getProperty("testCase")).isEqualTo("TestCreateClientCacheFactory");
assertThat(gemfireProperties.containsKey("testKey")).isTrue();
assertThat(gemfireProperties.getProperty("testKey")).isEqualTo("testValue");
}
@Test
public void prepareClientCacheFactoryCallsInitializePdxAndInitializePool() {
public void configureClientCacheFactoryCallsConfigurePdxAndConfigurePool() {
ClientCacheFactory mockClientCacheFactory = mock(ClientCacheFactory.class);
@@ -260,12 +275,17 @@ public class ClientCacheFactoryBeanTest {
assertThat(clientCacheFactoryBean.configureFactory(mockClientCacheFactory)).isSameAs(mockClientCacheFactory);
verify(clientCacheFactoryBean, times(1)).configureFactory(eq(mockClientCacheFactory));
verify(clientCacheFactoryBean, times(1)).configurePdx(eq(mockClientCacheFactory));
verify(clientCacheFactoryBean, times(1)).configurePool(eq(mockClientCacheFactory));
verifyNoMoreInteractions(mockClientCacheFactory);
}
@Test
public void initializePdxWithAllPdxOptions() {
public void configurePdxWithAllPdxOptions() {
ClientCacheFactory mockClientCacheFactory = mock(ClientCacheFactory.class);
ClientCacheFactoryBean clientCacheFactoryBean = new ClientCacheFactoryBean();
@@ -283,8 +303,6 @@ public class ClientCacheFactoryBeanTest {
assertThat(clientCacheFactoryBean.getPdxReadSerialized()).isFalse();
assertThat(clientCacheFactoryBean.getPdxSerializer()).isSameAs(mockPdxSerializer);
ClientCacheFactory mockClientCacheFactory = mock(ClientCacheFactory.class);
assertThat(clientCacheFactoryBean.configurePdx(mockClientCacheFactory)).isSameAs(mockClientCacheFactory);
verify(mockClientCacheFactory, times(1)).setPdxSerializer(eq(mockPdxSerializer));
@@ -292,10 +310,14 @@ public class ClientCacheFactoryBeanTest {
verify(mockClientCacheFactory, times(1)).setPdxIgnoreUnreadFields(eq(false));
verify(mockClientCacheFactory, times(1)).setPdxPersistent(eq(true));
verify(mockClientCacheFactory, times(1)).setPdxReadSerialized(eq(false));
verifyNoMoreInteractions(mockClientCacheFactory);
}
@Test
public void initializePdxWithPartialPdxOptions() {
public void configurePdxWithPartialPdxOptions() {
ClientCacheFactory mockClientCacheFactory = mock(ClientCacheFactory.class);
ClientCacheFactoryBean clientCacheFactoryBean = new ClientCacheFactoryBean();
@@ -308,8 +330,6 @@ public class ClientCacheFactoryBeanTest {
assertThat(clientCacheFactoryBean.getPdxReadSerialized()).isTrue();
assertThat(clientCacheFactoryBean.getPdxSerializer()).isNull();
ClientCacheFactory mockClientCacheFactory = mock(ClientCacheFactory.class);
assertThat(clientCacheFactoryBean.configurePdx(mockClientCacheFactory)).isSameAs(mockClientCacheFactory);
verify(mockClientCacheFactory, never()).setPdxDiskStore(anyString());
@@ -317,10 +337,14 @@ public class ClientCacheFactoryBeanTest {
verify(mockClientCacheFactory, never()).setPdxPersistent(anyBoolean());
verify(mockClientCacheFactory, times(1)).setPdxReadSerialized(eq(true));
verify(mockClientCacheFactory, never()).setPdxSerializer(any(PdxSerializer.class));
verifyNoMoreInteractions(mockClientCacheFactory);
}
@Test
public void initializePdxWithNoPdxOptions() {
public void configurePdxWithNoPdxOptions() {
ClientCacheFactory mockClientCacheFactory = mock(ClientCacheFactory.class);
ClientCacheFactoryBean clientCacheFactoryBean = new ClientCacheFactoryBean();
@@ -330,15 +354,13 @@ public class ClientCacheFactoryBeanTest {
assertThat(clientCacheFactoryBean.getPdxReadSerialized()).isNull();
assertThat(clientCacheFactoryBean.getPdxSerializer()).isNull();
ClientCacheFactory mockClientCacheFactory = mock(ClientCacheFactory.class);
assertThat(clientCacheFactoryBean.configurePdx(mockClientCacheFactory)).isSameAs(mockClientCacheFactory);
verifyNoInteractions(mockClientCacheFactory);
}
@Test
public void initializePoolWithClientCacheFactoryBean() {
public void configurePoolWithClientCacheFactoryBean() {
Pool mockPool = mock(Pool.class);
@@ -429,7 +451,7 @@ public class ClientCacheFactoryBeanTest {
}
@Test
public void initializePoolWithPool() {
public void configurePoolWithPool() {
Pool mockPool = mock(Pool.class);
@@ -544,7 +566,7 @@ public class ClientCacheFactoryBeanTest {
}
@Test
public void initializePoolWithClientCacheFactoryBeanAndPoolButClientCacheFactoryBeanOverridesPool() {
public void configurePoolWithClientCacheFactoryBeanAndPoolButClientCacheFactoryBeanOverridesPool() {
Pool mockPool = mock(Pool.class);
@@ -672,7 +694,7 @@ public class ClientCacheFactoryBeanTest {
}
@Test
public void initializePoolWithFactoryLocator() {
public void configurePoolWithFactoryLocator() {
Pool mockPool = mock(Pool.class);
@@ -699,7 +721,7 @@ public class ClientCacheFactoryBeanTest {
}
@Test
public void initializePoolWithFactoryServer() {
public void configurePoolWithFactoryServer() {
Pool mockPool = mock(Pool.class);
@@ -726,7 +748,7 @@ public class ClientCacheFactoryBeanTest {
}
@Test
public void initializePoolWithPoolLocator() {
public void configurePoolWithPoolLocator() {
Pool mockPool = mock(Pool.class);
@@ -752,7 +774,7 @@ public class ClientCacheFactoryBeanTest {
}
@Test
public void initializePoolWithPoolServer() {
public void configurePoolWithPoolServer() {
Pool mockPool = mock(Pool.class);
@@ -778,7 +800,7 @@ public class ClientCacheFactoryBeanTest {
}
@Test
public void initializePoolWithDefaultServer() {
public void configurePoolWithDefaultServer() {
ClientCacheFactoryBean clientCacheFactoryBean = spy(new ClientCacheFactoryBean());
@@ -804,13 +826,14 @@ public class ClientCacheFactoryBeanTest {
ClientCacheFactory mockClientCacheFactory = mock(ClientCacheFactory.class);
when(mockClientCacheFactory.create()).thenReturn(mockClientCache);
doReturn(mockClientCache).when(mockClientCacheFactory).create();
ClientCacheFactoryBean clientCacheFactoryBean = new ClientCacheFactoryBean();
assertThat(clientCacheFactoryBean.<GemFireCache>createCache(mockClientCacheFactory)).isSameAs(mockClientCache);
verify(mockClientCacheFactory, times(1)).create();
verifyNoMoreInteractions(mockClientCacheFactory);
verifyNoInteractions(mockClientCache);
}
@@ -907,7 +930,7 @@ public class ClientCacheFactoryBeanTest {
ClientCacheFactoryBean clientCacheFactoryBean = spy(new ClientCacheFactoryBean());
doReturn(mockClientCache).when(clientCacheFactoryBean).fetchCache();
doReturn(mockClientCache).when(clientCacheFactoryBean).getCache();
clientCacheFactoryBean.setReadyForEvents(true);
@@ -927,7 +950,7 @@ public class ClientCacheFactoryBeanTest {
ClientCacheFactoryBean clientCacheFactoryBean = spy(new ClientCacheFactoryBean());
doReturn(mockClientCache).when(clientCacheFactoryBean).fetchCache();
doReturn(mockClientCache).when(clientCacheFactoryBean).getCache();
clientCacheFactoryBean.setReadyForEvents(false);
@@ -947,7 +970,7 @@ public class ClientCacheFactoryBeanTest {
ClientCacheFactoryBean clientCacheFactoryBean = spy(new ClientCacheFactoryBean());
doReturn(mockClientCache).when(clientCacheFactoryBean).fetchCache();
doReturn(mockClientCache).when(clientCacheFactoryBean).getCache();
clientCacheFactoryBean.setReadyForEvents(true);
@@ -963,7 +986,7 @@ public class ClientCacheFactoryBeanTest {
ClientCacheFactoryBean clientCacheFactoryBean = spy(new ClientCacheFactoryBean());
doThrow(new CacheClosedException("test")).when(clientCacheFactoryBean).fetchCache();
doThrow(new CacheClosedException("test")).when(clientCacheFactoryBean).getCache();
clientCacheFactoryBean.setReadyForEvents(true);
@@ -1188,7 +1211,7 @@ public class ClientCacheFactoryBeanTest {
ClientCacheFactoryBean clientCacheFactoryBean = spy(new ClientCacheFactoryBean());
doReturn(mockClientCache).when(clientCacheFactoryBean).fetchCache();
doReturn(mockClientCache).when(clientCacheFactoryBean).getCache();
clientCacheFactoryBean.setReadyForEvents(true);
@@ -1205,7 +1228,7 @@ public class ClientCacheFactoryBeanTest {
ClientCacheFactoryBean clientCacheFactoryBean = spy(new ClientCacheFactoryBean());
doReturn(mockClientCache).when(clientCacheFactoryBean).fetchCache();
doReturn(mockClientCache).when(clientCacheFactoryBean).getCache();
clientCacheFactoryBean.setReadyForEvents(false);
@@ -1220,7 +1243,7 @@ public class ClientCacheFactoryBeanTest {
ClientCacheFactoryBean clientCacheFactoryBean = spy(new ClientCacheFactoryBean());
doThrow(new CacheClosedException("test")).when(clientCacheFactoryBean).fetchCache();
doThrow(new CacheClosedException("test")).when(clientCacheFactoryBean).getCache();
assertThat(clientCacheFactoryBean.getReadyForEvents()).isNull();
assertThat(clientCacheFactoryBean.isReadyForEvents()).isFalse();
@@ -1233,7 +1256,7 @@ public class ClientCacheFactoryBeanTest {
ClientCacheFactoryBean clientCacheFactoryBean = spy(new ClientCacheFactoryBean());
doReturn(mockClientCache).when(clientCacheFactoryBean).fetchCache();
doReturn(mockClientCache).when(clientCacheFactoryBean).getCache();
assertThat(clientCacheFactoryBean.getReadyForEvents()).isNull();
assertThat(clientCacheFactoryBean.isReadyForEvents()).isTrue();
@@ -1248,7 +1271,7 @@ public class ClientCacheFactoryBeanTest {
ClientCacheFactoryBean clientCacheFactoryBean = spy(new ClientCacheFactoryBean());
doReturn(mockClientCache).when(clientCacheFactoryBean).fetchCache();
doReturn(mockClientCache).when(clientCacheFactoryBean).getCache();
assertThat(clientCacheFactoryBean.getReadyForEvents()).isNull();
assertThat(clientCacheFactoryBean.isReadyForEvents()).isFalse();

View File

@@ -30,9 +30,9 @@ public class MockClientCacheFactoryBean extends ClientCacheFactoryBean {
setUseBeanFactoryLocator(false);
Optional.ofNullable(clientCacheFactoryBean).ifPresent(it -> {
this.beanFactoryLocator = it.getBeanFactoryLocator();
setBeanClassLoader(it.getBeanClassLoader());
setBeanFactory(it.getBeanFactory());
setBeanFactoryLocator(it.getBeanFactoryLocator());
setBeanName(it.getBeanName());
setCacheXml(it.getCacheXml());
setCopyOnRead(it.getCopyOnRead());