diff --git a/spring-data-geode/src/main/java/org/springframework/data/gemfire/AbstractBasicCacheFactoryBean.java b/spring-data-geode/src/main/java/org/springframework/data/gemfire/AbstractBasicCacheFactoryBean.java index 2bdbe00c..00d9aebc 100644 --- a/spring-data-geode/src/main/java/org/springframework/data/gemfire/AbstractBasicCacheFactoryBean.java +++ b/spring-data-geode/src/main/java/org/springframework/data/gemfire/AbstractBasicCacheFactoryBean.java @@ -58,9 +58,12 @@ import org.springframework.util.StringUtils; * {@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 Spring's {@link PersistenceExceptionTranslationPostProcessor} - * to translate Apache Geode thrown {@link GemFireException} and {@link GemFireCheckedException} types + * to translate native Apache Geode thrown {@link GemFireException} and {@link GemFireCheckedException} types * as Spring {@link DataAccessException DataAccessExceptions}. * + * In addition, this class also assumes the responsibility of positioning the creation of the cache in the appropriate + * phase of the Spring container's lifecycle, providing default callbacks for both initialization and destruction. + * * 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 @@ -69,6 +72,17 @@ import org.springframework.util.StringUtils; * 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)). * + * In summary, this abstract class primarily handles and encapsulates the configuration of the following concerns: + * + * + * + * All of these concerns are applicable to both Apache Geode {@link ClientCache} and peer {@link Cache} instances. + * * @author John Blum * @see org.apache.geode.GemFireCheckedException * @see org.apache.geode.GemFireException @@ -114,7 +128,7 @@ public abstract class AbstractBasicCacheFactoryBean extends AbstractFactoryBeanS private Float evictionHeapPercentage; private Float evictionOffHeapPercentage; - private GemFireCache cache; + private volatile GemFireCache cache; private List transactionListeners; @@ -128,7 +142,7 @@ public abstract class AbstractBasicCacheFactoryBean extends AbstractFactoryBeanS * 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}. + * @param cache {@link GemFireCache} created by this cache {@link FactoryBean}. * @see org.apache.geode.cache.GemFireCache */ protected void setCache(@Nullable GemFireCache cache) { @@ -139,7 +153,8 @@ public abstract class AbstractBasicCacheFactoryBean extends AbstractFactoryBeanS * 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}. + * @param parameterized {@link Class} type extending {@link GemFireCache}. + * @return a reference to the {@link GemFireCache} created by this cache {@link FactoryBean}. * @see org.apache.geode.cache.GemFireCache */ @SuppressWarnings("unchecked") @@ -152,7 +167,7 @@ public abstract class AbstractBasicCacheFactoryBean extends AbstractFactoryBeanS * instance created by this cache {@link FactoryBean}. * * @param parameterized {@link Class} type extending {@link GemFireCache}. - * @return an {@link Optional} reference to the {@link GemFireCache} created by this {@link FactoryBean}. + * @return an {@link Optional} reference to the {@link GemFireCache} created by this {cache @link FactoryBean}. * @see org.apache.geode.cache.GemFireCache * @see java.util.Optional * @see #getCache() @@ -186,123 +201,141 @@ public abstract class AbstractBasicCacheFactoryBean extends AbstractFactoryBeanS } /** - * Sets a boolean value used to determine whether the cache should be closed on shutdown of the Spring application. + * Sets a boolean value used to determine whether the cache should be closed on shutdown of the Spring container. * - * @param close boolean value used to determine whether the cache will 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 container. */ public void setClose(boolean close) { this.close = close; } /** - * Returns a boolean value used to determine whether the cache will be closed on shutdown of the Spring application. + * Returns a boolean value used to determine whether the cache will be closed on shutdown of the Spring container. * - * @return a boolean value used to determine whether the cache will be closed on shutdown of the Spring application. + * Defaults to {@literal true}. + * + * @return a boolean value used to determine whether the cache will be closed on shutdown of the Spring container. */ public boolean isClose() { return this.close; } /** - * Sets the {@link GemFireCache#getCopyOnRead()} property of the {@link GemFireCache cache}. + * Sets the {@link GemFireCache#getCopyOnRead()} property of the {@link GemFireCache}. * - * @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)}. + * @param copyOnRead a {@link Boolean} value to indicate whether {@link Object objects} + * stored in the {@link GemFireCache} 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}. + * Returns the configuration of the {@link GemFireCache#getCopyOnRead()} property set on the {@link GemFireCache}. * - * @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)}. + * @return a {@link Boolean} value to indicate whether {@link Object objects} + * stored in the {@link GemFireCache} 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)}. + * Determines whether {@link Object objects} stored in the {@link GemFireCache} 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)}. + * Defaults to {@literal false}. + * + * @return a boolean value indicating whether {@link Object objects} stored in the {@link GemFireCache} + * are copied when read (i.e. {@link Region#get(Object)}. + * @see #getCopyOnRead() */ public boolean isCopyOnRead() { - return Boolean.TRUE.equals(this.copyOnRead); + return Boolean.TRUE.equals(getCopyOnRead()); } /** - * Set the Cache's critical heap percentage attribute. + * Set the {@link GemFireCache} critical heap percentage property. * - * @param criticalHeapPercentage floating point value indicating the critical heap percentage. + * @param criticalHeapPercentage {@link Float} value specifying the configuration for the {@link GemFireCache} + * critical heap percentage. */ public void setCriticalHeapPercentage(@Nullable Float criticalHeapPercentage) { this.criticalHeapPercentage = criticalHeapPercentage; } /** - * @return the criticalHeapPercentage + * Gets the configuration of the {@link GemFireCache} critical heap percentage property. + * + * @return a {@link Float} value specifying the configuration for the {@link GemFireCache} critical heap percentage. */ public Float getCriticalHeapPercentage() { return this.criticalHeapPercentage; } /** - * Set the cache's critical off-heap percentage property. + * Set the {@link GemFireCache} critical off-heap percentage property. * - * @param criticalOffHeapPercentage floating point value indicating the critical off-heap percentage. + * @param criticalOffHeapPercentage {@link Float} value specifying the configuration for the {@link GemFireCache} + * critical off-heap percentage. */ public void setCriticalOffHeapPercentage(@Nullable Float criticalOffHeapPercentage) { this.criticalOffHeapPercentage = criticalOffHeapPercentage; } /** - * @return the criticalOffHeapPercentage + * Gets the configuration of the {@link GemFireCache} critical off-heap percentage property. + * + * @return a {@link Float} value specifying the configuration for the {@link GemFireCache} critical off-heap + * percentage. */ public Float getCriticalOffHeapPercentage() { return this.criticalOffHeapPercentage; } /** - * Set the Cache's eviction heap percentage attribute. + * Set the {@link GemFireCache} eviction heap percentage property. * - * @param evictionHeapPercentage float-point value indicating the Cache's heap use percentage to trigger eviction. + * @param evictionHeapPercentage {@link Float} value specifying the configuration for the {@link GemFireCache} + * eviction heap percentage. */ public void setEvictionHeapPercentage(Float evictionHeapPercentage) { this.evictionHeapPercentage = evictionHeapPercentage; } /** - * @return the evictionHeapPercentage + * Gets the configuration of the {@link GemFireCache} eviction heap percentage property. + * + * @return a {@link Float} value specifying the configuration for the {@link GemFireCache} eviction heap percentage. */ public Float getEvictionHeapPercentage() { return this.evictionHeapPercentage; } /** - * Set the cache's eviction off-heap percentage property. + * Set the {@link GemFireCache} eviction off-heap percentage property. * - * @param evictionOffHeapPercentage float-point value indicating the percentage of off-heap use triggering eviction. + * @param evictionOffHeapPercentage {@link Float} value specifying the configuration for the {@link GemFireCache} + * eviction off-heap percentage. */ public void setEvictionOffHeapPercentage(Float evictionOffHeapPercentage) { this.evictionOffHeapPercentage = evictionOffHeapPercentage; } /** - * @return the evictionOffHeapPercentage + * Gets the configuration of the {@link GemFireCache} eviction off-heap percentage property. + * + * @return a {@link Float} value specifying the configuration for the {@link GemFireCache} eviction off-heap + * percentage. */ public Float getEvictionOffHeapPercentage() { return this.evictionOffHeapPercentage; } /** - * Returns the cache object reference created by this cache {@link FactoryBean}. + * Returns the {@link GemFireCache cache object reference} created by this cache {@link FactoryBean}. * - * @return the cache object reference created by this cache {@link FactoryBean}. + * @return the {@link GemFireCache cache object reference} created by this cache {@link FactoryBean}. * @see org.springframework.beans.factory.FactoryBean#getObject() * @see org.apache.geode.cache.GemFireCache * @see #doGetObject() @@ -310,16 +343,27 @@ public abstract class AbstractBasicCacheFactoryBean extends AbstractFactoryBeanS */ @Override public GemFireCache getObject() throws Exception { - return Optional.ofNullable(getCache()).orElseGet(this::doGetObject); + + GemFireCache cache = getCache(); + + return cache != null ? cache : doGetObject(); } + /** + * Called if {@link #getCache()} returns a {@literal null} {@link GemFireCache} reference from {@link #getObject()}. + * + * @return a new constructed, configured and initialized {@link GemFireCache} instance. + * @see org.apache.geode.cache.GemFireCache + * @see #getObject() + */ protected abstract GemFireCache doGetObject(); /** * Returns the {@link Class type} of {@link GemFireCache} created by this cache {@link FactoryBean}. * - * @return the {@link Class type} type of {@link GemFireCache} created by this cache {@link FactoryBean}. + * @return the {@link Class type} of {@link GemFireCache} created by this cache {@link FactoryBean}. * @see org.springframework.beans.factory.FactoryBean#getObjectType() + * @see #doGetObjectType() */ @Override public Class getObjectType() { @@ -334,6 +378,7 @@ public abstract class AbstractBasicCacheFactoryBean extends AbstractFactoryBeanS * * @return {@link GemFireCache} {@link Class} by default. * @see org.apache.geode.cache.GemFireCache#getClass() + * @see #getObjectType() * @see java.lang.Class */ protected Class doGetObjectType() { @@ -461,7 +506,8 @@ public abstract class AbstractBasicCacheFactoryBean extends AbstractFactoryBeanS /** * 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. + * @param phase {@link Integer#TYPE} value specifying the lifecycle phase for this cache bean + * in the Spring container. * @see org.springframework.context.Phased#getPhase() */ protected void setPhase(int phase) { @@ -471,7 +517,7 @@ public abstract class AbstractBasicCacheFactoryBean extends AbstractFactoryBeanS /** * 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. + * @return an {@link Integer#TYPE} used specifying the lifecycle phase for this cache bean in the Spring container. * @see org.springframework.context.Phased#getPhase() */ @Override @@ -696,6 +742,19 @@ public abstract class AbstractBasicCacheFactoryBean extends AbstractFactoryBeanS return cache != null ? cache : doFetchCache(); } + /** + * Called by {@link #fetchCache()} if the {@link GemFireCache} reference returned by {@link #getCache()} + * is {@literal null}. + * + * This method is typically implemented by calling {@link CacheFactory#getAnyInstance()} + * or {@link ClientCacheFactory#getAnyInstance()} depending on the {@link GemFireCache} type declared + * and used in the Spring application. + * + * @param parameterized {@link Class} type extending {@link GemFireCache}. + * @return a (existing) reference to a {@link GemFireCache} instance. + * @throws org.apache.geode.cache.CacheClosedException if a {@link GemFireCache} reference does not exist. + * @see #fetchCache() + */ protected abstract T doFetchCache(); /** diff --git a/spring-data-geode/src/main/java/org/springframework/data/gemfire/AbstractConfigurableCacheFactoryBean.java b/spring-data-geode/src/main/java/org/springframework/data/gemfire/AbstractConfigurableCacheFactoryBean.java index 47704412..8840116e 100644 --- a/spring-data-geode/src/main/java/org/springframework/data/gemfire/AbstractConfigurableCacheFactoryBean.java +++ b/spring-data-geode/src/main/java/org/springframework/data/gemfire/AbstractConfigurableCacheFactoryBean.java @@ -46,6 +46,7 @@ import org.springframework.lang.Nullable; * @see org.apache.geode.cache.client.ClientCache * @see org.springframework.beans.factory.BeanFactory * @see org.springframework.core.io.Resource + * @see org.springframework.data.gemfire.AbstractBasicCacheFactoryBean * @see org.springframework.data.gemfire.support.GemfireBeanFactoryLocator * @since 2.5.0 */ @@ -218,8 +219,8 @@ public abstract class AbstractConfigurableCacheFactoryBean extends AbstractBasic * and an existing {@link #getBeanFactoryLocator() GemfireBeanFactoryLocator} is not already present. * * @see org.springframework.data.gemfire.support.GemfireBeanFactoryLocator#newBeanFactoryLocator(BeanFactory, String) + * @see #getOptionalBeanFactoryLocator() * @see #isUseBeanFactoryLocator() - * @see #getBeanFactoryLocator() * @see #getBeanFactory() * @see #getBeanName() */ @@ -234,13 +235,14 @@ public abstract class AbstractConfigurableCacheFactoryBean extends AbstractBasic } private boolean useBeanFactoryLocator() { - return isUseBeanFactoryLocator() && getBeanFactoryLocator() == null; + return isUseBeanFactoryLocator() && !getOptionalBeanFactoryLocator().isPresent(); } /** * Destroys and releases resources used by the {@link GemfireBeanFactoryLocator}, if present. * * @see org.springframework.data.gemfire.support.GemfireBeanFactoryLocator#destroy() + * @see #getOptionalBeanFactoryLocator() */ @Override public void destroy() { @@ -262,6 +264,7 @@ public abstract class AbstractConfigurableCacheFactoryBean extends AbstractBasic * into the {@link GemFireCache}. * @see org.apache.geode.cache.GemFireCache#loadCacheXml(InputStream) * @see org.apache.geode.cache.GemFireCache + * @see #getOptionalCacheXml() */ protected @NonNull T loadCacheXml(@NonNull T cache) { diff --git a/spring-data-geode/src/main/java/org/springframework/data/gemfire/AbstractResolvableCacheFactoryBean.java b/spring-data-geode/src/main/java/org/springframework/data/gemfire/AbstractResolvableCacheFactoryBean.java index 8c24b7b9..9ce248dc 100644 --- a/spring-data-geode/src/main/java/org/springframework/data/gemfire/AbstractResolvableCacheFactoryBean.java +++ b/spring-data-geode/src/main/java/org/springframework/data/gemfire/AbstractResolvableCacheFactoryBean.java @@ -29,7 +29,7 @@ import org.apache.geode.distributed.DistributedSystem; import org.springframework.lang.NonNull; /** - * Abstract base class encapsulating logic to resolve or create a {@link GemFireCache cache} instance. + * Abstract base class encapsulating logic to resolve or create a {@link GemFireCache} instance. * * @author John Blum * @see java.util.Properties diff --git a/spring-data-geode/src/main/java/org/springframework/data/gemfire/CacheFactoryBean.java b/spring-data-geode/src/main/java/org/springframework/data/gemfire/CacheFactoryBean.java index d16bb271..6a49039e 100644 --- a/spring-data-geode/src/main/java/org/springframework/data/gemfire/CacheFactoryBean.java +++ b/spring-data-geode/src/main/java/org/springframework/data/gemfire/CacheFactoryBean.java @@ -75,10 +75,10 @@ public class CacheFactoryBean extends AbstractResolvableCacheFactoryBean { private Integer messageSyncInterval; private Integer searchTimeout; - private final List peerCacheConfigurers = new ArrayList<>(); - private List jndiDataSources; + private final List peerCacheConfigurers = new ArrayList<>(); + private final PeerCacheConfigurer compositePeerCacheConfigurer = (beanName, bean) -> nullSafeList(peerCacheConfigurers).forEach(peerCacheConfigurer -> peerCacheConfigurer.configure(beanName, bean)); @@ -174,7 +174,7 @@ public class CacheFactoryBean extends AbstractResolvableCacheFactoryBean { * * @param factory {@link CacheFactory} used to create the {@link Cache}. * @return the configured {@link CacheFactory}. - * @see #configurePdx(org.springframework.data.gemfire.AbstractPdxConfigurableCacheFactoryBean.PdxConfigurer) + * @see #configurePdx(CacheFactory) * @see #configureSecurity(CacheFactory) * @see org.apache.geode.cache.CacheFactory */ @@ -286,10 +286,10 @@ public class CacheFactoryBean extends AbstractResolvableCacheFactoryBean { } /** - * Returns a reference to the Composite {@link PeerCacheConfigurer} used to apply additional configuration - * to this {@link CacheFactoryBean} on Spring container initialization. + * Returns a reference to the {@literal Composite} {@link PeerCacheConfigurer} used to + * apply additional configuration to this {@link CacheFactoryBean} during Spring container initialization. * - * @return the Composite {@link PeerCacheConfigurer}. + * @return the {@literal Composite} {@link PeerCacheConfigurer}. * @see org.springframework.data.gemfire.config.annotation.PeerCacheConfigurer */ public @NonNull PeerCacheConfigurer getCompositePeerCacheConfigurer() { diff --git a/spring-data-geode/src/main/java/org/springframework/data/gemfire/client/ClientCacheFactoryBean.java b/spring-data-geode/src/main/java/org/springframework/data/gemfire/client/ClientCacheFactoryBean.java index 8ad14ca1..02624648 100644 --- a/spring-data-geode/src/main/java/org/springframework/data/gemfire/client/ClientCacheFactoryBean.java +++ b/spring-data-geode/src/main/java/org/springframework/data/gemfire/client/ClientCacheFactoryBean.java @@ -197,7 +197,7 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat * @see org.springframework.beans.factory.FactoryBean#getObjectType() */ @Override - public Class doGetObjectType() { + protected Class doGetObjectType() { return ClientCache.class; } @@ -411,7 +411,7 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat } /** - * Inform the Pivotal GemFire/Apache Geode cluster that this cache client is ready to receive events + * Inform the Apache Geode cluster that this {@link ClientCache} is ready to receive events * iff the client is non-durable. * * @param event {@link ApplicationContextEvent} fired when the {@link ApplicationContext} is refreshed. @@ -465,8 +465,8 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat * Null-safe operation to set an array of {@link ClientCacheConfigurer ClientCacheConfigurers} used to apply * additional configuration to this {@link ClientCacheFactoryBean} when using Annotation-based configuration. * - * @param clientCacheConfigurers array of {@link ClientCacheConfigurer ClientCacheConfigurers} used to apply - * additional configuration to this {@link ClientCacheFactoryBean}. + * @param clientCacheConfigurers array of {@link ClientCacheConfigurer ClientCacheConfigurers} used to + * apply additional configuration to this {@link ClientCacheFactoryBean}. * @see org.springframework.data.gemfire.config.annotation.ClientCacheConfigurer * @see #setClientCacheConfigurers(List) */ @@ -475,25 +475,26 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat } /** - * Null-safe operation to set an {@link Iterable} of {@link ClientCacheConfigurer ClientCacheConfigurers} to apply + * Null-safe operation to set an {@link List} of {@link ClientCacheConfigurer ClientCacheConfigurers} to apply * additional configuration to this {@link ClientCacheFactoryBean} when using Annotation-based configuration. * - * @param peerCacheConfigurers {@link Iterable} of {@link ClientCacheConfigurer ClientCacheConfigurers} used to apply - * additional configuration to this {@link ClientCacheFactoryBean}. + * @param clientCacheConfigurers {@link List} of {@link ClientCacheConfigurer ClientCacheConfigurers} used to + * apply additional configuration to this {@link ClientCacheFactoryBean}. * @see org.springframework.data.gemfire.config.annotation.ClientCacheConfigurer + * @see #setClientCacheConfigurers(ClientCacheConfigurer...) */ - public void setClientCacheConfigurers(List peerCacheConfigurers) { - this.clientCacheConfigurers = peerCacheConfigurers != null ? peerCacheConfigurers : Collections.emptyList(); + public void setClientCacheConfigurers(List clientCacheConfigurers) { + this.clientCacheConfigurers = clientCacheConfigurers != null ? clientCacheConfigurers : Collections.emptyList(); } /** - * Returns a reference to the Composite {@link ClientCacheConfigurer} used to apply additional configuration - * to this {@link ClientCacheFactoryBean} on Spring container initialization. + * Returns a reference to the {@literal Composite} {@link ClientCacheConfigurer} used to apply additional + * configuration to this {@link ClientCacheFactoryBean} on Spring container initialization. * - * @return the Composite {@link ClientCacheConfigurer}. + * @return the {@literal Composite} {@link ClientCacheConfigurer}. * @see org.springframework.data.gemfire.config.annotation.ClientCacheConfigurer */ - public ClientCacheConfigurer getCompositeClientCacheConfigurer() { + public @NonNull ClientCacheConfigurer getCompositeClientCacheConfigurer() { return this.compositeClientCacheConfigurer; }