Create the new AbstractConfigurableCacheFactoryBean class.
The intent of this abstract class is to encapsulate externalized configuration metadata applied to the cache such as Apache Geode native cache.xml as well as gemfire.properties. This abstract class also handles any additional component configuration related to external configuration metadata handling, such as configuration applied and processed by the GemfireBeanFactoryLocator. Resolves gh-493.
This commit is contained in:
@@ -15,16 +15,9 @@
|
||||
*/
|
||||
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.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.apache.geode.GemFireCheckedException;
|
||||
@@ -40,12 +33,10 @@ import org.apache.geode.cache.client.ClientCache;
|
||||
import org.apache.geode.cache.client.ClientCacheFactory;
|
||||
import org.apache.geode.pdx.PdxSerializer;
|
||||
|
||||
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;
|
||||
@@ -53,7 +44,6 @@ 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.data.gemfire.util.CollectionUtils;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.lang.Nullable;
|
||||
@@ -67,44 +57,48 @@ import org.springframework.util.StringUtils;
|
||||
* 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.
|
||||
* the presence of this class automatically enables Spring's {@link PersistenceExceptionTranslationPostProcessor}
|
||||
* to translate Apache Geode thrown {@link GemFireException} and {@link GemFireCheckedException} types
|
||||
* as Spring {@link DataAccessException DataAccessExceptions}.
|
||||
*
|
||||
* Importantly, this abstract class encapsulates configuration applicable to tuning Apache Geode to efficiently use JVM
|
||||
* Heap memory. Since Apache Geode stores data in-memory, on the JVM Heap, it is important that Apache 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.
|
||||
* More importantly, this abstract class encapsulates configuration applicable to tuning Apache Geode in order to
|
||||
* efficiently use JVM Heap memory. Since Apache Geode stores data in-memory, on the JVM Heap, it is important that
|
||||
* Apache Geode be tuned to monitor the JVM Heap and respond to memory pressure accordingly, by evicting data
|
||||
* and issuing warnings when the JVM Heap reaches critical mass.
|
||||
*
|
||||
* This abstract class is also concerned with the configuration of PDX and transaction event handling along with
|
||||
* whether the contents (entries) of the cache should be made effectively immutable on reads (i.e. get(key)).
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.io.File
|
||||
* @see java.util.Properties
|
||||
* @see org.apache.geode.GemFireCheckedException
|
||||
* @see org.apache.geode.GemFireException
|
||||
* @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.TransactionListener
|
||||
* @see org.apache.geode.cache.TransactionWriter
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @see org.apache.geode.cache.client.ClientCacheFactory
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see org.apache.geode.pdx.PdxSerializer
|
||||
* @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.annotation.PersistenceExceptionTranslationPostProcessor
|
||||
* @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;
|
||||
|
||||
@@ -120,44 +114,16 @@ public abstract class AbstractBasicCacheFactoryBean extends AbstractFactoryBeanS
|
||||
private Float evictionHeapPercentage;
|
||||
private Float evictionOffHeapPercentage;
|
||||
|
||||
private GemfireBeanFactoryLocator beanFactoryLocator;
|
||||
|
||||
private GemFireCache cache;
|
||||
|
||||
private List<TransactionListener> transactionListeners;
|
||||
|
||||
private PdxSerializer pdxSerializer;
|
||||
|
||||
private Properties properties;
|
||||
|
||||
private Resource cacheXml;
|
||||
|
||||
private String pdxDiskStoreName;
|
||||
|
||||
private TransactionWriter transactionWriter;
|
||||
|
||||
/**
|
||||
* 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}.
|
||||
@@ -219,62 +185,6 @@ public abstract class AbstractBasicCacheFactoryBean extends AbstractFactoryBeanS
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a boolean value used to determine whether the cache should be closed on shutdown of the Spring application.
|
||||
*
|
||||
@@ -406,9 +316,9 @@ public abstract class AbstractBasicCacheFactoryBean extends AbstractFactoryBeanS
|
||||
protected abstract GemFireCache doGetObject();
|
||||
|
||||
/**
|
||||
* Returns the {@link Class type} of {@link GemFireCache} produced by this cache {@link FactoryBean}.
|
||||
* Returns the {@link Class type} of {@link GemFireCache} created by this cache {@link FactoryBean}.
|
||||
*
|
||||
* @return the {@link Class type} type of {@link GemFireCache} produced by this cache {@link FactoryBean}.
|
||||
* @return the {@link Class type} type of {@link GemFireCache} created by this cache {@link FactoryBean}.
|
||||
* @see org.springframework.beans.factory.FactoryBean#getObjectType()
|
||||
*/
|
||||
@Override
|
||||
@@ -419,6 +329,13 @@ public abstract class AbstractBasicCacheFactoryBean extends AbstractFactoryBeanS
|
||||
return cache != null ? cache.getClass() : doGetObjectType();
|
||||
}
|
||||
|
||||
/**
|
||||
* By default, returns {@link GemFireCache} {@link Class}.
|
||||
*
|
||||
* @return {@link GemFireCache} {@link Class} by default.
|
||||
* @see org.apache.geode.cache.GemFireCache#getClass()
|
||||
* @see java.lang.Class
|
||||
*/
|
||||
protected Class<? extends GemFireCache> doGetObjectType() {
|
||||
return GemFireCache.class;
|
||||
}
|
||||
@@ -562,40 +479,6 @@ public abstract class AbstractBasicCacheFactoryBean extends AbstractFactoryBeanS
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the cache (transaction manager) with a {@link List} of {@link TransactionListener TransactionListeners}
|
||||
* implemented by applications to listen for and receive transaction events after a transaction is processed
|
||||
@@ -605,7 +488,7 @@ public abstract class AbstractBasicCacheFactoryBean extends AbstractFactoryBeanS
|
||||
* registered with the cache to listen for and receive transaction events.
|
||||
* @see org.apache.geode.cache.TransactionListener
|
||||
*/
|
||||
public void setTransactionListeners(@NonNull List<TransactionListener> transactionListeners) {
|
||||
public void setTransactionListeners(List<TransactionListener> transactionListeners) {
|
||||
this.transactionListeners = transactionListeners;
|
||||
}
|
||||
|
||||
@@ -618,7 +501,7 @@ public abstract class AbstractBasicCacheFactoryBean extends AbstractFactoryBeanS
|
||||
* the cache (transaction manager) to listen for and receive transaction events.
|
||||
* @see org.apache.geode.cache.TransactionListener
|
||||
*/
|
||||
public @NonNull List<TransactionListener> getTransactionListeners() {
|
||||
public List<TransactionListener> getTransactionListeners() {
|
||||
return CollectionUtils.nullSafeList(this.transactionListeners);
|
||||
}
|
||||
|
||||
@@ -643,26 +526,6 @@ public abstract class AbstractBasicCacheFactoryBean extends AbstractFactoryBeanS
|
||||
return this.transactionWriter;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes this cache {@link FactoryBean} after all properties for this cache bean have been set
|
||||
* by the Spring container.
|
||||
@@ -670,12 +533,10 @@ public abstract class AbstractBasicCacheFactoryBean extends AbstractFactoryBeanS
|
||||
* @throws Exception if initialization fails.
|
||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||
* @see #applyCacheConfigurers()
|
||||
* @see #initBeanFactoryLocator()
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
applyCacheConfigurers();
|
||||
initBeanFactoryLocator();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -705,8 +566,8 @@ public abstract class AbstractBasicCacheFactoryBean extends AbstractFactoryBeanS
|
||||
* Destroys the cache bean on Spring Container shutdown.
|
||||
*
|
||||
* @see org.springframework.beans.factory.DisposableBean#destroy()
|
||||
* @see #destroyBeanFactoryLocator()
|
||||
* @see #close(GemFireCache)
|
||||
* @see #fetchCache()
|
||||
* @see #isClose()
|
||||
*/
|
||||
@Override
|
||||
@@ -714,50 +575,13 @@ public abstract class AbstractBasicCacheFactoryBean extends AbstractFactoryBeanS
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the {@link GemFireCache} critical and eviction heap thresholds as percentages.
|
||||
*
|
||||
@@ -830,6 +654,29 @@ public abstract class AbstractBasicCacheFactoryBean extends AbstractFactoryBeanS
|
||||
return cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches an existing cache instance from the Apache Geode cache factory.
|
||||
*
|
||||
@@ -851,23 +698,6 @@ public abstract class AbstractBasicCacheFactoryBean extends AbstractFactoryBeanS
|
||||
|
||||
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}.
|
||||
@@ -888,33 +718,6 @@ public abstract class AbstractBasicCacheFactoryBean extends AbstractFactoryBeanS
|
||||
.orElse(factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the configured {@literal cache.xml} to initialize the {@link GemFireCache}.
|
||||
*
|
||||
* @param <T> parameterized {@link Class} type extending {@link GemFireCache}.
|
||||
* @param cache {@link GemFireCache} instance to initialize with {@literal cache.xml}; must not be {@literal null}.
|
||||
* @return the given {@link GemFireCache}.
|
||||
* @throws RuntimeException if the configured {@literal cache.xml} file could not be loaded
|
||||
* into the {@link GemFireCache}.
|
||||
* @see org.apache.geode.cache.GemFireCache#loadCacheXml(InputStream)
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
*/
|
||||
protected @NonNull <T extends GemFireCache> T loadCacheXml(@NonNull 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers configured, application-defined {@link TransactionListener TransactionListeners} with the cache
|
||||
* (transaction manager) to listen for and receive transaction events when a (cache) transaction is processed
|
||||
@@ -959,20 +762,6 @@ public abstract class AbstractBasicCacheFactoryBean extends AbstractFactoryBeanS
|
||||
return cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the Apache Geode {@link Properties} used to configure the {@link GemFireCache}.
|
||||
*
|
||||
* @return the resolved Apache Geode {@link Properties} used to configure the {@link GemFireCache}.
|
||||
* @see #setAndGetProperties(Properties)
|
||||
* @see #getProperties()
|
||||
* @see java.util.Properties
|
||||
*/
|
||||
protected @NonNull Properties resolveProperties() {
|
||||
|
||||
return Optional.ofNullable(getProperties())
|
||||
.orElseGet(() -> setAndGetProperties(new Properties()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates the thrown Apache Geode {@link RuntimeException} into a corresponding {@link Exception} from Spring's
|
||||
* generic {@link DataAccessException} hierarchy if possible.
|
||||
|
||||
@@ -0,0 +1,296 @@
|
||||
/*
|
||||
* 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.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.cache.Cache;
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.cache.client.ClientCache;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.data.gemfire.support.GemfireBeanFactoryLocator;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Abstract base class encapsulating functionality for (externally) configuring an Apache Geode {@link ClientCache}
|
||||
* or peer {@link Cache} as a bean in the Spring context.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.io.File
|
||||
* @see java.io.InputStream
|
||||
* @see java.util.Properties
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see org.springframework.core.io.Resource
|
||||
* @see org.springframework.data.gemfire.support.GemfireBeanFactoryLocator
|
||||
* @since 2.5.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public abstract class AbstractConfigurableCacheFactoryBean extends AbstractBasicCacheFactoryBean {
|
||||
|
||||
private boolean useBeanFactoryLocator = false;
|
||||
|
||||
private GemfireBeanFactoryLocator beanFactoryLocator;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an {@link Optional} reference to the configured {@link GemfireBeanFactoryLocator} used to
|
||||
* resolve Spring bean references in Apache Geode native configuration metadata (e.g. {@literal cache.xml}).
|
||||
*
|
||||
* @return an {@link Optional} reference to the configured {@link GemfireBeanFactoryLocator}.
|
||||
* @see org.springframework.data.gemfire.support.GemfireBeanFactoryLocator
|
||||
* @see #getBeanFactoryLocator()
|
||||
* @see java.util.Optional
|
||||
*/
|
||||
public Optional<GemfireBeanFactoryLocator> getOptionalBeanFactoryLocator() {
|
||||
return Optional.ofNullable(getBeanFactoryLocator());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an {@link Optional} reference to an Apache Geode native {@literal cache.xml} {@link Resource}.
|
||||
*
|
||||
* @return an {@link Optional} reference to an Apache Geode native {@literal cache.xml} {@link Resource}.
|
||||
* @see org.springframework.core.io.Resource
|
||||
* @see java.util.Optional
|
||||
* @see #getCacheXml()
|
||||
*/
|
||||
public Optional<Resource> getOptionalCacheXml() {
|
||||
return Optional.ofNullable(getCacheXml());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a {@literal cache.xml} {@link Resource} exists (i.e. is present).
|
||||
*
|
||||
* @return boolean value indicating whether a {@literal cache.xml} exists.
|
||||
* @see org.springframework.core.io.Resource#exists()
|
||||
* @see #getCacheXml()
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
protected boolean isCacheXmlPresent() {
|
||||
|
||||
Resource cacheXml = getCacheXml();
|
||||
|
||||
return cacheXml != null && cacheXml.exists();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the optionally configured {@literal cache.xml} is resolvable as a {@link File}
|
||||
* in the file system.
|
||||
*
|
||||
* @return a boolean value indicating whether the optionally configured {@literal cache.xml}
|
||||
* is resolvable as a {@link File} in the file system.
|
||||
* @see org.springframework.core.io.Resource#isFile()
|
||||
* @see #getCacheXml()
|
||||
* @see java.io.File
|
||||
*/
|
||||
protected boolean isCacheXmlResolvableAsAFile() {
|
||||
|
||||
Resource cacheXml = getCacheXml();
|
||||
|
||||
return cacheXml != null && cacheXml.isFile();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 @Nullable 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the {@link GemfireBeanFactoryLocator} if {@link #isUseBeanFactoryLocator()} returns {@literal true}
|
||||
* and an existing {@link #getBeanFactoryLocator() GemfireBeanFactoryLocator} is not already present.
|
||||
*
|
||||
* @see org.springframework.data.gemfire.support.GemfireBeanFactoryLocator#newBeanFactoryLocator(BeanFactory, String)
|
||||
* @see #isUseBeanFactoryLocator()
|
||||
* @see #getBeanFactoryLocator()
|
||||
* @see #getBeanFactory()
|
||||
* @see #getBeanName()
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
|
||||
super.afterPropertiesSet();
|
||||
|
||||
if (useBeanFactoryLocator()) {
|
||||
setBeanFactoryLocator(GemfireBeanFactoryLocator.newBeanFactoryLocator(getBeanFactory(), getBeanName()));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean useBeanFactoryLocator() {
|
||||
return isUseBeanFactoryLocator() && getBeanFactoryLocator() == null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys and releases resources used by the {@link GemfireBeanFactoryLocator}, if present.
|
||||
*
|
||||
* @see org.springframework.data.gemfire.support.GemfireBeanFactoryLocator#destroy()
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
|
||||
super.destroy();
|
||||
|
||||
getOptionalBeanFactoryLocator().ifPresent(GemfireBeanFactoryLocator::destroy);
|
||||
|
||||
setBeanFactoryLocator(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the configured {@literal cache.xml} to initialize the {@link GemFireCache}.
|
||||
*
|
||||
* @param <T> parameterized {@link Class} type extending {@link GemFireCache}.
|
||||
* @param cache {@link GemFireCache} instance to initialize with {@literal cache.xml}; must not be {@literal null}.
|
||||
* @return the given {@link GemFireCache}.
|
||||
* @throws RuntimeException if the configured {@literal cache.xml} file could not be loaded
|
||||
* into the {@link GemFireCache}.
|
||||
* @see org.apache.geode.cache.GemFireCache#loadCacheXml(InputStream)
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
*/
|
||||
protected @NonNull <T extends GemFireCache> T loadCacheXml(@NonNull T cache) {
|
||||
|
||||
// Load the cache.xml file (Resource) and initialize the cache
|
||||
getOptionalCacheXml().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 GemFireCache}.
|
||||
*
|
||||
* @return the resolved Apache Geode {@link Properties} used to configure the {@link GemFireCache}.
|
||||
* @see #setAndGetProperties(Properties)
|
||||
* @see #getProperties()
|
||||
* @see java.util.Properties
|
||||
*/
|
||||
protected @NonNull Properties resolveProperties() {
|
||||
|
||||
Properties properties = getProperties();
|
||||
|
||||
return properties != null ? properties : setAndGetProperties(new Properties());
|
||||
}
|
||||
}
|
||||
@@ -36,10 +36,10 @@ import org.springframework.lang.NonNull;
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.distributed.DistributedMember
|
||||
* @see org.apache.geode.distributed.DistributedSystem
|
||||
* @see org.springframework.data.gemfire.AbstractBasicCacheFactoryBean
|
||||
* @see org.springframework.data.gemfire.AbstractConfigurableCacheFactoryBean
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public abstract class AbstractResolvableCacheFactoryBean extends AbstractBasicCacheFactoryBean {
|
||||
public abstract class AbstractResolvableCacheFactoryBean extends AbstractConfigurableCacheFactoryBean {
|
||||
|
||||
private volatile String cacheResolutionMessagePrefix;
|
||||
|
||||
|
||||
@@ -98,6 +98,7 @@ public class CacheFactoryBeanUnitTests {
|
||||
|
||||
CacheFactoryBean cacheFactoryBean = spy(new CacheFactoryBean());
|
||||
|
||||
cacheFactoryBean.setUseBeanFactoryLocator(true);
|
||||
cacheFactoryBean.afterPropertiesSet();
|
||||
|
||||
InOrder orderVerifier = inOrder(cacheFactoryBean);
|
||||
@@ -106,7 +107,7 @@ public class CacheFactoryBeanUnitTests {
|
||||
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();
|
||||
orderVerifier.verify(cacheFactoryBean, times(1)).setBeanFactoryLocator(isA(GemfireBeanFactoryLocator.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -738,7 +739,6 @@ public class CacheFactoryBeanUnitTests {
|
||||
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();
|
||||
@@ -761,7 +761,6 @@ public class CacheFactoryBeanUnitTests {
|
||||
verify(cacheFactoryBean, times(1)).isClose();
|
||||
verify(cacheFactoryBean, times(1)).fetchCache();
|
||||
verify(cacheFactoryBean, times(1)).close(isNull());
|
||||
verify(cacheFactoryBean, times(1)).destroyBeanFactoryLocator();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -776,7 +775,6 @@ public class CacheFactoryBeanUnitTests {
|
||||
verify(cacheFactoryBean, times(1)).isClose();
|
||||
verify(cacheFactoryBean, never()).fetchCache();
|
||||
verify(cacheFactoryBean, never()).close(any());
|
||||
verify(cacheFactoryBean, never()).destroyBeanFactoryLocator();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user