diff --git a/src/main/java/org/springframework/data/gemfire/RegionFactoryBean.java b/src/main/java/org/springframework/data/gemfire/RegionFactoryBean.java index 72962e45..0e9496cf 100644 --- a/src/main/java/org/springframework/data/gemfire/RegionFactoryBean.java +++ b/src/main/java/org/springframework/data/gemfire/RegionFactoryBean.java @@ -28,9 +28,12 @@ import org.apache.geode.cache.Cache; import org.apache.geode.cache.CacheListener; import org.apache.geode.cache.CacheLoader; import org.apache.geode.cache.CacheWriter; +import org.apache.geode.cache.CustomExpiry; import org.apache.geode.cache.DataPolicy; +import org.apache.geode.cache.DiskStore; import org.apache.geode.cache.EvictionAction; import org.apache.geode.cache.EvictionAttributes; +import org.apache.geode.cache.ExpirationAttributes; import org.apache.geode.cache.GemFireCache; import org.apache.geode.cache.PartitionAttributes; import org.apache.geode.cache.PartitionAttributesFactory; @@ -48,6 +51,8 @@ import org.springframework.beans.factory.FactoryBean; import org.springframework.context.SmartLifecycle; import org.springframework.core.io.Resource; import org.springframework.data.gemfire.client.ClientRegionFactoryBean; +import org.springframework.data.gemfire.eviction.EvictingRegionFactoryBean; +import org.springframework.data.gemfire.expiration.ExpiringRegionFactoryBean; import org.springframework.data.gemfire.util.RegionUtils; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; @@ -85,9 +90,9 @@ import org.springframework.util.StringUtils; * @see org.springframework.data.gemfire.config.annotation.RegionConfigurer */ @SuppressWarnings("unused") -// TODO: Rename to PeerRegionFatoryBean in SD Lovelace +// TODO: Rename to PeerRegionFactoryBean in SD Lovelace public abstract class RegionFactoryBean extends ConfigurableRegionFactoryBean - implements DisposableBean, SmartLifecycle { + implements EvictingRegionFactoryBean, ExpiringRegionFactoryBean, DisposableBean, SmartLifecycle { private boolean close = true; private boolean destroy = false; @@ -95,6 +100,7 @@ public abstract class RegionFactoryBean extends ConfigurableRegionFactoryB private Boolean offHeap; private Boolean persistent; + private Boolean statisticsEnabled; private AsyncEventQueue[] asyncEventQueues; @@ -109,10 +115,18 @@ public abstract class RegionFactoryBean extends ConfigurableRegionFactoryB private Compressor compressor; + private CustomExpiry customEntryIdleTimeout; + private CustomExpiry customEntryTimeToLive; + private DataPolicy dataPolicy; private EvictionAttributes evictionAttributes; + private ExpirationAttributes entryIdleTimeout; + private ExpirationAttributes entryTimeToLive; + private ExpirationAttributes regionIdleTimeout; + private ExpirationAttributes regionTimeToLive; + private GatewaySender[] gatewaySenders; private RegionAttributes attributes; @@ -236,6 +250,8 @@ public abstract class RegionFactoryBean extends ConfigurableRegionFactoryB */ protected RegionFactory configure(RegionFactory regionFactory) { + regionFactory.setStatisticsEnabled(resolveStatisticsEnabled()); + stream(nullSafeArray(this.asyncEventQueues, AsyncEventQueue.class)) .forEach(asyncEventQueue -> regionFactory.addAsyncEventQueueId(asyncEventQueue.getId())); @@ -247,12 +263,20 @@ public abstract class RegionFactoryBean extends ConfigurableRegionFactoryB Optional.ofNullable(this.compressor).ifPresent(regionFactory::setCompressor); + Optional.ofNullable(this.customEntryIdleTimeout).ifPresent(regionFactory::setCustomEntryIdleTimeout); + + Optional.ofNullable(this.customEntryTimeToLive).ifPresent(regionFactory::setCustomEntryTimeToLive); + resolveDataPolicy(regionFactory, this.persistent, this.dataPolicy); Optional.ofNullable(this.diskStoreName) .filter(name -> isDiskStoreConfigurationAllowed()) .ifPresent(regionFactory::setDiskStoreName); + Optional.ofNullable(this.entryIdleTimeout).ifPresent(regionFactory::setEntryIdleTimeout); + + Optional.ofNullable(this.entryTimeToLive).ifPresent(regionFactory::setEntryTimeToLive); + Optional.ofNullable(this.evictionAttributes).ifPresent(regionFactory::setEvictionAttributes); stream(nullSafeArray(this.gatewaySenders, GatewaySender.class)) @@ -260,6 +284,10 @@ public abstract class RegionFactoryBean extends ConfigurableRegionFactoryB Optional.ofNullable(this.keyConstraint).ifPresent(regionFactory::setKeyConstraint); + Optional.ofNullable(this.regionIdleTimeout).ifPresent(regionFactory::setRegionIdleTimeout); + + Optional.ofNullable(this.regionTimeToLive).ifPresent(regionFactory::setRegionTimeToLive); + Optional.ofNullable(getScope()).ifPresent(regionFactory::setScope); Optional.ofNullable(this.valueConstraint).ifPresent(regionFactory::setValueConstraint); @@ -391,9 +419,13 @@ public abstract class RegionFactoryBean extends ConfigurableRegionFactoryB } /** + * Merges the {@link RegionAttributes} into the {@link RegionFactory}. * - * @param regionFactory - * @param regionAttributes + * @param regionFactory {@link RegionFactory} to configure. + * @param regionAttributes {@link RegionAttributes} used to configure the {@link RegionFactory} + * if not {@literal null}. + * @see org.apache.geode.cache.RegionAttributes + * @see org.apache.geode.cache.RegionFactory */ protected void mergePartitionAttributes(RegionFactory regionFactory, RegionAttributes regionAttributes) { @@ -560,8 +592,10 @@ public abstract class RegionFactoryBean extends ConfigurableRegionFactoryB /** * Closes and destroys the {@link Region}. * - * @throws Exception if destroy fails. + * @throws Exception if {@code destroy()} fails. * @see org.springframework.beans.factory.DisposableBean + * @see org.apache.geode.cache.Region#close() + * @see org.apache.geode.cache.Region#destroyRegion() */ @Override public void destroy() throws Exception { @@ -585,30 +619,34 @@ public abstract class RegionFactoryBean extends ConfigurableRegionFactoryB } /** - * The list of AsyncEventQueues to use with this Region. + * Configures an array of {@link AsyncEventQueue AsyncEventQueues} for this {@link Region} used to perform + * asynchronous data access operations, e.g. {@literal asynchronous write-behind}. * - * @param asyncEventQueues defined as Object for backwards compatibility with Gemfire 6. + * @param asyncEventQueues array of {@link AsyncEventQueue AsyncEventQueues} used by this {@link Region} + * to perform asynchronous data access operations. + * @see org.apache.geode.cache.asyncqueue.AsyncEventQueue */ public void setAsyncEventQueues(AsyncEventQueue[] asyncEventQueues) { this.asyncEventQueues = asyncEventQueues; } /** - * Sets the region attributes used for the region used by this factory. - * Allows maximum control in specifying the region settings. Used only when - * a new region is created. + * Sets the {@link RegionAttributes} used to configure this {@link Region}. * - * @param attributes the attributes to set on a newly created region + * Specifying {@link RegionAttributes} allows maximum control in specifying various {@link Region} settings. + * Used only when the {@link Region} is created and not when the {@link Region} is looked up. + * + * @param attributes {@link RegionAttributes} used to configure this {@link Region}. + * @see org.apache.geode.cache.RegionAttributes */ public void setAttributes(RegionAttributes attributes) { this.attributes = attributes; } /** - * Returns the attributes used to configure the Region created by this factory as set in the SDG XML namespace - * configuration meta-data, or as set with the setAttributes(:Attributes) method. + * Returns the {@link RegionAttributes} used to configure this {@link Region}. * - * @return the RegionAttributes used to configure the Region created by this factory. + * @return the {@link RegionAttributes} used to configure this {@link Region}. * @see org.apache.geode.cache.RegionAttributes */ public RegionAttributes getAttributes() { @@ -616,42 +654,58 @@ public abstract class RegionFactoryBean extends ConfigurableRegionFactoryB } /** - * Sets the cache listeners used for the region used by this factory. Used - * only when a new region is created.Overrides the settings specified - * through {@link #setAttributes(RegionAttributes)}. + * Configures {@link CacheListener CacheListeners} used to listen for entry events on this {@link Region}. * - * @param cacheListeners the cacheListeners to set on a newly created region + * Used only when a new {@link Region} is created and not {@link #isLookupEnabled() looked up}. + * + * Overrides the {@link Region} settings specified in {@link RegionAttributes} + * set with {@link #setAttributes(RegionAttributes)}. + * + * @param cacheListeners array {@link CacheListener CacheListeners} to register with this {@link Region}. + * @see org.apache.geode.cache.CacheListener */ public void setCacheListeners(CacheListener[] cacheListeners) { this.cacheListeners = cacheListeners; } /** - * Sets the cache loader used for the region used by this factory. Used only - * when a new region is created.Overrides the settings specified through - * {@link #setAttributes(RegionAttributes)}. + * Configures the {@link CacheLoader} used by this {@link Region} to perform {@literal synchronous read-through} + * data access operations to an underlying, external data source. * - * @param cacheLoader the cacheLoader to set on a newly created region + * Used only when a new {@link Region} is created and not {@link #isLookupEnabled() looked up}. + * + * Overrides the {@link Region} settings specified in {@link RegionAttributes} + * set with {@link #setAttributes(RegionAttributes)}. + * + * @param cacheLoader {@link CacheLoader} to register for this {@link Region}. + * @see org.apache.geode.cache.CacheLoader */ public void setCacheLoader(CacheLoader cacheLoader) { this.cacheLoader = cacheLoader; } /** - * Sets the cache writer used for the region used by this factory. Used only - * when a new region is created. Overrides the settings specified through - * {@link #setAttributes(RegionAttributes)}. + * Configures the {@link CacheWriter} used by this {@link Region} to perform {@literal synchronous write-through} + * data access operations to an underlying, external data source. * - * @param cacheWriter the cacheWriter to set on a newly created region + * Used only when a new {@link Region} is created and not {@link #isLookupEnabled() looked up}. + * + * Overrides the {@link Region} settings specified in {@link RegionAttributes} + * set with {@link #setAttributes(RegionAttributes)}. + * + * @param cacheWriter {@link CacheWriter} to register for this {@link Region}. + * @see org.apache.geode.cache.CacheWriter */ public void setCacheWriter(CacheWriter cacheWriter) { this.cacheWriter = cacheWriter; } /** - * Indicates whether the Region referred to by this factory bean will be closed on shutdown (default true). + * Configure whether to close this {@literal Region} during shutdown. * - * @param close a boolean value indicating whether this Region should be closed on member shutdown. + * Defaults to {@literal true}. + * + * @param close boolean value indicating whether this {@link Region} should be closed during shutdown. * @see #setDestroy(boolean) */ public void setClose(boolean close) { @@ -659,29 +713,40 @@ public abstract class RegionFactoryBean extends ConfigurableRegionFactoryB } /** - * Configures the {@link Compressor} used to compress the this {@link Region Region's} data. + * Configures the {@link Compressor} used to compress this {@link Region Region's} data. * - * @param compressor {@link Compressor} used to compress the this {@link Region Region's} data. + * @param compressor {@link Compressor} used to compress this {@link Region Region's} data. * @see org.apache.geode.compression.Compressor */ public void setCompressor(Compressor compressor) { this.compressor = compressor; } + public void setCustomEntryIdleTimeout(CustomExpiry customEntryIdleTimeout) { + this.customEntryIdleTimeout = customEntryIdleTimeout; + } + + public void setCustomEntryTimeToLive(CustomExpiry customEntryTimeToLive) { + this.customEntryTimeToLive = customEntryTimeToLive; + } + /** - * Indicates whether the Region referred to by this factory bean will be destroyed on shutdown (default false). + * Configure whether to destroy this {@link Region} during shutdown. * - * @param destroy a boolean value indicating whether the Region is to be destroy on member shutdown. - * @see #setDestroy(boolean) + * Defaults to {@literal false}. + * + * @param destroy value indicating whether this {@link Region} should be destroyed during shutdown. + * @see #setClose(boolean) */ public void setDestroy(boolean destroy) { this.destroy = destroy; } /** - * Sets the DataPolicy of the Region. + * Configure the {@link DataPolicy} for this {@link Region}. * - * @param dataPolicy the GemFire DataPolicy to use when configuring the Region. + * @param dataPolicy {@link DataPolicy} used when configuring this {@link Region}. + * @see org.apache.geode.cache.DataPolicy * @since 1.4.0 */ public void setDataPolicy(DataPolicy dataPolicy) { @@ -689,11 +754,12 @@ public abstract class RegionFactoryBean extends ConfigurableRegionFactoryB } /** - * Sets the DataPolicy of the Region as a String. + * Configures the {@link DataPolicy} for this {@link Region} as a {@link String}. * - * @param dataPolicyName the name of the DataPolicy (e.g. REPLICATE, PARTITION) + * @param dataPolicyName {@link String} containing the name of the {@link DataPolicy}, + * (e.g. {@literal PARTITION} or {@literal REPLICATE}, etc). * @see #setDataPolicy(org.apache.geode.cache.DataPolicy) - * @deprecated as of 1.4.0, use setDataPolicy(:DataPolicy) instead. + * @deprecated as of 1.4.0; use setDataPolicy(:DataPolicy) instead. */ @Deprecated public void setDataPolicy(String dataPolicyName) { @@ -701,10 +767,12 @@ public abstract class RegionFactoryBean extends ConfigurableRegionFactoryB } /** - * Gets the "resolved" Data Policy as determined by this RegionFactory when configuring the attributes - * of the Region to be created. + * Returns resolved {@link DataPolicy} as configured with the {@link RegionFactory} + * when creating this {@link Region}. * - * @return the "resolved" Data Policy to be used to create the Region. + * @return the configured, resolved {@link DataPolicy} used by this {@link Region}. + * @throws IllegalStateException if the {@link DataPolicy} has not been configured + * or is not resolvable. * @see org.apache.geode.cache.DataPolicy */ public DataPolicy getDataPolicy() { @@ -713,31 +781,47 @@ public abstract class RegionFactoryBean extends ConfigurableRegionFactoryB } /** - * Sets the name of Disk Store used for either overflow or persistence, or both. + * Configures the {@link String name} of the {@link DiskStore} used by this {@link Region} + * for overflow and/or persistence. * - * @param diskStoreName the name of the Disk Store bean in context used for overflow/persistence. + * @param diskStoreName {@link String} containing the name of the {@link DiskStore} bean + * configured for this {@link Region}. */ public void setDiskStoreName(String diskStoreName) { this.diskStoreName = diskStoreName; } + // TODO: review/add Javadoc from here forward... + + public void setEntryIdleTimeout(ExpirationAttributes entryIdleTimeout) { + this.entryIdleTimeout = entryIdleTimeout; + } + + public void setEntryTimeToLive(ExpirationAttributes entryTimeToLive) { + this.entryTimeToLive = entryTimeToLive; + } + public void setEvictionAttributes(EvictionAttributes evictionAttributes) { this.evictionAttributes = evictionAttributes; } /** + * Configures the {@link GatewaySender GatewaySenders} used to send data and events from this {@link Region} + * to a corresponding {@link Region} in a remote cluster/site. * - * @param gatewaySenders defined as Object for backward compatibility with - * Gemfire 6 + * @param gatewaySenders {@link GatewaySender GatewaySenders} used to send data and events from this {@link Region} + * to a corresponding {@link Region} in a remote cluster/site. + * @see org.apache.geode.cache.wan.GatewaySender */ public void setGatewaySenders(GatewaySender[] gatewaySenders) { this.gatewaySenders = gatewaySenders; } /** - * Sets whether to enable this {@link Region} to store it's data in off-heap memory. + * Configures whether to enable this {@link Region} with the ability to store data in {@literal off-heap memory}. * - * @param offHeap Boolean value indicating whether to enable off-heap memory for this Region. + * @param offHeap {@link Boolean} value indicating whether to enable {@literal off-heap memory} + * for this {@link Region}. * @see org.apache.geode.cache.RegionFactory#setOffHeap(boolean) */ public void setOffHeap(Boolean offHeap) { @@ -745,64 +829,139 @@ public abstract class RegionFactoryBean extends ConfigurableRegionFactoryB } /** - * Returns a {@link Boolean} value indicating whether off-heap memory was enabled for this {@link Region}. - * Off-heap will be enabled if this method returns a non-{@literal null} {@link Boolean} value that evaluates - * to {@literal true}. + * Returns a {@link Boolean} value indicating whether {@literal off-heap memory} was enabled for this {@link Region}. * - * @return a {@link Boolean} value indicating whether off-heap is enabled for this {@link Region}. + * {@literal Off-heap memory} will be enabled if this method returns a {@literal non-null} {@link Boolean} value + * evaluating to {@literal true}. + * + * @return a {@link Boolean} value indicating whether {@literal off-heap memory} is enabled for this {@link Region}. */ public Boolean getOffHeap() { return this.offHeap; } /** - * Returns a boolean value indicating whether off-heap has been enabled for this {@link Region}. + * Returns a boolean value indicating whether {@literal off-heap memory} has been enabled for this {@link Region}. * - * @return a {@literal boolean} value indicating whether off-heap has been enabled for this {@link Region}. + * @return a {@literal boolean} value indicating whether {@literal off-heap memory} has been enabled + * for this {@link Region}. * @see #getOffHeap() */ public boolean isOffHeap() { return Boolean.TRUE.equals(getOffHeap()); } + /** + * Configures the {@link Class key constraint} used to enforce key {@link Class types} for this {@link Region}. + * + * @param keyConstraint {@link Class} specifying the key type constraint for this {@link Region}. + * @see org.apache.geode.cache.RegionFactory#setKeyConstraint(Class) + * @see org.apache.geode.cache.RegionAttributes#getKeyConstraint() + * @see java.lang.Class + */ public void setKeyConstraint(Class keyConstraint) { this.keyConstraint = keyConstraint; } + /** + * Configures whether to enable {@literal persistence} for this {@link Region}. + * + * When {@literal persistence} is enable, then data in the {@link Region} is persisted to disk + * using the configured, specified {@link DiskStore}, or the {@literal DEFAULT} {@link DiskStore} + * if a {@link DiskStore} was not explicitly configured. + * + * @param persistent {@link Boolean} value indicating whether to enaable {@literal persistence} + * for this {@link Region}. + */ public void setPersistent(Boolean persistent) { this.persistent = persistent; } - public Scope getScope() { - return this.scope; + public void setRegionIdleTimeout(ExpirationAttributes regionIdleTimeout) { + this.regionIdleTimeout = regionIdleTimeout; + } + + public void setRegionTimeToLive(ExpirationAttributes regionTimeToLive) { + this.regionTimeToLive = regionTimeToLive; } /** - * Sets the region scope. Used only when a new region is created. Overrides - * the settings specified through {@link #setAttributes(RegionAttributes)}. + * Configures the {@link Region Region's} {@link Scope}, which affects data distribution + * and acknowledgement strategy (useful in consistency) for the {@link Region}. * - * @see Scope - * @param scope the region scope + * @param scope {@link Scope} used to configure the {@link Region Region's} data distribution + * and acknowledgement strategy. + * @see org.apache.geode.cache.Scope */ public void setScope(Scope scope) { this.scope = scope; } /** - * Configures the Region with a RegionShortcut. + * Returns the configured {@link Scope} of the {@link Region} affecting data distribution + * and acknowledgement strategy (useful in consistency) for the {@link Region}. * - * @param shortcut the RegionShortcut used to configure pre-defined default for the Region created - * by this FactoryBean. + * @return the configured {@link Scope} of the {@link Region}. + * @see org.apache.geode.cache.Scope + */ + public Scope getScope() { + return this.scope; + } + + /** + * Configures the {@link Region} with the given {@link RegionShortcut}. + * + * @param shortcut {@link RegionShortcut} used to configure pre-defined defaults for the {@link Region}. * @see org.apache.geode.cache.RegionShortcut */ public void setShortcut(RegionShortcut shortcut) { this.shortcut = shortcut; } - protected final RegionShortcut getShortcut() { - return shortcut; + /** + * Returns the configured {@link RegionShortcut}. + * + * @return the configured {@link RegionShortcut}. + * @see org.apache.geode.cache.RegionShortcut + */ + public RegionShortcut getShortcut() { + return this.shortcut; } + public void setStatisticsEnabled(Boolean statisticsEnabled) { + this.statisticsEnabled = statisticsEnabled; + } + + public Boolean getStatisticsEnabled() { + return this.statisticsEnabled; + } + + public boolean isStatisticsEnabled() { + return Boolean.TRUE.equals(getStatisticsEnabled()); + } + + protected boolean resolveStatisticsEnabled() { + + return isStatisticsEnabled() + || this.customEntryIdleTimeout != null + || this.customEntryTimeToLive != null + || this.entryIdleTimeout != null + || this.entryTimeToLive != null + || this.regionIdleTimeout != null + || this.regionTimeToLive != null + || Optional.ofNullable(getAttributes()) + .map(RegionAttributes::getStatisticsEnabled) + .orElse(false); + } + + /** + * Configures the {@link Class value constraint} used to enforce value {@link Class types} for this {@link Region}. + * + * @param valueConstraint {@link Class} specifying the value type constraint for this {@link Region}. + * @see org.apache.geode.cache.RegionFactory#setValueConstraint(Class) + * @see org.apache.geode.cache.RegionAttributes#getValueConstraint() + * @see java.lang.Class + */ public void setValueConstraint(Class valueConstraint) { this.valueConstraint = valueConstraint; } diff --git a/src/main/java/org/springframework/data/gemfire/client/ClientRegionFactoryBean.java b/src/main/java/org/springframework/data/gemfire/client/ClientRegionFactoryBean.java index 27e7d5a6..b9ea6be2 100644 --- a/src/main/java/org/springframework/data/gemfire/client/ClientRegionFactoryBean.java +++ b/src/main/java/org/springframework/data/gemfire/client/ClientRegionFactoryBean.java @@ -50,6 +50,8 @@ import org.springframework.data.gemfire.GemfireUtils; import org.springframework.data.gemfire.RegionLookupFactoryBean; import org.springframework.data.gemfire.config.annotation.RegionConfigurer; import org.springframework.data.gemfire.config.xml.GemfireConstants; +import org.springframework.data.gemfire.eviction.EvictingRegionFactoryBean; +import org.springframework.data.gemfire.expiration.ExpiringRegionFactoryBean; import org.springframework.data.gemfire.util.RegionUtils; import org.springframework.data.gemfire.util.SpringUtils; import org.springframework.util.Assert; @@ -77,7 +79,8 @@ import org.springframework.util.StringUtils; * @see org.springframework.data.gemfire.config.annotation.RegionConfigurer */ @SuppressWarnings("unused") -public class ClientRegionFactoryBean extends ConfigurableRegionFactoryBean implements DisposableBean { +public class ClientRegionFactoryBean extends ConfigurableRegionFactoryBean + implements EvictingRegionFactoryBean, ExpiringRegionFactoryBean, DisposableBean { public static final String DEFAULT_POOL_NAME = "DEFAULT"; public static final String GEMFIRE_POOL_NAME = GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME; @@ -306,6 +309,8 @@ public class ClientRegionFactoryBean extends ConfigurableRegionFactoryBean stream(nullSafeArray(this.cacheListeners, CacheListener.class)).forEach(clientRegionFactory::addCacheListener); + clientRegionFactory.setStatisticsEnabled(resolveStatisticsEnabled()); + Optional.ofNullable(this.cloningEnabled).ifPresent(clientRegionFactory::setCloningEnabled); Optional.ofNullable(this.compressor).ifPresent(clientRegionFactory::setCompressor); Optional.ofNullable(this.concurrencyChecksEnabled).ifPresent(clientRegionFactory::setConcurrencyChecksEnabled); @@ -326,7 +331,6 @@ public class ClientRegionFactoryBean extends ConfigurableRegionFactoryBean Optional.ofNullable(this.regionIdleTimeout).ifPresent(clientRegionFactory::setRegionIdleTimeout); Optional.ofNullable(this.regionTimeToLive).ifPresent(clientRegionFactory::setRegionTimeToLive); - Optional.ofNullable(this.statisticsEnabled).ifPresent(clientRegionFactory::setStatisticsEnabled); Optional.ofNullable(this.valueConstraint).ifPresent(clientRegionFactory::setValueConstraint); return clientRegionFactory; @@ -724,6 +728,28 @@ public class ClientRegionFactoryBean extends ConfigurableRegionFactoryBean this.statisticsEnabled = statisticsEnabled; } + public Boolean getStatisticsEnabled() { + return this.statisticsEnabled; + } + + public boolean isStatisticsEnabled() { + return Boolean.TRUE.equals(getStatisticsEnabled()); + } + + protected boolean resolveStatisticsEnabled() { + + return isStatisticsEnabled() + || this.customEntryIdleTimeout != null + || this.customEntryTimeToLive != null + || this.entryIdleTimeout != null + || this.entryTimeToLive != null + || this.regionIdleTimeout != null + || this.regionTimeToLive != null + || Optional.ofNullable(getAttributes()) + .map(RegionAttributes::getStatisticsEnabled) + .orElse(false); + } + /** * Sets a {@link Class type} constraint on this {@link Region client Region's} values. * diff --git a/src/main/java/org/springframework/data/gemfire/config/annotation/EnableEviction.java b/src/main/java/org/springframework/data/gemfire/config/annotation/EnableEviction.java index 5069e8aa..6005d898 100644 --- a/src/main/java/org/springframework/data/gemfire/config/annotation/EnableEviction.java +++ b/src/main/java/org/springframework/data/gemfire/config/annotation/EnableEviction.java @@ -27,17 +27,23 @@ import java.lang.annotation.Target; import org.apache.geode.cache.EvictionAttributes; import org.apache.geode.cache.Region; import org.apache.geode.cache.util.ObjectSizer; +import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.data.gemfire.eviction.EvictionActionType; import org.springframework.data.gemfire.eviction.EvictionPolicyType; /** - * The {@link EnableEviction} annotation marks a Spring {@link org.springframework.context.annotation.Configuration @Configuration} - * annotated class to enable {@link Region} Eviction. + * The {@link EnableEviction} annotation marks a Spring {@link Configuration @Configuration} annotated class + * to enable {@link Region} Eviction. * * @author John Blum + * @see org.apache.geode.cache.EvictionAttributes + * @see org.apache.geode.cache.Region + * @see org.apache.geode.cache.util.ObjectSizer * @see org.springframework.context.annotation.Import * @see org.springframework.data.gemfire.config.annotation.EvictionConfiguration + * @see org.springframework.data.gemfire.eviction.EvictionActionType + * @see org.springframework.data.gemfire.eviction.EvictionPolicyType * @see org.apache.geode.cache.Region * @since 1.9.0 */ diff --git a/src/main/java/org/springframework/data/gemfire/config/annotation/EnableExpiration.java b/src/main/java/org/springframework/data/gemfire/config/annotation/EnableExpiration.java index 5ed62781..d8b62773 100644 --- a/src/main/java/org/springframework/data/gemfire/config/annotation/EnableExpiration.java +++ b/src/main/java/org/springframework/data/gemfire/config/annotation/EnableExpiration.java @@ -39,12 +39,13 @@ import org.springframework.data.gemfire.expiration.TimeToLiveExpiration; * cover {@link Region} expiration; {@link Region} expiration must be configure on the {@link Region} definition itself. * * @author John Blum + * @see org.apache.geode.cache.Region * @see org.springframework.context.annotation.Import * @see org.springframework.data.gemfire.config.annotation.ExpirationConfiguration - * @see Expiration - * @see IdleTimeoutExpiration - * @see TimeToLiveExpiration - * @see org.apache.geode.cache.Region + * @see org.springframework.data.gemfire.expiration.Expiration + * @see org.springframework.data.gemfire.expiration.ExpirationActionType + * @see org.springframework.data.gemfire.expiration.IdleTimeoutExpiration + * @see org.springframework.data.gemfire.expiration.TimeToLiveExpiration * @see Annotation-based Data Expiration * @see GemFire Expiration * @see Geode Expiration @@ -117,7 +118,7 @@ public @interface EnableExpiration { * Types of Expiration algorithms (Idle Timeout (TTI) or Time to Live (TTL)) configured and used by * {@link Region Region(s)} to expire entries. * - * Defaults to both Idle Timeout (TTI). + * Defaults to Idle Timeout (TTI). * * @see org.springframework.data.gemfire.config.annotation.EnableExpiration.ExpirationType */ @@ -150,6 +151,7 @@ public @interface EnableExpiration { * @see #abbreviation() */ static ExpirationType valueOfAbbreviation(String abbreviation) { + for (ExpirationType expirationType : values()) { if (expirationType.abbreviation().equalsIgnoreCase(abbreviation)) { return expirationType; diff --git a/src/main/java/org/springframework/data/gemfire/config/annotation/EvictionConfiguration.java b/src/main/java/org/springframework/data/gemfire/config/annotation/EvictionConfiguration.java index b3af7f0a..42695e12 100644 --- a/src/main/java/org/springframework/data/gemfire/config/annotation/EvictionConfiguration.java +++ b/src/main/java/org/springframework/data/gemfire/config/annotation/EvictionConfiguration.java @@ -27,7 +27,6 @@ import java.lang.annotation.Annotation; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; -import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.function.Supplier; @@ -48,6 +47,8 @@ import org.springframework.core.type.AnnotationMetadata; import org.springframework.data.gemfire.RegionFactoryBean; import org.springframework.data.gemfire.RegionLookupFactoryBean; import org.springframework.data.gemfire.client.ClientRegionFactoryBean; +import org.springframework.data.gemfire.config.annotation.support.AbstractAnnotationConfigSupport; +import org.springframework.data.gemfire.eviction.EvictingRegionFactoryBean; import org.springframework.data.gemfire.eviction.EvictionActionType; import org.springframework.data.gemfire.eviction.EvictionAttributesFactoryBean; import org.springframework.data.gemfire.eviction.EvictionPolicyType; @@ -64,17 +65,21 @@ import org.springframework.util.StringUtils; * @see org.springframework.context.annotation.Bean * @see org.springframework.context.annotation.Configuration * @see org.springframework.context.annotation.ImportAware - * @see EvictionActionType - * @see EvictionAttributesFactoryBean - * @see EvictionPolicyType * @see org.springframework.data.gemfire.RegionFactoryBean + * @see org.springframework.data.gemfire.RegionLookupFactoryBean * @see org.springframework.data.gemfire.client.ClientRegionFactoryBean + * @see org.springframework.data.gemfire.config.annotation.support.AbstractAnnotationConfigSupport + * @see org.springframework.data.gemfire.eviction.EvictionActionType + * @see org.springframework.data.gemfire.eviction.EvictionAttributesFactoryBean + * @see org.springframework.data.gemfire.eviction.EvictionPolicyType * @see org.apache.geode.cache.EvictionAttributes * @see org.apache.geode.cache.Region + * @see org.apache.geode.cache.util.ObjectSizer * @since 1.9.0 */ @Configuration -public class EvictionConfiguration implements ApplicationContextAware, ImportAware { +public class EvictionConfiguration extends AbstractAnnotationConfigSupport + implements ApplicationContextAware, ImportAware { private ApplicationContext applicationContext; @@ -87,33 +92,11 @@ public class EvictionConfiguration implements ApplicationContextAware, ImportAwa * @see java.lang.annotation.Annotation * @see java.lang.Class */ + @Override protected Class getAnnotationType() { return EnableEviction.class; } - /** - * Returns the name of the {@link Annotation} type that enables and configures Eviction. - * - * @return the name of the {@link Annotation} type that enables and configures Eviction. - * @see java.lang.Class#getName() - * @see #getAnnotationType() - */ - protected String getAnnotationTypeName() { - return getAnnotationType().getName(); - } - - /** - * Returns the simple name of the {@link Annotation} type that enables and configures Eviction. - * - * @return the simple name of the {@link Annotation} type that enables and configures Eviction. - * @see java.lang.Class#getSimpleName() - * @see #getAnnotationType() - */ - @SuppressWarnings("unused") - protected String getAnnotationTypeSimpleName() { - return getAnnotationType().getSimpleName(); - } - /** * Sets a reference to the Spring {@link ApplicationContext}. * @@ -127,36 +110,22 @@ public class EvictionConfiguration implements ApplicationContextAware, ImportAwa this.applicationContext = applicationContext; } - /** - * Determines whether the Spring bean is an instance of {@link RegionFactoryBean} - * or {@link ClientRegionFactoryBean}. - * - * @param bean Spring bean to evaluate. - * @return a boolean value indicating whether the Spring bean is an instance of {@link RegionFactoryBean} - * or the {@link ClientRegionFactoryBean}. - * @see org.springframework.data.gemfire.RegionFactoryBean - * @see org.springframework.data.gemfire.client.ClientRegionFactoryBean - */ - protected static boolean isRegionFactoryBean(Object bean) { - return (bean instanceof RegionFactoryBean || bean instanceof ClientRegionFactoryBean); - } - /** * @inheritDoc */ @Override public void setImportMetadata(AnnotationMetadata importMetadata) { - if (importMetadata.hasAnnotation(getAnnotationTypeName())) { - Map enableEvictionAttributes = - importMetadata.getAnnotationAttributes(getAnnotationTypeName()); + if (isAnnotationPresent(importMetadata)) { - AnnotationAttributes[] policies = (AnnotationAttributes[]) enableEvictionAttributes.get("policies"); + AnnotationAttributes enableEvictionAttributes = getAnnotationAttributes(importMetadata); + + AnnotationAttributes[] policies = enableEvictionAttributes.getAnnotationArray("policies"); for (AnnotationAttributes evictionPolicyAttributes : nullSafeArray(policies, AnnotationAttributes.class)) { - this.evictionPolicyConfigurer = ComposableEvictionPolicyConfigurer.compose( - this.evictionPolicyConfigurer, EvictionPolicyMetaData.from(evictionPolicyAttributes, - this.applicationContext)); + this.evictionPolicyConfigurer = ComposableEvictionPolicyConfigurer + .compose(this.evictionPolicyConfigurer, + EvictionPolicyMetaData.from(evictionPolicyAttributes, this.applicationContext)); } this.evictionPolicyConfigurer = Optional.ofNullable(this.evictionPolicyConfigurer) @@ -164,6 +133,19 @@ public class EvictionConfiguration implements ApplicationContextAware, ImportAwa } } + /** + * Determines whether the Spring bean is an instance of {@link EvictingRegionFactoryBean}. + * + * @param bean Spring bean to evaluate. + * @return a boolean value indicating whether the Spring bean is an instance of {@link EvictingRegionFactoryBean}. + * @see org.springframework.data.gemfire.eviction.EvictingRegionFactoryBean + * @see org.springframework.data.gemfire.client.ClientRegionFactoryBean + * @see org.springframework.data.gemfire.RegionFactoryBean + */ + protected static boolean isRegionFactoryBean(Object bean) { + return bean instanceof EvictingRegionFactoryBean; + } + /** * Returns a reference to the configured {@link EvictionPolicyConfigurer} used to configure the Eviction policy * of a {@link Region}. @@ -184,12 +166,7 @@ public class EvictionConfiguration implements ApplicationContextAware, ImportAwa @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { - return (isRegionFactoryBean(bean) ? getEvictionPolicyConfigurer().configure(bean) : bean); - } - - @Override - public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { - return bean; + return isRegionFactoryBean(bean) ? getEvictionPolicyConfigurer().configure(bean) : bean; } }; } @@ -271,7 +248,7 @@ public class EvictionConfiguration implements ApplicationContextAware, ImportAwa * multiple {@link EvictionPolicyConfigurer} objects using the Composite Software Design Pattern. */ protected static EvictionPolicyConfigurer compose(EvictionPolicyConfigurer one, EvictionPolicyConfigurer two) { - return (one == null ? two : (two == null ? one : new ComposableEvictionPolicyConfigurer(one, two))); + return one == null ? two : (two == null ? one : new ComposableEvictionPolicyConfigurer(one, two)); } /** @@ -291,7 +268,7 @@ public class EvictionConfiguration implements ApplicationContextAware, ImportAwa */ @Override public Object configure(Object regionFactoryBean) { - return two.configure(one.configure(regionFactoryBean)); + return this.two.configure(this.one.configure(regionFactoryBean)); } } @@ -418,7 +395,7 @@ public class EvictionConfiguration implements ApplicationContextAware, ImportAwa * @see #accepts(Supplier) */ protected boolean accepts(Object regionFactoryBean) { - return (isRegionFactoryBean(regionFactoryBean) && accepts(() -> resolveRegionName(regionFactoryBean))); + return isRegionFactoryBean(regionFactoryBean) && accepts(() -> resolveRegionName(regionFactoryBean)); } /** @@ -428,7 +405,7 @@ public class EvictionConfiguration implements ApplicationContextAware, ImportAwa * @return a boolean value if the named {@link Region} is accepted for Eviction policy configuration. */ protected boolean accepts(Supplier regionName) { - return (this.regionNames.isEmpty() || this.regionNames.contains(regionName.get())); + return this.regionNames.isEmpty() || this.regionNames.contains(regionName.get()); } /** @@ -439,8 +416,10 @@ public class EvictionConfiguration implements ApplicationContextAware, ImportAwa * @see org.springframework.data.gemfire.RegionLookupFactoryBean#resolveRegionName() */ protected String resolveRegionName(Object regionFactoryBean) { - return (regionFactoryBean instanceof RegionLookupFactoryBean - ? ((RegionLookupFactoryBean) regionFactoryBean).resolveRegionName() : null); + + return regionFactoryBean instanceof RegionLookupFactoryBean + ? ((RegionLookupFactoryBean) regionFactoryBean).resolveRegionName() + : null; } /** @@ -450,29 +429,23 @@ public class EvictionConfiguration implements ApplicationContextAware, ImportAwa * @param regionFactoryBean {@link RegionFactoryBean} or {@link ClientRegionFactoryBean} on which to * set the {@link EvictionAttributes} encapsulating the Eviction policy for the targeted {@link Region}. * @return the {@code regionFactoryBean}. - * @see org.springframework.data.gemfire.RegionFactoryBean#setEvictionAttributes(EvictionAttributes) - * @see org.springframework.data.gemfire.client.ClientRegionFactoryBean#setEvictionAttributes(EvictionAttributes) + * @see org.springframework.data.gemfire.eviction.EvictingRegionFactoryBean#setEvictionAttributes(EvictionAttributes) * @see org.apache.geode.cache.EvictionAttributes * @see #getEvictionAttributes() */ - protected Object setEvictionAttributes(Object regionFactoryBean) { + protected EvictingRegionFactoryBean setEvictionAttributes(EvictingRegionFactoryBean regionFactoryBean) { - if (regionFactoryBean instanceof RegionFactoryBean) { - ((RegionFactoryBean) regionFactoryBean).setEvictionAttributes(getEvictionAttributes()); - } - else { - ((ClientRegionFactoryBean) regionFactoryBean).setEvictionAttributes(getEvictionAttributes()); - } + regionFactoryBean.setEvictionAttributes(getEvictionAttributes()); return regionFactoryBean; } - /** - * @inheritDoc - */ @Override public Object configure(Object regionFactoryBean) { - return (accepts(regionFactoryBean) ? setEvictionAttributes(regionFactoryBean) : regionFactoryBean); + + return accepts(regionFactoryBean) + ? setEvictionAttributes((EvictingRegionFactoryBean) regionFactoryBean) + : regionFactoryBean; } } } diff --git a/src/main/java/org/springframework/data/gemfire/config/annotation/ExpirationConfiguration.java b/src/main/java/org/springframework/data/gemfire/config/annotation/ExpirationConfiguration.java index a453ce3e..1872b61a 100644 --- a/src/main/java/org/springframework/data/gemfire/config/annotation/ExpirationConfiguration.java +++ b/src/main/java/org/springframework/data/gemfire/config/annotation/ExpirationConfiguration.java @@ -26,11 +26,10 @@ import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newI import java.lang.annotation.Annotation; import java.util.Arrays; import java.util.HashSet; -import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.function.Supplier; -import org.apache.geode.cache.AttributesMutator; import org.apache.geode.cache.ExpirationAction; import org.apache.geode.cache.ExpirationAttributes; import org.apache.geode.cache.Region; @@ -41,8 +40,13 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.ImportAware; import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.type.AnnotationMetadata; +import org.springframework.data.gemfire.RegionFactoryBean; +import org.springframework.data.gemfire.RegionLookupFactoryBean; +import org.springframework.data.gemfire.client.ClientRegionFactoryBean; +import org.springframework.data.gemfire.config.annotation.support.AbstractAnnotationConfigSupport; import org.springframework.data.gemfire.expiration.AnnotationBasedExpiration; import org.springframework.data.gemfire.expiration.ExpirationActionType; +import org.springframework.data.gemfire.expiration.ExpiringRegionFactoryBean; import org.springframework.data.gemfire.util.CollectionUtils; import org.springframework.util.Assert; @@ -59,13 +63,16 @@ import org.springframework.util.Assert; * @since 1.9.0 */ @Configuration -public class ExpirationConfiguration implements ImportAware { +public class ExpirationConfiguration extends AbstractAnnotationConfigSupport implements ImportAware { protected static final int DEFAULT_TIMEOUT = 0; protected static final ExpirationActionType DEFAULT_ACTION = ExpirationActionType.DEFAULT; - protected static final ExpirationType[] DEFAULT_EXPIRATION_TYPES = { ExpirationType.IDLE_TIMEOUT }; + protected static final ExpirationType[] DEFAULT_EXPIRATION_TYPES = { + ExpirationType.IDLE_TIMEOUT, + ExpirationType.TIME_TO_LIVE, + }; private ExpirationPolicyConfigurer expirationPolicyConfigurer; @@ -80,46 +87,23 @@ public class ExpirationConfiguration implements ImportAware { return EnableExpiration.class; } - /** - * Returns the name of the {@link Annotation} type that enables and configures Expiration. - * - * @return the name of the {@link Annotation} type that enables and configures Expiration. - * @see java.lang.Class#getName() - * @see #getAnnotationType() - */ - protected String getAnnotationTypeName() { - return getAnnotationType().getName(); - } - - /** - * Returns the simple name of the {@link Annotation} type that enables and configures Expiration. - * - * @return the simple name of the {@link Annotation} type that enables and configures Expiration. - * @see java.lang.Class#getSimpleName() - * @see #getAnnotationType() - */ - @SuppressWarnings("unused") - protected String getAnnotationTypeSimpleName() { - return getAnnotationType().getSimpleName(); - } - /** * @inheritDoc */ @Override public void setImportMetadata(AnnotationMetadata importMetadata) { - if (importMetadata.hasAnnotation(getAnnotationTypeName())) { - Map enableExpirationAttributes = - importMetadata.getAnnotationAttributes(getAnnotationTypeName()); + if (isAnnotationPresent(importMetadata)) { - AnnotationAttributes[] policies = (AnnotationAttributes[]) enableExpirationAttributes.get("policies"); + AnnotationAttributes enableExpirationAttributes = getAnnotationAttributes(importMetadata); + + AnnotationAttributes[] policies = enableExpirationAttributes.getAnnotationArray("policies"); for (AnnotationAttributes expirationPolicyAttributes : nullSafeArray(policies, AnnotationAttributes.class)) { - this.expirationPolicyConfigurer = ComposableExpirationPolicyConfigurer.compose( - this.expirationPolicyConfigurer, ExpirationPolicyMetaData.from(expirationPolicyAttributes)); + this.expirationPolicyConfigurer = ComposableExpirationPolicyConfigurer + .compose(this.expirationPolicyConfigurer, ExpirationPolicyMetaData.from(expirationPolicyAttributes)); } this.expirationPolicyConfigurer = Optional.ofNullable(this.expirationPolicyConfigurer) @@ -128,19 +112,23 @@ public class ExpirationConfiguration implements ImportAware { } /** - * Determines whether the given bean is a {@link Region}. + * Determines whether the Spring bean is an instance of {@link ExpiringRegionFactoryBean} * - * @param bean {@link Object} to evaluate. - * @return a boolean value indicating whether the given bean is a {@link Region}. - * @see org.apache.geode.cache.Region + * @param bean Spring bean to evaluate. + * @return a boolean value indicating whether the Spring bean is an instance of {@link ExpiringRegionFactoryBean}. + * @see org.springframework.data.gemfire.expiration.ExpiringRegionFactoryBean + * @see org.springframework.data.gemfire.client.ClientRegionFactoryBean + * @see org.springframework.data.gemfire.RegionFactoryBean */ - protected boolean isRegion(Object bean) { - return (bean instanceof Region); + protected static boolean isRegionFactoryBean(Object bean) { + return bean instanceof ExpiringRegionFactoryBean; } protected ExpirationPolicyConfigurer getExpirationPolicyConfigurer() { - return Optional.ofNullable(this.expirationPolicyConfigurer).orElseThrow(() -> - newIllegalStateException("ExpirationPolicyConfigurer was not properly configured and initialized")); + + return Optional.ofNullable(this.expirationPolicyConfigurer) + .orElseThrow(() -> + newIllegalStateException("ExpirationPolicyConfigurer was not properly configured and initialized")); } @Bean @@ -149,16 +137,10 @@ public class ExpirationConfiguration implements ImportAware { return new BeanPostProcessor() { - @Override - public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { - return bean; - } - @Override @SuppressWarnings("unchecked") - public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { - return (isRegion(bean) ? getExpirationPolicyConfigurer().configure((Region) bean) - : bean); + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { + return isRegionFactoryBean(bean) ? getExpirationPolicyConfigurer().configure(bean) : bean; } }; } @@ -171,11 +153,11 @@ public class ExpirationConfiguration implements ImportAware { /** * Configures the expiration policy for the given {@link Region}. * - * @param region {@link Region} object who's expiration policy will be configured. + * @param regionFactoryBean {@link Region} object who's expiration policy will be configured. * @return the given {@link Region} object. * @see org.apache.geode.cache.Region */ - Object configure(Object region); + Object configure(Object regionFactoryBean); } @@ -235,7 +217,7 @@ public class ExpirationConfiguration implements ImportAware { protected static ExpirationPolicyConfigurer compose(ExpirationPolicyConfigurer one, ExpirationPolicyConfigurer two) { - return (one == null ? two : (two == null ? one : new ComposableExpirationPolicyConfigurer(one, two))); + return one == null ? two : (two == null ? one : new ComposableExpirationPolicyConfigurer(one, two)); } /** @@ -255,8 +237,8 @@ public class ExpirationConfiguration implements ImportAware { * @inheritDoc */ @Override - public Object configure(Object region) { - return this.two.configure(this.one.configure(region)); + public Object configure(Object regionFactoryBean) { + return this.two.configure(this.one.configure(regionFactoryBean)); } } @@ -452,15 +434,16 @@ public class ExpirationConfiguration implements ImportAware { } /** - * Determines whether to apply this expiration policy to the given {@link Region}. + * Determines whether the given {@link Object} (e.g. Spring bean) is accepted for Eviction policy configuration. * - * @param region {@link Region} to evaluate. - * @return a boolean value indicating whether the expiration policy applies to the given {@link Region}. - * @see org.apache.geode.cache.Region - * @see #accepts(String) + * @param regionFactoryBean {@link Object} being evaluated as an Eviction policy configuration candidate. + * @return a boolean value indicating whether the {@link Object} is accepted for Eviction policy configuration. + * @see #isRegionFactoryBean(Object) + * @see #resolveRegionName(Object) + * @see #accepts(Supplier) */ - protected boolean accepts(Object region) { - return (region instanceof Region && accepts(((Region) region).getName())); + protected boolean accepts(Object regionFactoryBean) { + return isRegionFactoryBean(regionFactoryBean) && accepts(() -> resolveRegionName(regionFactoryBean)); } /** @@ -470,8 +453,8 @@ public class ExpirationConfiguration implements ImportAware { * @return a boolean value indicating whether the expiration policy applies to the given {@link Region} * identified by name. */ - protected boolean accepts(String regionName) { - return (this.regionNames.isEmpty() || this.regionNames.contains(regionName)); + protected boolean accepts(Supplier regionName) { + return this.regionNames.isEmpty() || this.regionNames.contains(regionName.get()); } /** @@ -494,31 +477,56 @@ public class ExpirationConfiguration implements ImportAware { return this.types.contains(ExpirationType.TIME_TO_LIVE); } + /** + * Resolves the name of a given {@link Region} from the corresponding {@link RegionLookupFactoryBean} object. + * + * @param regionFactoryBean {@link RegionLookupFactoryBean} from which to resolve the {@link Region} name. + * @return the resolved name of the {@link Region} created from the given {@link RegionLookupFactoryBean}. + * @see org.springframework.data.gemfire.RegionLookupFactoryBean#resolveRegionName() + */ + protected String resolveRegionName(Object regionFactoryBean) { + return regionFactoryBean instanceof RegionLookupFactoryBean + ? ((RegionLookupFactoryBean) regionFactoryBean).resolveRegionName() : null; + } + + /** + * Configures the Expiration policies on the targeted {@link ExpiringRegionFactoryBean}, which may be + * either a {@link RegionFactoryBean} or {@link ClientRegionFactoryBean}. + * + * @param regionFactoryBean {@link ExpiringRegionFactoryBean} to configure. + * @return the given {@link ExpiringRegionFactoryBean}. + * @see org.springframework.data.gemfire.expiration.AnnotationBasedExpiration#forIdleTimeout(ExpirationAttributes) + * @see org.springframework.data.gemfire.expiration.AnnotationBasedExpiration#forTimeToLive(ExpirationAttributes) + * @see org.springframework.data.gemfire.expiration.ExpiringRegionFactoryBean + * @see #defaultExpirationAttributes() + */ + protected ExpiringRegionFactoryBean setExpirationAttributes( + ExpiringRegionFactoryBean regionFactoryBean) { + + ExpirationAttributes defaultExpirationAttributes = defaultExpirationAttributes(); + + if (isIdleTimeout()) { + regionFactoryBean.setCustomEntryIdleTimeout( + AnnotationBasedExpiration.forIdleTimeout(defaultExpirationAttributes)); + } + + if (isTimeToLive()) { + regionFactoryBean.setCustomEntryTimeToLive( + AnnotationBasedExpiration.forTimeToLive(defaultExpirationAttributes)); + } + + return regionFactoryBean; + } + /** * @inheritDoc */ @Override - public Object configure(Object regionObject) { + public Object configure(Object regionFactoryBean) { - if (accepts(regionObject)) { - Region region = (Region) regionObject; - - AttributesMutator regionAttributesMutator = region.getAttributesMutator(); - - ExpirationAttributes defaultExpirationAttributes = defaultExpirationAttributes(); - - if (isIdleTimeout()) { - regionAttributesMutator.setCustomEntryIdleTimeout( - AnnotationBasedExpiration.forIdleTimeout(defaultExpirationAttributes)); - } - - if (isTimeToLive()) { - regionAttributesMutator.setCustomEntryTimeToLive( - AnnotationBasedExpiration.forTimeToLive(defaultExpirationAttributes)); - } - } - - return regionObject; + return accepts(regionFactoryBean) + ? setExpirationAttributes((ExpiringRegionFactoryBean) regionFactoryBean) + : regionFactoryBean; } /** diff --git a/src/main/java/org/springframework/data/gemfire/config/annotation/StatisticsConfiguration.java b/src/main/java/org/springframework/data/gemfire/config/annotation/StatisticsConfiguration.java index f1d24eb8..d904b2b8 100644 --- a/src/main/java/org/springframework/data/gemfire/config/annotation/StatisticsConfiguration.java +++ b/src/main/java/org/springframework/data/gemfire/config/annotation/StatisticsConfiguration.java @@ -17,6 +17,7 @@ package org.springframework.data.gemfire.config.annotation; +import java.lang.annotation.Annotation; import java.util.Map; import java.util.Properties; @@ -50,11 +51,10 @@ public class StatisticsConfiguration extends EmbeddedServiceConfigurationSupport * @see org.springframework.data.gemfire.config.annotation.EnableStatistics */ @Override - protected Class getAnnotationType() { + protected Class getAnnotationType() { return EnableStatistics.class; } - /* (non-Javadoc) */ @Override protected Properties toGemFireProperties(Map annotationAttributes) { diff --git a/src/main/java/org/springframework/data/gemfire/config/annotation/support/CacheTypeAwareRegionFactoryBean.java b/src/main/java/org/springframework/data/gemfire/config/annotation/support/CacheTypeAwareRegionFactoryBean.java index f31b807b..594766c9 100644 --- a/src/main/java/org/springframework/data/gemfire/config/annotation/support/CacheTypeAwareRegionFactoryBean.java +++ b/src/main/java/org/springframework/data/gemfire/config/annotation/support/CacheTypeAwareRegionFactoryBean.java @@ -25,7 +25,10 @@ import java.util.List; import java.util.Optional; import org.apache.geode.cache.Cache; +import org.apache.geode.cache.CustomExpiry; import org.apache.geode.cache.DataPolicy; +import org.apache.geode.cache.EvictionAttributes; +import org.apache.geode.cache.ExpirationAttributes; import org.apache.geode.cache.GemFireCache; import org.apache.geode.cache.Region; import org.apache.geode.cache.RegionAttributes; @@ -45,6 +48,8 @@ import org.springframework.data.gemfire.RegionShortcutWrapper; import org.springframework.data.gemfire.ReplicatedRegionFactoryBean; import org.springframework.data.gemfire.client.ClientRegionFactoryBean; import org.springframework.data.gemfire.config.annotation.RegionConfigurer; +import org.springframework.data.gemfire.eviction.EvictingRegionFactoryBean; +import org.springframework.data.gemfire.expiration.ExpiringRegionFactoryBean; import org.springframework.util.StringUtils; /** @@ -54,7 +59,10 @@ import org.springframework.util.StringUtils; * * @author John Blum * @see org.apache.geode.cache.Cache + * @see org.apache.geode.cache.CustomExpiry * @see org.apache.geode.cache.DataPolicy + * @see org.apache.geode.cache.EvictionAttributes + * @see org.apache.geode.cache.ExpirationAttributes * @see org.apache.geode.cache.GemFireCache * @see org.apache.geode.cache.Region * @see org.apache.geode.cache.RegionAttributes @@ -71,15 +79,19 @@ import org.springframework.util.StringUtils; * @see org.springframework.data.gemfire.ReplicatedRegionFactoryBean * @see org.springframework.data.gemfire.client.ClientRegionFactoryBean * @see org.springframework.data.gemfire.config.annotation.RegionConfigurer + * @see org.springframework.data.gemfire.eviction.EvictingRegionFactoryBean + * @see org.springframework.data.gemfire.expiration.ExpiringRegionFactoryBean * @since 1.9.0 */ @SuppressWarnings("unused") -public class CacheTypeAwareRegionFactoryBean extends RegionLookupFactoryBean { +public class CacheTypeAwareRegionFactoryBean extends RegionLookupFactoryBean + implements EvictingRegionFactoryBean, ExpiringRegionFactoryBean { private GemFireCache gemfireCache; private Boolean close = false; private Boolean offHeap = false; + private Boolean statisticsEnabled = false; private Class keyConstraint; private Class valueConstraint; @@ -88,8 +100,18 @@ public class CacheTypeAwareRegionFactoryBean extends RegionLookupFactoryBe private Compressor compressor; + private CustomExpiry customEntryIdleTimeout; + private CustomExpiry customEntryTimeToLive; + private DataPolicy dataPolicy = DataPolicy.DEFAULT; + private EvictionAttributes evictionAttributes; + + private ExpirationAttributes entryIdleTimeout; + private ExpirationAttributes entryTimeToLive; + private ExpirationAttributes regionIdleTimeout; + private ExpirationAttributes regionTimeToLive; + private List regionConfigurers = Collections.emptyList(); private RegionAttributes regionAttributes; @@ -108,8 +130,9 @@ public class CacheTypeAwareRegionFactoryBean extends RegionLookupFactoryBe @Override public Region createRegion(GemFireCache gemfireCache, String regionName) throws Exception { - return (GemfireUtils.isClient(gemfireCache) ? newClientRegion(gemfireCache, regionName) - : newServerRegion(gemfireCache, regionName)); + return GemfireUtils.isClient(gemfireCache) + ? newClientRegion(gemfireCache, regionName) + : newServerRegion(gemfireCache, regionName); } /** @@ -144,6 +167,9 @@ public class CacheTypeAwareRegionFactoryBean extends RegionLookupFactoryBe getPoolName().ifPresent(clientRegionFactory::setPoolName); + configureEviction(clientRegionFactory); + configureExpiration(clientRegionFactory); + clientRegionFactory.afterPropertiesSet(); return clientRegionFactory.getObject(); @@ -194,6 +220,9 @@ public class CacheTypeAwareRegionFactoryBean extends RegionLookupFactoryBe serverRegionFactory.setShortcut(getServerRegionShortcut()); serverRegionFactory.setValueConstraint(getValueConstraint()); + configureEviction(serverRegionFactory); + configureExpiration(serverRegionFactory); + serverRegionFactory.afterPropertiesSet(); return serverRegionFactory.getObject(); @@ -224,14 +253,31 @@ public class CacheTypeAwareRegionFactoryBean extends RegionLookupFactoryBe return new PartitionedRegionFactoryBean<>(); } else if (resolvedDataPolicy.withReplication()) { + ReplicatedRegionFactoryBean replicatedRegionFactoryBean = new ReplicatedRegionFactoryBean<>(); + replicatedRegionFactoryBean.setScope(getScope()); + return replicatedRegionFactoryBean; } return new GenericRegionFactoryBean<>(); } + protected void configureEviction(EvictingRegionFactoryBean regionFactoryBean) { + regionFactoryBean.setEvictionAttributes(getEvictionAttributes()); + } + + protected void configureExpiration(ExpiringRegionFactoryBean regionFactoryBean) { + + regionFactoryBean.setCustomEntryIdleTimeout(getCustomEntryIdleTimeout()); + regionFactoryBean.setCustomEntryTimeToLive(getCustomEntryTimeToLive()); + regionFactoryBean.setEntryIdleTimeout(getEntryIdleTimeout()); + regionFactoryBean.setEntryTimeToLive(getEntryTimeToLive()); + regionFactoryBean.setRegionIdleTimeout(getRegionIdleTimeout()); + regionFactoryBean.setRegionTimeToLive(getRegionTimeToLive()); + } + public void setAttributes(RegionAttributes regionAttributes) { this.regionAttributes = regionAttributes; } @@ -280,6 +326,22 @@ public class CacheTypeAwareRegionFactoryBean extends RegionLookupFactoryBe return this.compressor; } + public void setCustomEntryIdleTimeout(CustomExpiry customEntryIdleTimeout) { + this.customEntryIdleTimeout = customEntryIdleTimeout; + } + + protected CustomExpiry getCustomEntryIdleTimeout() { + return customEntryIdleTimeout; + } + + public void setCustomEntryTimeToLive(CustomExpiry customEntryTimeToLive) { + this.customEntryTimeToLive = customEntryTimeToLive; + } + + protected CustomExpiry getCustomEntryTimeToLive() { + return customEntryTimeToLive; + } + public void setDataPolicy(DataPolicy dataPolicy) { this.dataPolicy = dataPolicy; } @@ -296,6 +358,30 @@ public class CacheTypeAwareRegionFactoryBean extends RegionLookupFactoryBe return this.diskStoreName; } + public void setEvictionAttributes(EvictionAttributes evictionAttributes) { + this.evictionAttributes = evictionAttributes; + } + + protected EvictionAttributes getEvictionAttributes() { + return evictionAttributes; + } + + public void setEntryIdleTimeout(ExpirationAttributes entryIdleTimeout) { + this.entryIdleTimeout = entryIdleTimeout; + } + + protected ExpirationAttributes getEntryIdleTimeout() { + return entryIdleTimeout; + } + + public void setEntryTimeToLive(ExpirationAttributes entryTimeToLive) { + this.entryTimeToLive = entryTimeToLive; + } + + protected ExpirationAttributes getEntryTimeToLive() { + return entryTimeToLive; + } + public void setKeyConstraint(Class keyConstraint) { this.keyConstraint = keyConstraint; } @@ -360,6 +446,22 @@ public class CacheTypeAwareRegionFactoryBean extends RegionLookupFactoryBe this.regionConfigurers = Optional.ofNullable(regionConfigurers).orElseGet(Collections::emptyList); } + public void setRegionIdleTimeout(ExpirationAttributes regionIdleTimeout) { + this.regionIdleTimeout = regionIdleTimeout; + } + + protected ExpirationAttributes getRegionIdleTimeout() { + return regionIdleTimeout; + } + + public void setRegionTimeToLive(ExpirationAttributes regionTimeToLive) { + this.regionTimeToLive = regionTimeToLive; + } + + protected ExpirationAttributes getRegionTimeToLive() { + return regionTimeToLive; + } + public void setScope(Scope scope) { this.scope = scope; } diff --git a/src/main/java/org/springframework/data/gemfire/config/xml/ParsingUtils.java b/src/main/java/org/springframework/data/gemfire/config/xml/ParsingUtils.java index 205a24a2..bc6f23f9 100644 --- a/src/main/java/org/springframework/data/gemfire/config/xml/ParsingUtils.java +++ b/src/main/java/org/springframework/data/gemfire/config/xml/ParsingUtils.java @@ -106,6 +106,7 @@ abstract class ParsingUtils { PropertyValue propertyValue = source.getPropertyValues().getPropertyValue(propertyName); if (propertyValue != null) { + builder.addPropertyValue(propertyValue.getName(), propertyValue.getValue()); if (withDependsOn && propertyValue.getValue() instanceof RuntimeBeanReference) { @@ -141,8 +142,8 @@ abstract class ParsingUtils { Object beanRef = ParsingUtils.getBeanReference(element, parserContext, "bean"); - return (beanRef != null ? beanRef : parserContext.getDelegate().parseCustomElement( - element, builder.getBeanDefinition())); + return beanRef != null ? beanRef + : parserContext.getDelegate().parseCustomElement(element, builder.getBeanDefinition()); } /** @@ -236,6 +237,7 @@ abstract class ParsingUtils { Element evictionElement = DomUtils.getChildElementByTagName(element, "eviction"); if (evictionElement != null) { + BeanDefinitionBuilder evictionAttributesBuilder = BeanDefinitionBuilder.genericBeanDefinition( EvictionAttributesFactoryBean.class); @@ -246,8 +248,10 @@ abstract class ParsingUtils { Element objectSizerElement = DomUtils.getChildElementByTagName(evictionElement, "object-sizer"); if (objectSizerElement != null) { + Object sizer = parseRefOrNestedBeanDeclaration(objectSizerElement, parserContext, evictionAttributesBuilder); + evictionAttributesBuilder.addPropertyValue("objectSizer", sizer); } @@ -270,13 +274,15 @@ abstract class ParsingUtils { */ @SuppressWarnings("unused") static boolean parseSubscription(Element element, ParserContext parserContext, + BeanDefinitionBuilder regionAttributesBuilder) { Element subscriptionElement = DomUtils.getChildElementByTagName(element, "subscription"); if (subscriptionElement != null) { - BeanDefinitionBuilder subscriptionAttributesBuilder = BeanDefinitionBuilder.genericBeanDefinition( - SubscriptionAttributesFactoryBean.class); + + BeanDefinitionBuilder subscriptionAttributesBuilder = + BeanDefinitionBuilder.genericBeanDefinition(SubscriptionAttributesFactoryBean.class); setPropertyValue(subscriptionElement, subscriptionAttributesBuilder, "type", "interestPolicy"); @@ -290,6 +296,7 @@ abstract class ParsingUtils { } static void parseTransportFilters(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { + Element transportFilterElement = DomUtils.getChildElementByTagName(element, "transport-filter"); if (transportFilterElement != null) { @@ -312,9 +319,10 @@ abstract class ParsingUtils { * @return a boolean indicating whether Region expiration attributes were specified. */ static boolean parseExpiration(Element element, ParserContext parserContext, - BeanDefinitionBuilder regionAttributesBuilder) { + BeanDefinitionBuilder regionAttributesBuilder) { - boolean result = parseExpiration(element, "region-ttl", "regionTimeToLive", regionAttributesBuilder); + boolean result = parseExpiration(element, "region-ttl", "regionTimeToLive", + regionAttributesBuilder); result |= parseExpiration(element, "region-tti", "regionIdleTimeout", regionAttributesBuilder); result |= parseExpiration(element, "entry-ttl", "entryTimeToLive", regionAttributesBuilder); @@ -325,7 +333,7 @@ abstract class ParsingUtils { regionAttributesBuilder); if (result) { - // turn on statistics + // enable statistics regionAttributesBuilder.addPropertyValue("statisticsEnabled", Boolean.TRUE); } @@ -361,6 +369,7 @@ abstract class ParsingUtils { @SuppressWarnings({ "deprecation", "unused" }) static void parseMembershipAttributes(Element element, ParserContext parserContext, + BeanDefinitionBuilder regionAttributesBuilder) { Element membershipAttributes = DomUtils.getChildElementByTagName(element, "membership-attributes"); @@ -387,6 +396,7 @@ abstract class ParsingUtils { } static void parseScope(Element element, BeanDefinitionBuilder builder) { + String scopeAttributeValue = element.getAttribute("scope"); if (StringUtils.hasText(scopeAttributeValue)) { @@ -400,8 +410,9 @@ abstract class ParsingUtils { Element expirationElement = DomUtils.getChildElementByTagName(rootElement, elementName); if (expirationElement != null) { - BeanDefinitionBuilder expirationAttributesBuilder = BeanDefinitionBuilder.genericBeanDefinition( - ExpirationAttributesFactoryBean.class); + + BeanDefinitionBuilder expirationAttributesBuilder = + BeanDefinitionBuilder.genericBeanDefinition(ExpirationAttributesFactoryBean.class); setPropertyValue(expirationElement, expirationAttributesBuilder, "action"); setPropertyValue(expirationElement, expirationAttributesBuilder, "timeout"); @@ -419,6 +430,7 @@ abstract class ParsingUtils { Element expirationElement = DomUtils.getChildElementByTagName(rootElement, elementName); if (expirationElement != null) { + Object customExpiry = parseRefOrSingleNestedBeanDeclaration(expirationElement, parserContext, regionAttributesBuilder); @@ -443,6 +455,7 @@ abstract class ParsingUtils { @SuppressWarnings("unused") static void assertGemFireFeatureAvailable(Element element, ParserContext parserContext) { + if (GemfireUtils.isGemfireFeatureUnavailable(element)) { parserContext.getReaderContext().error(String.format("'%1$s' is not supported in %2$s v%3$s", element.getLocalName(), GemfireUtils.GEMFIRE_NAME, GemfireUtils.GEMFIRE_VERSION), element); @@ -473,11 +486,13 @@ abstract class ParsingUtils { String elementName, String attributeName, ParserContext parserContext) { if (GemfireUtils.isGemfireFeatureUnavailable(feature)) { + String messagePrefix = (attributeName != null) ? String.format("Attribute '%1$s' of element '%2$s'", attributeName, elementName) : String.format("Element '%1$s'", elementName); - parserContext.getReaderContext().error( - String.format("%1$s requires GemFire version 7 or later. The current version is %2$s.", + + parserContext.getReaderContext() + .error(String.format("%1$s requires GemFire version 7 or later. The current version is %2$s.", messagePrefix, GemfireUtils.GEMFIRE_VERSION), null); } } diff --git a/src/main/java/org/springframework/data/gemfire/eviction/EvictingRegionFactoryBean.java b/src/main/java/org/springframework/data/gemfire/eviction/EvictingRegionFactoryBean.java new file mode 100644 index 00000000..4c8110ec --- /dev/null +++ b/src/main/java/org/springframework/data/gemfire/eviction/EvictingRegionFactoryBean.java @@ -0,0 +1,36 @@ +/* + * Copyright 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.data.gemfire.eviction; + +import org.apache.geode.cache.EvictionAttributes; +import org.apache.geode.cache.Region; +import org.springframework.beans.factory.FactoryBean; + +/** + * The {@link EvictingRegionFactoryBean} interface specifies {@link Region} {@link FactoryBean FactoryBeans} capable + * of supporting Eviction configuration, that is, evicting {@link Region} entries. + * + * @author John Blum + * @see org.apache.geode.cache.EvictionAttributes + * @see org.apache.geode.cache.Region + * @since 2.1.0 + */ +public interface EvictingRegionFactoryBean { + + void setEvictionAttributes(EvictionAttributes evictionAttributes); + +} diff --git a/src/main/java/org/springframework/data/gemfire/eviction/EvictionActionType.java b/src/main/java/org/springframework/data/gemfire/eviction/EvictionActionType.java index 636975b6..ac63472d 100644 --- a/src/main/java/org/springframework/data/gemfire/eviction/EvictionActionType.java +++ b/src/main/java/org/springframework/data/gemfire/eviction/EvictionActionType.java @@ -28,6 +28,7 @@ import org.apache.geode.cache.EvictionAction; */ @SuppressWarnings("unused") public enum EvictionActionType { + LOCAL_DESTROY(EvictionAction.LOCAL_DESTROY), NONE(EvictionAction.NONE), OVERFLOW_TO_DISK(EvictionAction.OVERFLOW_TO_DISK); @@ -55,7 +56,7 @@ public enum EvictionActionType { * @see #getEvictionAction() */ public static EvictionAction getEvictionAction(final EvictionActionType evictionActionType) { - return (evictionActionType != null ? evictionActionType.getEvictionAction() : null); + return evictionActionType != null ? evictionActionType.getEvictionAction() : null; } /** @@ -68,6 +69,7 @@ public enum EvictionActionType { * @see #getEvictionAction() */ public static EvictionActionType valueOf(final EvictionAction evictionAction) { + for (EvictionActionType evictionActionType : values()) { if (evictionActionType.getEvictionAction().equals(evictionAction)) { return evictionActionType; @@ -87,6 +89,7 @@ public enum EvictionActionType { * @see #name() */ public static EvictionActionType valueOfIgnoreCase(final String name) { + for (EvictionActionType evictionActionType : values()) { if (evictionActionType.name().equalsIgnoreCase(name)) { return evictionActionType; @@ -103,7 +106,6 @@ public enum EvictionActionType { * @see org.apache.geode.cache.EvictionAction */ public EvictionAction getEvictionAction() { - return evictionAction; + return this.evictionAction; } - } diff --git a/src/main/java/org/springframework/data/gemfire/eviction/EvictionPolicyType.java b/src/main/java/org/springframework/data/gemfire/eviction/EvictionPolicyType.java index 87653520..fd268227 100644 --- a/src/main/java/org/springframework/data/gemfire/eviction/EvictionPolicyType.java +++ b/src/main/java/org/springframework/data/gemfire/eviction/EvictionPolicyType.java @@ -30,6 +30,7 @@ import org.apache.geode.cache.EvictionAlgorithm; */ @SuppressWarnings("unused") public enum EvictionPolicyType { + ENTRY_COUNT(EvictionAlgorithm.LRU_ENTRY), HEAP_PERCENTAGE(EvictionAlgorithm.LRU_HEAP), MEMORY_SIZE(EvictionAlgorithm.LRU_MEMORY), @@ -56,7 +57,7 @@ public enum EvictionPolicyType { * @see #getEvictionAlgorithm() */ public static EvictionAlgorithm getEvictionAlgorithm(final EvictionPolicyType evictionPolicyType) { - return (evictionPolicyType != null ? evictionPolicyType.getEvictionAlgorithm() : null); + return evictionPolicyType != null ? evictionPolicyType.getEvictionAlgorithm() : null; } /** @@ -68,6 +69,7 @@ public enum EvictionPolicyType { * @see #getEvictionAlgorithm() */ public static EvictionPolicyType valueOf(final EvictionAlgorithm evictionAlgorithm) { + for (EvictionPolicyType evictionPolicyType : values()) { if (evictionPolicyType.getEvictionAlgorithm().equals(evictionAlgorithm)) { return evictionPolicyType; @@ -86,6 +88,7 @@ public enum EvictionPolicyType { * @see #name() */ public static EvictionPolicyType valueOfIgnoreCase(final String name) { + for (EvictionPolicyType evictionPolicyType : values()) { if (evictionPolicyType.name().equalsIgnoreCase(name)) { return evictionPolicyType; @@ -102,7 +105,6 @@ public enum EvictionPolicyType { * @see org.apache.geode.cache.EvictionAlgorithm */ public EvictionAlgorithm getEvictionAlgorithm() { - return evictionAlgorithm; + return this.evictionAlgorithm; } - } diff --git a/src/main/java/org/springframework/data/gemfire/expiration/AnnotationBasedExpiration.java b/src/main/java/org/springframework/data/gemfire/expiration/AnnotationBasedExpiration.java index 838d725d..65cbfacd 100644 --- a/src/main/java/org/springframework/data/gemfire/expiration/AnnotationBasedExpiration.java +++ b/src/main/java/org/springframework/data/gemfire/expiration/AnnotationBasedExpiration.java @@ -128,10 +128,15 @@ public class AnnotationBasedExpiration implements BeanFactoryAware, Custom * @see #AnnotationBasedExpiration(ExpirationAttributes) */ public static AnnotationBasedExpiration forIdleTimeout(ExpirationAttributes defaultExpirationAttributes) { + return new AnnotationBasedExpiration(defaultExpirationAttributes) { - @Override protected ExpirationMetaData getExpirationMetaData(Region.Entry entry) { - return (isIdleTimeoutConfigured(entry) ? ExpirationMetaData.from(getIdleTimeout(entry)) - : super.getExpirationMetaData(entry)); + + @Override + protected ExpirationMetaData getExpirationMetaData(Region.Entry entry) { + + return isIdleTimeoutConfigured(entry) + ? ExpirationMetaData.from(getIdleTimeout(entry)) + : super.getExpirationMetaData(entry); } }; } @@ -169,10 +174,15 @@ public class AnnotationBasedExpiration implements BeanFactoryAware, Custom * @see #AnnotationBasedExpiration(ExpirationAttributes) */ public static AnnotationBasedExpiration forTimeToLive(ExpirationAttributes defaultExpirationAttributes) { + return new AnnotationBasedExpiration(defaultExpirationAttributes) { - @Override protected ExpirationMetaData getExpirationMetaData(Region.Entry entry) { - return (isTimeToLiveConfigured(entry) ? ExpirationMetaData.from(getTimeToLive(entry)) - : super.getExpirationMetaData(entry)); + + @Override + protected ExpirationMetaData getExpirationMetaData(Region.Entry entry) { + + return isTimeToLiveConfigured(entry) + ? ExpirationMetaData.from(getTimeToLive(entry)) + : super.getExpirationMetaData(entry); } }; } @@ -182,9 +192,11 @@ public class AnnotationBasedExpiration implements BeanFactoryAware, Custom * and SpEL expressions in the Expiration annotation attribute values. */ protected void initEvaluationContext() { + BeanFactory beanFactory = getBeanFactory(); if (EVALUATION_CONTEXT_REFERENCE.compareAndSet(null, newEvaluationContext())) { + StandardEvaluationContext evaluationContext = EVALUATION_CONTEXT_REFERENCE.get(); evaluationContext.addPropertyAccessor(new BeanFactoryAccessor()); @@ -192,7 +204,9 @@ public class AnnotationBasedExpiration implements BeanFactoryAware, Custom evaluationContext.addPropertyAccessor(new MapAccessor()); if (beanFactory instanceof ConfigurableBeanFactory) { + ConfigurableBeanFactory configurableBeanFactory = (ConfigurableBeanFactory) beanFactory; + ConversionService conversionService = configurableBeanFactory.getConversionService(); if (conversionService != null) { @@ -206,7 +220,6 @@ public class AnnotationBasedExpiration implements BeanFactoryAware, Custom EVALUATION_CONTEXT_REFERENCE.get().setBeanResolver(new BeanFactoryResolver(beanFactory)); } - /* (non-Javadoc) */ StandardEvaluationContext newEvaluationContext() { return new StandardEvaluationContext(); } @@ -261,7 +274,7 @@ public class AnnotationBasedExpiration implements BeanFactoryAware, Custom */ protected ExpirationAttributes getDefaultExpirationAttributes() { //return (defaultExpirationAttributes != null ? defaultExpirationAttributes : ExpirationAttributes.DEFAULT); - return defaultExpirationAttributes; + return this.defaultExpirationAttributes; } /** @@ -290,7 +303,7 @@ public class AnnotationBasedExpiration implements BeanFactoryAware, Custom * @see AnnotationBasedExpiration.ExpirationMetaData */ protected ExpirationMetaData getExpirationMetaData(Region.Entry entry) { - return (isExpirationConfigured(entry) ? ExpirationMetaData.from(getExpiration(entry)) : null); + return isExpirationConfigured(entry) ? ExpirationMetaData.from(getExpiration(entry)) : null; } /** @@ -308,8 +321,10 @@ public class AnnotationBasedExpiration implements BeanFactoryAware, Custom * @see #getDefaultExpirationAttributes() */ protected ExpirationAttributes newExpirationAttributes(ExpirationMetaData expirationMetaData) { - return (expirationMetaData != null ? expirationMetaData.toExpirationAttributes() - : getDefaultExpirationAttributes()); + + return expirationMetaData != null + ? expirationMetaData.toExpirationAttributes() + : getDefaultExpirationAttributes(); } /** @@ -321,10 +336,9 @@ public class AnnotationBasedExpiration implements BeanFactoryAware, Custom * @see #isAnnotationPresent(Object, Class) */ protected boolean isExpirationConfigured(Region.Entry entry) { - return (entry != null && isExpirationConfigured(entry.getValue())); + return entry != null && isExpirationConfigured(entry.getValue()); } - /* (non-Javadoc) */ private boolean isExpirationConfigured(Object obj) { return isAnnotationPresent(obj, Expiration.class); } @@ -342,7 +356,6 @@ public class AnnotationBasedExpiration implements BeanFactoryAware, Custom return getExpiration(entry.getValue()); } - /* (non-Javadoc) */ private Expiration getExpiration(Object obj) { return getAnnotation(obj, Expiration.class); } @@ -356,10 +369,9 @@ public class AnnotationBasedExpiration implements BeanFactoryAware, Custom * @see #isAnnotationPresent(Object, Class) */ protected boolean isIdleTimeoutConfigured(Region.Entry entry) { - return (entry != null && isIdleTimeoutConfigured(entry.getValue())); + return entry != null && isIdleTimeoutConfigured(entry.getValue()); } - /* (non-Javadoc) */ private boolean isIdleTimeoutConfigured(Object obj) { return isAnnotationPresent(obj, IdleTimeoutExpiration.class); } @@ -377,7 +389,6 @@ public class AnnotationBasedExpiration implements BeanFactoryAware, Custom return getIdleTimeout(entry.getValue()); } - /* (non-Javadoc) */ private IdleTimeoutExpiration getIdleTimeout(Object obj) { return getAnnotation(obj, IdleTimeoutExpiration.class); } @@ -391,10 +402,9 @@ public class AnnotationBasedExpiration implements BeanFactoryAware, Custom * @see #isAnnotationPresent(Object, Class) */ protected boolean isTimeToLiveConfigured(Region.Entry entry) { - return (entry != null && isTimeToLiveConfigured(entry.getValue())); + return entry != null && isTimeToLiveConfigured(entry.getValue()); } - /* (non-Javadoc) */ private boolean isTimeToLiveConfigured(Object value) { return isAnnotationPresent(value, TimeToLiveExpiration.class); } @@ -412,17 +422,14 @@ public class AnnotationBasedExpiration implements BeanFactoryAware, Custom return getTimeToLive(entry.getValue()); } - /* (non-Javadoc) */ private TimeToLiveExpiration getTimeToLive(Object obj) { return getAnnotation(obj, TimeToLiveExpiration.class); } - /* (non-Javadoc) */ private boolean isAnnotationPresent(Object obj, Class annotationType) { return (obj != null && obj.getClass().isAnnotationPresent(annotationType)); } - /* (non-Javadoc) */ private T getAnnotation(Object obj, Class annotationType) { return AnnotationUtils.getAnnotation(obj.getClass(), annotationType); } @@ -432,8 +439,7 @@ public class AnnotationBasedExpiration implements BeanFactoryAware, Custom * or when a callback is removed from a Region using an AttributesMutator. */ @Override - public void close() { - } + public void close() { } /** * The ExpirationMetaData class encapsulates the settings constituting the expiration policy including @@ -449,50 +455,48 @@ public class AnnotationBasedExpiration implements BeanFactoryAware, Custom private final ExpirationActionType action; - /* (non-Javadoc) */ protected ExpirationMetaData(int timeout, ExpirationActionType action) { this.timeout = timeout; this.action = action; } - /* (non-Javadoc) */ protected static ExpirationMetaData from(ExpirationAttributes expirationAttributes) { return new ExpirationMetaData(expirationAttributes.getTimeout(), ExpirationActionType.valueOf( expirationAttributes.getAction())); } - /* (non-Javadoc) */ protected static ExpirationMetaData from(Expiration expiration) { return new ExpirationMetaData(parseTimeout(expiration.timeout()), parseAction(expiration.action())); } - /* (non-Javadoc) */ protected static ExpirationMetaData from(IdleTimeoutExpiration expiration) { return new ExpirationMetaData(parseTimeout(expiration.timeout()), parseAction(expiration.action())); } - /* (non-Javadoc) */ protected static ExpirationMetaData from(TimeToLiveExpiration expiration) { return new ExpirationMetaData(parseTimeout(expiration.timeout()), parseAction(expiration.action())); } - /* (non-Javadoc) */ public ExpirationAttributes toExpirationAttributes() { return new ExpirationAttributes(timeout(), expirationAction()); } - /* (non-Javadoc) */ + @SuppressWarnings("all") protected static int parseTimeout(String timeout) { + try { return Integer.parseInt(timeout); } catch (NumberFormatException cause) { + try { // Next, try to parse the 'timeout' as a Spring Expression using SpEL. - return new SpelExpressionParser().parseExpression(timeout).getValue( - EVALUATION_CONTEXT_REFERENCE.get(), Integer.TYPE); + return new SpelExpressionParser() + .parseExpression(timeout) + .getValue(EVALUATION_CONTEXT_REFERENCE.get(), Integer.TYPE); } catch (ParseException e) { + // Finally, try to process the 'timeout' as a Spring Property Placeholder. if (BEAN_FACTORY_REFERENCE.get() instanceof ConfigurableBeanFactory) { return Integer.parseInt(((ConfigurableBeanFactory) BEAN_FACTORY_REFERENCE.get()) @@ -504,12 +508,13 @@ public class AnnotationBasedExpiration implements BeanFactoryAware, Custom } } - /* (non-Javadoc) */ protected static ExpirationActionType parseAction(String action) { + try { return ExpirationActionType.valueOf(EXPIRATION_ACTION_CONVERTER.convert(action)); } catch (IllegalArgumentException cause) { + // Next, try to parse the 'action' as a Spring Expression using SpEL. EvaluationException evaluationException = new EvaluationException(String.format( "[%s] is not resolvable as an ExpirationAction(Type)", action), cause); @@ -517,12 +522,14 @@ public class AnnotationBasedExpiration implements BeanFactoryAware, Custom EvaluationContext evaluationContext = EVALUATION_CONTEXT_REFERENCE.get(); try { + Expression expression = new SpelExpressionParser().parseExpression(action); + Class valueType = expression.getValueType(evaluationContext); if (String.class.equals(valueType)) { - return ExpirationActionType.valueOf(EXPIRATION_ACTION_CONVERTER.convert(expression.getValue( - evaluationContext, String.class))); + return ExpirationActionType.valueOf(EXPIRATION_ACTION_CONVERTER + .convert(expression.getValue(evaluationContext, String.class))); } else if (ExpirationAction.class.equals(valueType)) { return ExpirationActionType.valueOf(expression.getValue(evaluationContext, ExpirationAction.class)); @@ -534,11 +541,13 @@ public class AnnotationBasedExpiration implements BeanFactoryAware, Custom throw evaluationException; } catch (ParseException e) { + // Finally, try to process the 'action' as a Spring Property Placeholder. if (BEAN_FACTORY_REFERENCE.get() instanceof ConfigurableBeanFactory) { try { - String resolvedValue = ((ConfigurableBeanFactory) BEAN_FACTORY_REFERENCE.get()) - .resolveEmbeddedValue(action); + + String resolvedValue = + ((ConfigurableBeanFactory) BEAN_FACTORY_REFERENCE.get()).resolveEmbeddedValue(action); return ExpirationActionType.valueOf(EXPIRATION_ACTION_CONVERTER.convert(resolvedValue)); } @@ -551,17 +560,14 @@ public class AnnotationBasedExpiration implements BeanFactoryAware, Custom } } - /* (non-Javadoc) */ public ExpirationActionType action() { return action; } - /* (non-Javadoc) */ public ExpirationAction expirationAction() { return action().getExpirationAction(); } - /* (non-Javadoc) */ public int timeout() { return timeout; } @@ -571,7 +577,8 @@ public class AnnotationBasedExpiration implements BeanFactoryAware, Custom */ @Override public boolean equals(final Object obj) { - if (obj == this) { + + if (this == obj) { return true; } @@ -590,9 +597,12 @@ public class AnnotationBasedExpiration implements BeanFactoryAware, Custom */ @Override public int hashCode() { + int hashValue = 17; + hashValue = 37 * hashValue + ObjectUtils.nullSafeHashCode(timeout()); hashValue = 37 * hashValue + ObjectUtils.nullSafeHashCode(action()); + return hashValue; } @@ -601,8 +611,8 @@ public class AnnotationBasedExpiration implements BeanFactoryAware, Custom */ @Override public String toString() { - return String.format("{ @type = %1$s, timeout = %2$d, action = %3$s }", getClass().getName(), - timeout(), action()); + return String.format("{ @type = %1$s, timeout = %2$d, action = %3$s }", + getClass().getName(), timeout(), action()); } } } diff --git a/src/main/java/org/springframework/data/gemfire/expiration/ExpirationActionType.java b/src/main/java/org/springframework/data/gemfire/expiration/ExpirationActionType.java index 4cac6549..03251b61 100644 --- a/src/main/java/org/springframework/data/gemfire/expiration/ExpirationActionType.java +++ b/src/main/java/org/springframework/data/gemfire/expiration/ExpirationActionType.java @@ -28,6 +28,7 @@ import org.apache.geode.cache.ExpirationAction; */ @SuppressWarnings("unused") public enum ExpirationActionType { + DESTROY(ExpirationAction.DESTROY), INVALIDATE(ExpirationAction.INVALIDATE), LOCAL_DESTROY(ExpirationAction.LOCAL_DESTROY), @@ -56,7 +57,7 @@ public enum ExpirationActionType { * @see org.apache.geode.cache.ExpirationAction */ public static ExpirationAction getExpirationAction(final ExpirationActionType expirationActionType) { - return (expirationActionType != null ? expirationActionType.getExpirationAction() : null); + return expirationActionType != null ? expirationActionType.getExpirationAction() : null; } /** @@ -69,6 +70,7 @@ public enum ExpirationActionType { * @see #getExpirationAction() */ public static ExpirationActionType valueOf(final ExpirationAction expirationAction) { + for (ExpirationActionType expirationActionType : values()) { if (expirationActionType.getExpirationAction().equals(expirationAction)) { return expirationActionType; @@ -88,6 +90,7 @@ public enum ExpirationActionType { * @see #name() */ public static ExpirationActionType valueOfIgnoreCase(final String name) { + for (ExpirationActionType expirationActionType : values()) { if (expirationActionType.name().equalsIgnoreCase(name)) { return expirationActionType; @@ -104,7 +107,6 @@ public enum ExpirationActionType { * @see org.apache.geode.cache.ExpirationAction */ public ExpirationAction getExpirationAction() { - return expirationAction; + return this.expirationAction; } - } diff --git a/src/main/java/org/springframework/data/gemfire/expiration/ExpiringRegionFactoryBean.java b/src/main/java/org/springframework/data/gemfire/expiration/ExpiringRegionFactoryBean.java new file mode 100644 index 00000000..1d7ec40d --- /dev/null +++ b/src/main/java/org/springframework/data/gemfire/expiration/ExpiringRegionFactoryBean.java @@ -0,0 +1,56 @@ +/* + * Copyright 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.data.gemfire.expiration; + +import org.apache.geode.cache.CustomExpiry; +import org.apache.geode.cache.ExpirationAttributes; +import org.apache.geode.cache.Region; +import org.springframework.beans.factory.FactoryBean; + +/** + * The {@link ExpiringRegionFactoryBean} interface signifies {@link Region} {@link FactoryBean FactoryBeans} + * that support Expiration configuration. That is, {@link Region Region's} capable of expiring both entries + * as well as the {@link Region} itself. + * + * Expiration policies may either be expressed as {@link ExpirationAttributes} or using a {@link CustomExpiry} + * object enable the application developer to specify custom expiration criteria. + * + * Apache Geode and Pivotal GemFire supports both Idle Timeout (TTI) as well as Time-to-Live (TTL) expiration policies + * at both the {@link Region} level as well as for entries. + * + * @author John Blum + * @see org.apache.geode.cache.CustomExpiry + * @see org.apache.geode.cache.ExpirationAttributes + * @see org.apache.geode.cache.Region + * @since 2.1.0 + */ +@SuppressWarnings("unused") +public interface ExpiringRegionFactoryBean { + + void setCustomEntryIdleTimeout(CustomExpiry customEntryIdleTimeout); + + void setCustomEntryTimeToLive(CustomExpiry customEntryTimeToLive); + + void setEntryIdleTimeout(ExpirationAttributes entryIdleTimeout); + + void setEntryTimeToLive(ExpirationAttributes entryTimeToLive); + + void setRegionIdleTimeout(ExpirationAttributes regionIdleTimeout); + + void setRegionTimeToLive(ExpirationAttributes regionTimeToLive); + +} diff --git a/src/test/java/org/springframework/data/gemfire/SubRegionIntegrationTest.java b/src/test/java/org/springframework/data/gemfire/SubRegionIntegrationTest.java index 4061d54a..594a2fbf 100644 --- a/src/test/java/org/springframework/data/gemfire/SubRegionIntegrationTest.java +++ b/src/test/java/org/springframework/data/gemfire/SubRegionIntegrationTest.java @@ -72,6 +72,7 @@ public class SubRegionIntegrationTest { @Test public void testGemFireAccountsSubRegionCreation() { + assertNotNull("The GemFire Cache was not properly initialized!", cache); Region customers = cache.getRegion("Customers"); @@ -93,6 +94,7 @@ public class SubRegionIntegrationTest { @Test public void testSpringSubRegionConfiguration() { + assertNotNull("The /Customers/Accounts SubRegion was not properly initialized!", accounts); assertEquals("Accounts", accounts.getName()); assertEquals("/Customers/Accounts", accounts.getFullPath()); diff --git a/src/test/java/org/springframework/data/gemfire/client/ClientRegionFactoryBeanTest.java b/src/test/java/org/springframework/data/gemfire/client/ClientRegionFactoryBeanTest.java index 547b2644..01eadddd 100644 --- a/src/test/java/org/springframework/data/gemfire/client/ClientRegionFactoryBeanTest.java +++ b/src/test/java/org/springframework/data/gemfire/client/ClientRegionFactoryBeanTest.java @@ -160,7 +160,7 @@ public class ClientRegionFactoryBeanTest { verify(mockClientRegionFactory, times(1)).setPoolName(eq("TestPoolTwo")); verify(mockClientRegionFactory, times(1)).setRegionIdleTimeout(any(ExpirationAttributes.class)); verify(mockClientRegionFactory, times(1)).setRegionTimeToLive(any(ExpirationAttributes.class)); - verify(mockClientRegionFactory, times(1)).setStatisticsEnabled(eq(true)); + verify(mockClientRegionFactory, times(2)).setStatisticsEnabled(eq(true)); verify(mockClientRegionFactory, times(1)).setValueConstraint(eq(Number.class)); verify(mockClientRegionFactory, times(1)).create(eq("TestRegion")); verify(mockRegion, never()).loadSnapshot(any(InputStream.class)); diff --git a/src/test/java/org/springframework/data/gemfire/config/annotation/EnableEvictionConfigurationIntegrationTests.java b/src/test/java/org/springframework/data/gemfire/config/annotation/EnableEvictionConfigurationIntegrationTests.java new file mode 100644 index 00000000..0a1fa35b --- /dev/null +++ b/src/test/java/org/springframework/data/gemfire/config/annotation/EnableEvictionConfigurationIntegrationTests.java @@ -0,0 +1,105 @@ +/* + * Copyright 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.data.gemfire.config.annotation; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Optional; + +import org.apache.geode.cache.DataPolicy; +import org.apache.geode.cache.Region; +import org.apache.geode.cache.RegionShortcut; +import org.apache.geode.cache.client.ClientRegionShortcut; +import org.junit.After; +import org.junit.Test; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.data.gemfire.eviction.EvictionActionType; +import org.springframework.data.gemfire.eviction.EvictionPolicyType; +import org.springframework.data.gemfire.test.model.Person; + +/** + * The EnableEvictionConfigurationIntegrationTests class... + * + * @author John Blum + * @since 1.0.0 + */ +public class EnableEvictionConfigurationIntegrationTests { + + private static final String GEMFIRE_LOG_LEVEL = "error"; + + private ConfigurableApplicationContext applicationContext; + + @After + public void tearDown() { + Optional.ofNullable(this.applicationContext).ifPresent(ConfigurableApplicationContext::close); + } + + private ConfigurableApplicationContext newApplicationContext(Class... annotatedClasses) { + this.applicationContext = new AnnotationConfigApplicationContext(annotatedClasses); + return this.applicationContext; + } + + @SuppressWarnings("unchecked") + private Region getRegion(ConfigurableApplicationContext applicationContext, String beanName) { + return applicationContext.getBean(beanName, Region.class); + } + + private void assertRegionEvictionConfiguration(ConfigurableApplicationContext applicationContext, + String regionBeanName, EvictionActionType expectedEvictionActionType, int expectedEvictionMaximum) { + + Region region = getRegion(applicationContext, regionBeanName); + + assertThat(region).isNotNull(); + assertThat(region.getName()).isEqualTo(regionBeanName); + assertThat(region.getAttributes()).isNotNull(); + assertThat(region.getAttributes().getDataPolicy()).isEqualTo(DataPolicy.NORMAL); + assertThat(region.getAttributes().getEvictionAttributes()).isNotNull(); + + assertThat(region.getAttributes().getEvictionAttributes().getAction()) + .isEqualTo(expectedEvictionActionType.getEvictionAction()); + + assertThat(region.getAttributes().getEvictionAttributes().getAlgorithm()) + .isEqualTo(EvictionPolicyType.ENTRY_COUNT.getEvictionAlgorithm()); + + assertThat(region.getAttributes().getEvictionAttributes().getMaximum()).isEqualTo(expectedEvictionMaximum); + } + + @Test + public void assertClientCacheRegionEvictionPolicyIsCorrect() { + assertRegionEvictionConfiguration(newApplicationContext(ClientCacheRegionEvictionConfiguration.class), + "People", EvictionActionType.LOCAL_DESTROY, 100); + } + + @Test + public void assertPeerCacheRegionEvictionPolicyIsCorrect() { + assertRegionEvictionConfiguration(newApplicationContext(PeerCacheRegionEvictionConfiguration.class), + "People", EvictionActionType.OVERFLOW_TO_DISK, 10000); + } + + @ClientCacheApplication(name = "EnableEvictionConfigurationIntegrationTests", logLevel = GEMFIRE_LOG_LEVEL) + @EnableEntityDefinedRegions(basePackageClasses = Person.class, clientRegionShortcut = ClientRegionShortcut.LOCAL) + @EnableEviction(policies = @EnableEviction.EvictionPolicy(regionNames = "People", maximum = 100)) + static class ClientCacheRegionEvictionConfiguration { } + + @PeerCacheApplication(name = "EnableEvictionConfigurationIntegrationTests", logLevel = GEMFIRE_LOG_LEVEL) + @EnableEntityDefinedRegions(basePackageClasses = Person.class, serverRegionShortcut = RegionShortcut.LOCAL) + @EnableEviction(policies = @EnableEviction.EvictionPolicy(regionNames = "People", + action = EvictionActionType.OVERFLOW_TO_DISK, maximum = 10000)) + static class PeerCacheRegionEvictionConfiguration { } + +} diff --git a/src/test/java/org/springframework/data/gemfire/config/annotation/EnableExpirationConfigurationIntegrationTests.java b/src/test/java/org/springframework/data/gemfire/config/annotation/EnableExpirationConfigurationIntegrationTests.java new file mode 100644 index 00000000..83c0ea1f --- /dev/null +++ b/src/test/java/org/springframework/data/gemfire/config/annotation/EnableExpirationConfigurationIntegrationTests.java @@ -0,0 +1,99 @@ +/* + * Copyright 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.data.gemfire.config.annotation; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Optional; + +import org.apache.geode.cache.DataPolicy; +import org.apache.geode.cache.Region; +import org.apache.geode.cache.RegionShortcut; +import org.apache.geode.cache.client.ClientRegionShortcut; +import org.junit.After; +import org.junit.Test; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.data.gemfire.expiration.AnnotationBasedExpiration; +import org.springframework.data.gemfire.test.model.Person; + +/** + * The EnableExpirationConfigurationIntegrationTests class... + * + * @author John Blum + * @since 1.0.0 + */ +public class EnableExpirationConfigurationIntegrationTests { + + private static final String GEMFIRE_LOG_LEVEL = "error"; + + private ConfigurableApplicationContext applicationContext; + + @After + public void tearDown() { + Optional.ofNullable(this.applicationContext).ifPresent(ConfigurableApplicationContext::close); + } + + private ConfigurableApplicationContext newApplicationContext(Class... annotatedClasses) { + this.applicationContext = new AnnotationConfigApplicationContext(annotatedClasses); + return this.applicationContext; + } + + @SuppressWarnings("unchecked") + private Region getRegion(ConfigurableApplicationContext applicationContext, String beanName) { + return applicationContext.getBean(beanName, Region.class); + } + + private void assertRegionExpirationConfiguration(ConfigurableApplicationContext applicationContext, + String regionBeanName) { + + Region region = getRegion(applicationContext, regionBeanName); + + assertThat(region).isNotNull(); + assertThat(region.getName()).isEqualTo(regionBeanName); + assertThat(region.getAttributes()).isNotNull(); + assertThat(region.getAttributes().getDataPolicy()).isEqualTo(DataPolicy.NORMAL); + assertThat(region.getAttributes().getStatisticsEnabled()).isTrue(); + assertThat(region.getAttributes().getCustomEntryIdleTimeout()) + .isInstanceOf(AnnotationBasedExpiration.class); + assertThat(region.getAttributes().getCustomEntryTimeToLive()) + .isInstanceOf(AnnotationBasedExpiration.class); + } + + @Test + public void assertClientCacheRegionExpirationPoliciesAreCorrect() { + assertRegionExpirationConfiguration(newApplicationContext(ClientCacheRegionExpirationConfiguration.class), + "People"); + } + + @Test + public void assertPeerCacheRegionExpirationPoliciesAreCorrect() { + assertRegionExpirationConfiguration(newApplicationContext(PeerCacheRegionExpirationConfiguration.class), + "People"); + } + + @ClientCacheApplication(name = "EnableExpirationConfigurationIntegrationTests", logLevel = GEMFIRE_LOG_LEVEL) + @EnableEntityDefinedRegions(basePackageClasses = Person.class, clientRegionShortcut = ClientRegionShortcut.LOCAL) + @EnableExpiration + static class ClientCacheRegionExpirationConfiguration { } + + @PeerCacheApplication(name = "EnableExpirationConfigurationIntegrationTests", logLevel = GEMFIRE_LOG_LEVEL) + @EnableEntityDefinedRegions(basePackageClasses = Person.class, serverRegionShortcut = RegionShortcut.LOCAL) + @EnableExpiration + static class PeerCacheRegionExpirationConfiguration { } + +} diff --git a/src/test/java/org/springframework/data/gemfire/config/annotation/EnableExpirationConfigurationUnitTests.java b/src/test/java/org/springframework/data/gemfire/config/annotation/EnableExpirationConfigurationUnitTests.java index be03a0b6..27a984e3 100644 --- a/src/test/java/org/springframework/data/gemfire/config/annotation/EnableExpirationConfigurationUnitTests.java +++ b/src/test/java/org/springframework/data/gemfire/config/annotation/EnableExpirationConfigurationUnitTests.java @@ -18,30 +18,26 @@ package org.springframework.data.gemfire.config.annotation; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.springframework.data.gemfire.config.annotation.EnableExpiration.ExpirationPolicy; import static org.springframework.data.gemfire.config.annotation.EnableExpiration.ExpirationType; -import java.util.concurrent.atomic.AtomicReference; +import java.util.Optional; -import org.apache.geode.cache.AttributesMutator; import org.apache.geode.cache.CustomExpiry; import org.apache.geode.cache.ExpirationAction; import org.apache.geode.cache.ExpirationAttributes; +import org.apache.geode.cache.GemFireCache; import org.apache.geode.cache.Region; -import org.apache.geode.cache.RegionAttributes; import org.junit.After; import org.junit.Test; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; +import org.springframework.data.gemfire.LocalRegionFactoryBean; import org.springframework.data.gemfire.expiration.ExpirationActionType; +import org.springframework.data.gemfire.test.mock.annotation.EnableGemFireMockObjects; import org.springframework.data.gemfire.util.ArrayUtils; /** @@ -64,42 +60,43 @@ public class EnableExpirationConfigurationUnitTests { @After public void tearDown() { - if (applicationContext != null) { - applicationContext.close(); - } + Optional.ofNullable(this.applicationContext).ifPresent(ConfigurableApplicationContext::close); } - protected void assertRegionExpiration(ExpirationAttributes expectedExpirationAttributes, + @SuppressWarnings({ "unchecked", "unused" }) + private void assertRegionExpiration(ExpirationAttributes expectedExpirationAttributes, Region region, V... applicationDomainObjects) { assertIdleTimeoutExpiration(expectedExpirationAttributes, region, applicationDomainObjects); assertTimeToLiveExpiration(expectedExpirationAttributes, region, applicationDomainObjects); } - protected void assertIdleTimeoutExpiration(ExpirationAttributes expectedExpirationAttributes, + @SuppressWarnings("unchecked") + private void assertIdleTimeoutExpiration(ExpirationAttributes expectedExpirationAttributes, Region region, V... applicationDomainObjects) { assertExpiration(expectedExpirationAttributes, region.getAttributes().getCustomEntryIdleTimeout(), applicationDomainObjects); } - protected void assertNoIdleTimeoutExpiration(Region region) { + private void assertNoIdleTimeoutExpiration(Region region) { assertThat(region.getAttributes().getCustomEntryIdleTimeout()).isNull(); } - protected void assertTimeToLiveExpiration(ExpirationAttributes expectedExpirationAttributes, + @SuppressWarnings("unchecked") + private void assertTimeToLiveExpiration(ExpirationAttributes expectedExpirationAttributes, Region region, V... applicationDomainObjects) { assertExpiration(expectedExpirationAttributes, region.getAttributes().getCustomEntryTimeToLive(), applicationDomainObjects); } - protected void assertNoTimeToLiveExpiration(Region region) { + private void assertNoTimeToLiveExpiration(Region region) { assertThat(region.getAttributes().getCustomEntryTimeToLive()).isNull(); } @SuppressWarnings("unchecked") - protected void assertExpiration(ExpirationAttributes expectedExpirationAttributes, + private void assertExpiration(ExpirationAttributes expectedExpirationAttributes, CustomExpiry customExpiry, V... applicationDomainObjects) { Region.Entry regionEntry = mockRegionEntry(ArrayUtils.getFirst(applicationDomainObjects)); @@ -108,32 +105,34 @@ public class EnableExpirationConfigurationUnitTests { } @SuppressWarnings({ "unchecked", "unused" }) - protected void assertExpiration(ExpirationAttributes actualExpirationAttributes, + private void assertExpiration(ExpirationAttributes actualExpirationAttributes, ExpirationAttributes expectedExpirationAttributes) { assertThat(actualExpirationAttributes).isEqualTo(expectedExpirationAttributes); } @SuppressWarnings("unchecked") - protected Region getRegion(String beanName) { - return applicationContext.getBean(beanName, Region.class); + private Region getRegion(String beanName) { + return this.applicationContext.getBean(beanName, Region.class); } - protected AnnotationConfigApplicationContext newApplicationContext(Class... annotatedClasses) { + private AnnotationConfigApplicationContext newApplicationContext(Class... annotatedClasses) { return new AnnotationConfigApplicationContext(annotatedClasses); } - protected ExpirationAttributes newExpirationAttributes(int timeout, ExpirationActionType action) { + private ExpirationAttributes newExpirationAttributes(int timeout, ExpirationActionType action) { return newExpirationAttributes(timeout, action.getExpirationAction()); } - protected ExpirationAttributes newExpirationAttributes(int timeout, ExpirationAction action) { + private ExpirationAttributes newExpirationAttributes(int timeout, ExpirationAction action) { return new ExpirationAttributes(timeout, action); } @Test + @SuppressWarnings("unchecked") public void usesDefaultExpirationPolicyConfiguration() { - applicationContext = newApplicationContext(DefaultExpirationPolicyConfiguration.class); + + this.applicationContext = newApplicationContext(DefaultExpirationPolicyConfiguration.class); ExpirationAttributes expectedExpiration = newExpirationAttributes(0, ExpirationActionType.INVALIDATE); @@ -142,14 +141,15 @@ public class EnableExpirationConfigurationUnitTests { assertIdleTimeoutExpiration(expectedExpiration, one); assertIdleTimeoutExpiration(expectedExpiration, two); - - assertNoTimeToLiveExpiration(one); - assertNoTimeToLiveExpiration(two); + assertTimeToLiveExpiration(expectedExpiration, one); + assertTimeToLiveExpiration(expectedExpiration, two); } @Test - public void usesCustomExpirationPolicyConfiguration() { - applicationContext = newApplicationContext(CustomExpirationPolicyConfiguration.class); + @SuppressWarnings("unchecked") + public void usesCustomIdleTimeoutExpirationPolicyConfiguration() { + + this.applicationContext = newApplicationContext(CustomIdleTimeoutExpirationPolicyConfiguration.class); ExpirationAttributes expectedExpiration = newExpirationAttributes(300, ExpirationActionType.LOCAL_DESTROY); @@ -164,8 +164,28 @@ public class EnableExpirationConfigurationUnitTests { } @Test + @SuppressWarnings("unchecked") + public void usesCustomTimeToLiveExpirationPolicyConfiguration() { + + this.applicationContext = newApplicationContext(CustomTimeToLiveTimeoutExpirationPolicyConfiguration.class); + + ExpirationAttributes expectedExpiration = newExpirationAttributes(900, ExpirationActionType.LOCAL_INVALIDATE); + + Region one = getRegion("One"); + Region two = getRegion("Two"); + + assertTimeToLiveExpiration(expectedExpiration, one); + assertTimeToLiveExpiration(expectedExpiration, two); + + assertNoIdleTimeoutExpiration(one); + assertNoIdleTimeoutExpiration(two); + } + + @Test + @SuppressWarnings("unchecked") public void usesRegionSpecificExpirationPolicyConfiguration() { - applicationContext = newApplicationContext(RegionSpecificExpirationPolicyConfiguration.class); + + this.applicationContext = newApplicationContext(RegionSpecificExpirationPolicyConfiguration.class); ExpirationAttributes expectedIdleTimeout = newExpirationAttributes(180, ExpirationActionType.INVALIDATE); ExpirationAttributes expectedTimeToLive = newExpirationAttributes(360, ExpirationActionType.DESTROY); @@ -181,10 +201,12 @@ public class EnableExpirationConfigurationUnitTests { } @Test + @SuppressWarnings("unchecked") public void usesMixedExpirationPolicyConfiguration() { - applicationContext = newApplicationContext(MixedExpirationPolicyConfiguration.class); - ExpirationAttributes expectedIdleTimeout = newExpirationAttributes(120, ExpirationActionType.LOCAL_INVALIDATE); + this.applicationContext = newApplicationContext(MixedExpirationPolicyConfiguration.class); + + ExpirationAttributes expectedIdleTimeout = newExpirationAttributes(60, ExpirationActionType.LOCAL_INVALIDATE); ExpirationAttributes expectedTimeToLive = newExpirationAttributes(600, ExpirationActionType.DESTROY); Region one = getRegion("One"); @@ -197,98 +219,66 @@ public class EnableExpirationConfigurationUnitTests { assertTimeToLiveExpiration(expectedTimeToLive, two); } - @SuppressWarnings("unchecked") - static Region mockRegion(String name) { - Region mockRegion = mock(Region.class); - - when(mockRegion.getName()).thenReturn(name); - when(mockRegion.getFullPath()).thenReturn(String.format("%1$s%2$s", Region.SEPARATOR, name)); - - final AtomicReference> entryIdleTimeout = new AtomicReference>(null); - final AtomicReference> entryTimeToLive = new AtomicReference>(null); - - AttributesMutator mockAttributesMutator = mock(AttributesMutator.class); - - when(mockRegion.getAttributesMutator()).thenReturn(mockAttributesMutator); - - doAnswer(new Answer>() { - @Override - public CustomExpiry answer(InvocationOnMock invocation) throws Throwable { - CustomExpiry customExpiry = invocation.getArgument(0); - entryIdleTimeout.set(customExpiry); - return customExpiry; - } - }).when(mockAttributesMutator).setCustomEntryIdleTimeout(any(CustomExpiry.class)); - - doAnswer(new Answer>() { - @Override - public CustomExpiry answer(InvocationOnMock invocation) throws Throwable { - CustomExpiry customExpiry = invocation.getArgument(0); - entryTimeToLive.set(customExpiry); - return customExpiry; - } - }).when(mockAttributesMutator).setCustomEntryTimeToLive(any(CustomExpiry.class)); - - RegionAttributes mockRegionAttributes = mock(RegionAttributes.class); - - when(mockRegion.getAttributes()).thenReturn(mockRegionAttributes); - - when(mockRegionAttributes.getCustomEntryIdleTimeout()).thenAnswer(new Answer>() { - @Override public CustomExpiry answer(InvocationOnMock invocation) throws Throwable { - return entryIdleTimeout.get(); - } - }); - - when(mockRegionAttributes.getCustomEntryTimeToLive()).thenAnswer(new Answer>() { - @Override public CustomExpiry answer(InvocationOnMock invocation) throws Throwable { - return entryTimeToLive.get(); - } - }); - - return mockRegion; - } - @SuppressWarnings("unchecked") static Region.Entry mockRegionEntry(V applicationDomainObject) { + Region.Entry mockRegionEntry = mock(Region.Entry.class); + when(mockRegionEntry.getValue()).thenReturn(applicationDomainObject); + return mockRegionEntry; } - @Configuration + @PeerCacheApplication + @EnableGemFireMockObjects @SuppressWarnings("unused") static class RegionConfiguration { @Bean("One") - Region regionOne() { - return mockRegion("One"); + public LocalRegionFactoryBean regionOne(GemFireCache gemfireCache) { + + LocalRegionFactoryBean regionOne = new LocalRegionFactoryBean<>(); + + regionOne.setCache(gemfireCache); + regionOne.setClose(false); + regionOne.setPersistent(false); + + return regionOne; } @Bean("Two") - Region regionTwo() { - return mockRegion("Two"); + public LocalRegionFactoryBean regionTwo(GemFireCache gemfireCache) { + + LocalRegionFactoryBean regionTwo = new LocalRegionFactoryBean<>(); + + regionTwo.setCache(gemfireCache); + regionTwo.setClose(false); + regionTwo.setPersistent(false); + + return regionTwo; } + } @EnableExpiration - static class DefaultExpirationPolicyConfiguration extends RegionConfiguration { - } + static class DefaultExpirationPolicyConfiguration extends RegionConfiguration { } @EnableExpiration(policies = { @ExpirationPolicy(timeout = 300, action = ExpirationActionType.LOCAL_DESTROY) }) - static class CustomExpirationPolicyConfiguration extends RegionConfiguration { - } + static class CustomIdleTimeoutExpirationPolicyConfiguration extends RegionConfiguration { } + + @EnableExpiration(policies = { @ExpirationPolicy(timeout = 900, action = ExpirationActionType.LOCAL_INVALIDATE, types = ExpirationType.TIME_TO_LIVE) }) + static class CustomTimeToLiveTimeoutExpirationPolicyConfiguration extends RegionConfiguration { } @EnableExpiration(policies = { @ExpirationPolicy(timeout = 180, action = ExpirationActionType.INVALIDATE, regionNames = "One"), @ExpirationPolicy(timeout = 360, action = ExpirationActionType.DESTROY, regionNames = "Two", types = ExpirationType.TIME_TO_LIVE) }) - static class RegionSpecificExpirationPolicyConfiguration extends RegionConfiguration { - } + static class RegionSpecificExpirationPolicyConfiguration extends RegionConfiguration { } @EnableExpiration(policies = { - @ExpirationPolicy(timeout = 120, action = ExpirationActionType.LOCAL_INVALIDATE, regionNames = "One", types = ExpirationType.IDLE_TIMEOUT), + @ExpirationPolicy(timeout = 60, action = ExpirationActionType.LOCAL_INVALIDATE, regionNames = "One", types = ExpirationType.IDLE_TIMEOUT), @ExpirationPolicy(timeout = 600, action = ExpirationActionType.DESTROY, types = ExpirationType.TIME_TO_LIVE) }) - static class MixedExpirationPolicyConfiguration extends RegionConfiguration { - } + static class MixedExpirationPolicyConfiguration extends RegionConfiguration { } + } diff --git a/src/test/java/org/springframework/data/gemfire/config/xml/DiskStoreAndEvictionRegionParsingTest.java b/src/test/java/org/springframework/data/gemfire/config/xml/DiskStoreAndEvictionRegionParsingTest.java index 88931714..63e4ab18 100644 --- a/src/test/java/org/springframework/data/gemfire/config/xml/DiskStoreAndEvictionRegionParsingTest.java +++ b/src/test/java/org/springframework/data/gemfire/config/xml/DiskStoreAndEvictionRegionParsingTest.java @@ -22,9 +22,9 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; +import static org.springframework.data.gemfire.util.ArrayUtils.nullSafeArray; import java.io.File; -import java.io.FilenameFilter; import org.apache.geode.cache.Cache; import org.apache.geode.cache.CustomExpiry; @@ -55,7 +55,7 @@ import org.springframework.data.gemfire.SimpleObjectSizer; import org.springframework.data.gemfire.TestUtils; import org.springframework.data.gemfire.test.GemfireTestApplicationContextInitializer; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import org.springframework.util.FileSystemUtils; /** @@ -63,7 +63,7 @@ import org.springframework.util.FileSystemUtils; * @author David Turanski * @author John Blum */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration(locations="diskstore-ns.xml", initializers=GemfireTestApplicationContextInitializer.class) @SuppressWarnings("unused") // TODO move test cases into a DiskStoreIntegrationTests class @@ -86,20 +86,19 @@ public class DiskStoreAndEvictionRegionParsingTest { @AfterClass public static void tearDown() { + FileSystemUtils.deleteRecursively(diskStoreDirectory); - for (String name : new File(".").list(new FilenameFilter() { - @Override - public boolean accept(File dir, String name) { - return name.startsWith("BACKUPds"); - } - })) { + for (String name : nullSafeArray(new File(".") + .list((dir, name) -> name.startsWith("BACKUP")), String.class)) { + new File(name).delete(); } } @Test public void testDiskStore() { + assertNotNull(applicationContext.getBean("ds2")); applicationContext.getBean("diskStore1"); assertNotNull(diskStore); @@ -117,6 +116,7 @@ public class DiskStoreAndEvictionRegionParsingTest { @Test @SuppressWarnings("rawtypes") public void testReplicatedDataRegionAttributes() throws Exception { + assertTrue(applicationContext.containsBean("replicated-data")); RegionFactoryBean replicatedDataRegionFactoryBean = applicationContext.getBean("&replicated-data", RegionFactoryBean.class); @@ -146,6 +146,7 @@ public class DiskStoreAndEvictionRegionParsingTest { @Test @SuppressWarnings("rawtypes") public void testPartitionDataOptions() throws Exception { + assertTrue(applicationContext.containsBean("partition-data")); RegionFactoryBean fb = applicationContext.getBean("&partition-data", RegionFactoryBean.class); assertTrue(fb instanceof PartitionedRegionFactoryBean); @@ -165,7 +166,9 @@ public class DiskStoreAndEvictionRegionParsingTest { @Test @SuppressWarnings("rawtypes") public void testEntryTtl() throws Exception { + assertTrue(applicationContext.containsBean("replicated-data")); + RegionFactoryBean fb = applicationContext.getBean("&replicated-data", RegionFactoryBean.class); RegionAttributes attrs = TestUtils.readField("attributes", fb); @@ -190,7 +193,9 @@ public class DiskStoreAndEvictionRegionParsingTest { @Test @SuppressWarnings("rawtypes") public void testCustomExpiry() throws Exception { + assertTrue(applicationContext.containsBean("replicated-data-custom-expiry")); + RegionFactoryBean fb = applicationContext.getBean("&replicated-data-custom-expiry", RegionFactoryBean.class); RegionAttributes attrs = TestUtils.readField("attributes", fb); @@ -202,14 +207,14 @@ public class DiskStoreAndEvictionRegionParsingTest { } public static class TestCustomExpiry implements CustomExpiry { + @Override public ExpirationAttributes getExpiry(Entry entry) { return null; } @Override - public void close() { + public void close() { } - } } } diff --git a/src/test/java/org/springframework/data/gemfire/config/xml/DiskStoreNamespaceTest.java b/src/test/java/org/springframework/data/gemfire/config/xml/DiskStoreNamespaceTest.java index c033fbfd..b17fe18b 100644 --- a/src/test/java/org/springframework/data/gemfire/config/xml/DiskStoreNamespaceTest.java +++ b/src/test/java/org/springframework/data/gemfire/config/xml/DiskStoreNamespaceTest.java @@ -29,7 +29,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.data.gemfire.test.GemfireTestApplicationContextInitializer; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; /** * The DiskStoreNamespaceTest class is a test suite of test cases testing the contract and functionality of using @@ -42,7 +42,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; * @see org.springframework.test.context.junit4.SpringJUnit4ClassRunner * @since 2.0.0 */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration(locations = "diskstore-ns.xml", initializers = GemfireTestApplicationContextInitializer.class) @SuppressWarnings("unused") public class DiskStoreNamespaceTest { @@ -57,6 +57,7 @@ public class DiskStoreNamespaceTest { @Test public void testDiskStoreConfiguration() { + assertNotNull("The 'fullyConfiguredDiskStore' was not properly configured and initialized", diskStore); assertEquals("fullyConfiguredDiskStore", diskStore.getName()); assertEquals(Boolean.valueOf(props.getProperty("allowForceCompaction")), diskStore.getAllowForceCompaction()); @@ -76,5 +77,4 @@ public class DiskStoreNamespaceTest { assertEquals(new File(props.getProperty("location")), diskStore.getDiskDirs()[0]); assertEquals(Long.valueOf(props.getProperty("maxSize")), Long.valueOf(diskStore.getDiskDirSizes()[0])); } - } diff --git a/src/test/java/org/springframework/data/gemfire/config/xml/RegionExpirationAttributesNamespaceTest.java b/src/test/java/org/springframework/data/gemfire/config/xml/RegionExpirationAttributesNamespaceTest.java index 4ff29584..7be99e6a 100644 --- a/src/test/java/org/springframework/data/gemfire/config/xml/RegionExpirationAttributesNamespaceTest.java +++ b/src/test/java/org/springframework/data/gemfire/config/xml/RegionExpirationAttributesNamespaceTest.java @@ -32,7 +32,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.data.gemfire.test.GemfireTestApplicationContextInitializer; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import org.springframework.util.Assert; /** @@ -50,7 +50,7 @@ import org.springframework.util.Assert; * @see org.apache.geode.cache.EvictionAttributes * @since 1.5.0 */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration(initializers = GemfireTestApplicationContextInitializer.class) @SuppressWarnings("unused") public class RegionExpirationAttributesNamespaceTest { @@ -67,12 +67,13 @@ public class RegionExpirationAttributesNamespaceTest { @Resource(name = "LocalExample") private Region localExample; - protected void assertRegionMetaData(final Region region, final String regionName, final DataPolicy dataPolicy) { + private void assertRegionMetaData(final Region region, final String regionName, final DataPolicy dataPolicy) { assertRegionMetaData(region, regionName, Region.SEPARATOR + regionName, dataPolicy); } - protected void assertRegionMetaData(final Region region, final String regionName, final String regionFullPath, - final DataPolicy dataPolicy) { + private void assertRegionMetaData(Region region, String regionName, String regionFullPath, + DataPolicy dataPolicy) { + assertNotNull(String.format("The '%1$s' Region was not properly configured and initialized!", regionName), region); assertEquals(regionName, region.getName()); assertEquals(regionFullPath, region.getFullPath()); @@ -80,14 +81,15 @@ public class RegionExpirationAttributesNamespaceTest { assertEquals(dataPolicy, region.getAttributes().getDataPolicy()); } - protected void assertNoExpiration(final ExpirationAttributes expirationAttributes) { + private void assertNoExpiration(final ExpirationAttributes expirationAttributes) { + if (expirationAttributes != null) { //assertEquals(ExpirationAction.INVALIDATE, expirationAttributes.getAction()); assertEquals(0, expirationAttributes.getTimeout()); } } - protected void assertExpirationAttributes(final ExpirationAttributes expirationAttributes, + private void assertExpirationAttributes(ExpirationAttributes expirationAttributes, final int timeout, final ExpirationAction action) { assertNotNull(expirationAttributes); assertEquals(timeout, expirationAttributes.getTimeout()); @@ -95,8 +97,9 @@ public class RegionExpirationAttributesNamespaceTest { } @SuppressWarnings("unchecked") - protected void assertCustomExpiry(final CustomExpiry customExpiry, final String name, - final int timeout, final ExpirationAction action) { + private void assertCustomExpiry(CustomExpiry customExpiry, String name, int timeout, + ExpirationAction action) { + assertNotNull(customExpiry); assertEquals(name, customExpiry.toString()); assertExpirationAttributes(customExpiry.getExpiry(mock(Region.Entry.class)), timeout, action); @@ -104,6 +107,7 @@ public class RegionExpirationAttributesNamespaceTest { @Test public void testReplicateExampleExpirationAttributes() { + assertRegionMetaData(replicateExample, "ReplicateExample", DataPolicy.REPLICATE); assertExpirationAttributes(replicateExample.getAttributes().getEntryTimeToLive(), 600, ExpirationAction.DESTROY); @@ -115,6 +119,7 @@ public class RegionExpirationAttributesNamespaceTest { @Test public void testPreloadedExampleExpirationAttributes() { + assertRegionMetaData(preloadedExample, "PreloadedExample", DataPolicy.PRELOADED); assertExpirationAttributes(preloadedExample.getAttributes().getEntryTimeToLive(), 120, ExpirationAction.LOCAL_DESTROY); @@ -125,6 +130,7 @@ public class RegionExpirationAttributesNamespaceTest { @Test public void testPartitionExampleExpirationAttributes() { + assertRegionMetaData(partitionExample, "PartitionExample", DataPolicy.PARTITION); assertExpirationAttributes(partitionExample.getAttributes().getEntryTimeToLive(), 300, ExpirationAction.DESTROY); @@ -136,6 +142,7 @@ public class RegionExpirationAttributesNamespaceTest { @Test public void testLocalExampleExpirationAttributes() { + assertRegionMetaData(localExample, "LocalExample", DataPolicy.NORMAL); assertNoExpiration(localExample.getAttributes().getEntryTimeToLive()); assertNoExpiration(localExample.getAttributes().getEntryIdleTimeout()); @@ -181,5 +188,4 @@ public class RegionExpirationAttributesNamespaceTest { return this.name; } } - } diff --git a/src/test/java/org/springframework/data/gemfire/config/xml/TemplateClientRegionNamespaceTest.java b/src/test/java/org/springframework/data/gemfire/config/xml/TemplateClientRegionNamespaceTest.java index f261a18f..5a3edd78 100644 --- a/src/test/java/org/springframework/data/gemfire/config/xml/TemplateClientRegionNamespaceTest.java +++ b/src/test/java/org/springframework/data/gemfire/config/xml/TemplateClientRegionNamespaceTest.java @@ -44,7 +44,7 @@ import org.apache.geode.cache.util.ObjectSizer; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import org.springframework.util.StringUtils; /** @@ -61,7 +61,7 @@ import org.springframework.util.StringUtils; * @see org.apache.geode.cache.Region * @since 1.5.0 */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration @SuppressWarnings("unused") public class TemplateClientRegionNamespaceTest { @@ -69,7 +69,8 @@ public class TemplateClientRegionNamespaceTest { @Resource(name = "TemplateBasedClientRegion") private Region templateBasedClientRegion; - protected void assertCacheListeners(final Region region, final String... expectedNames) { + private void assertCacheListeners(Region region, String... expectedNames) { + assertNotNull(region); assertNotNull(region.getAttributes()); assertNotNull(region.getAttributes().getCacheListeners()); @@ -81,31 +82,28 @@ public class TemplateClientRegionNamespaceTest { } } - protected void assertCacheLoader(final Region region, final String expectedName) { + private void assertCacheLoader(Region region, String expectedName) { assertNotNull(region); assertNotNull(region.getAttributes()); assertTrue(region.getAttributes().getCacheLoader() instanceof TestCacheLoader); assertEquals(expectedName, region.getAttributes().getCacheLoader().toString()); } - protected void assertCacheWriter(final Region region, final String expectedName) { + private void assertCacheWriter(Region region, String expectedName) { assertNotNull(region); assertNotNull(region.getAttributes()); assertTrue(region.getAttributes().getCacheWriter() instanceof TestCacheWriter); assertEquals(expectedName, region.getAttributes().getCacheWriter().toString()); } - protected void assertDefaultEvictionAttributes(final EvictionAttributes evictionAttributes) { + private void assertDefaultEvictionAttributes(EvictionAttributes evictionAttributes) { assumeNotNull(evictionAttributes); assertEvictionAttributes(evictionAttributes, EvictionAction.NONE, EvictionAlgorithm.NONE, 0, null); } - protected void assertEvictionAttributes(final EvictionAttributes evictionAttributes, - final EvictionAction expectedAction, - final EvictionAlgorithm expectedAlgorithm, - final int expectedMaximum, - final ObjectSizer expectedObjectSizer) - { + private void assertEvictionAttributes(EvictionAttributes evictionAttributes, EvictionAction expectedAction, + EvictionAlgorithm expectedAlgorithm, int expectedMaximum, ObjectSizer expectedObjectSizer) { + assertNotNull("The 'EvictionAttributes' must not be null!", evictionAttributes); assertEquals(expectedAction, evictionAttributes.getAction()); assertEquals(expectedAlgorithm, evictionAttributes.getAlgorithm()); @@ -113,22 +111,22 @@ public class TemplateClientRegionNamespaceTest { assertEquals(expectedObjectSizer, evictionAttributes.getObjectSizer()); } - protected void assertDefaultExpirationAttributes(final ExpirationAttributes expirationAttributes) { + private void assertDefaultExpirationAttributes(ExpirationAttributes expirationAttributes) { assumeNotNull(expirationAttributes); assertEquals(ExpirationAction.INVALIDATE, expirationAttributes.getAction()); assertEquals(0, expirationAttributes.getTimeout()); } - protected void assertExpirationAttributes(final ExpirationAttributes expirationAttributes, - final ExpirationAction expectedAction, - final int expectedTimeout) - { + private void assertExpirationAttributes(ExpirationAttributes expirationAttributes, ExpirationAction expectedAction, + int expectedTimeout) { + assertNotNull("The 'ExpirationAttributes' must not be null!", expirationAttributes); assertEquals(expectedAction, expirationAttributes.getAction()); assertEquals(expectedTimeout, expirationAttributes.getTimeout()); } - protected void assertDefaultRegionAttributes(final Region region) { + private void assertDefaultRegionAttributes(Region region) { + assertNotNull("The Region must not be null!", region); assertNotNull(String.format("The Region (%1$s) must have 'RegionAttributes' defined!", region.getFullPath()), region.getAttributes()); @@ -141,23 +139,24 @@ public class TemplateClientRegionNamespaceTest { assertDefaultExpirationAttributes(region.getAttributes().getRegionIdleTimeout()); } - protected static void assertEmpty(final Object[] array) { + private static void assertEmpty(Object[] array) { assertTrue((array == null || array.length == 0)); } - protected static void assertEmpty(final Iterable collection) { + private static void assertEmpty(Iterable collection) { assertTrue(collection == null || !collection.iterator().hasNext()); } - protected static void assertNullEmpty(final String value) { + private static void assertNullEmpty(String value) { assertFalse(StringUtils.hasText(value)); } - protected static void assertRegionMetaData(final Region region, final String expectedRegionName) { + private static void assertRegionMetaData(Region region, String expectedRegionName) { assertRegionMetaData(region, expectedRegionName, Region.SEPARATOR + expectedRegionName); } - protected static void assertRegionMetaData(final Region region, final String expectedRegionName, final String expectedRegionPath) { + private static void assertRegionMetaData(Region region, String expectedRegionName, String expectedRegionPath) { + assertNotNull(String.format("The '%1$s' Region was not properly configured and initialized!", expectedRegionName), region); assertEquals(expectedRegionName, region.getName()); @@ -168,6 +167,7 @@ public class TemplateClientRegionNamespaceTest { @Test public void testTemplateBasedClientRegion() { + assertRegionMetaData(templateBasedClientRegion, "TemplateBasedClientRegion"); assertDefaultRegionAttributes(templateBasedClientRegion); assertCacheListeners(templateBasedClientRegion, "XYZ"); @@ -193,7 +193,7 @@ public class TemplateClientRegionNamespaceTest { private String name; - public void setName(final String name) { + public void setName(String name) { this.name = name; } @@ -207,18 +207,17 @@ public class TemplateClientRegionNamespaceTest { private String name; - public void setName(final String name) { + public void setName(String name) { this.name = name; } @Override - public Object load(final LoaderHelper loaderHelper) throws CacheLoaderException { + public Object load(LoaderHelper loaderHelper) throws CacheLoaderException { return null; } @Override - public void close() { - } + public void close() { } @Override public String toString() { @@ -230,7 +229,7 @@ public class TemplateClientRegionNamespaceTest { private String name; - public void setName(final String name) { + public void setName(String name) { this.name = name; } @@ -239,5 +238,4 @@ public class TemplateClientRegionNamespaceTest { return name; } } - } diff --git a/src/test/java/org/springframework/data/gemfire/config/xml/TemplateRegionsNamespaceTests.java b/src/test/java/org/springframework/data/gemfire/config/xml/TemplateRegionsNamespaceTests.java index 7f400b9e..a9b70ee5 100644 --- a/src/test/java/org/springframework/data/gemfire/config/xml/TemplateRegionsNamespaceTests.java +++ b/src/test/java/org/springframework/data/gemfire/config/xml/TemplateRegionsNamespaceTests.java @@ -65,7 +65,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.data.gemfire.test.GemfireTestApplicationContextInitializer; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; @@ -84,7 +84,7 @@ import org.springframework.util.StringUtils; * @see org.apache.geode.cache.Region * @since 1.5.0 */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration(initializers = GemfireTestApplicationContextInitializer.class) @SuppressWarnings("unused") public class TemplateRegionsNamespaceTests { @@ -110,7 +110,8 @@ public class TemplateRegionsNamespaceTests { @Resource(name = "TemplateBasedLocalRegion") private Region templateBasedLocalRegion; - protected void assertAsyncEventQueues(final Region region, final String... expectedNames) { + private void assertAsyncEventQueues(Region region, String... expectedNames) { + assertNotNull(region); assertNotNull(region.getAttributes()); assertNotNull(region.getAttributes().getAsyncEventQueueIds()); @@ -121,7 +122,8 @@ public class TemplateRegionsNamespaceTests { } } - protected void assertCacheListeners(final Region region, final String... expectedNames) { + private void assertCacheListeners(Region region, String... expectedNames) { + assertNotNull(region); assertNotNull(region.getAttributes()); assertNotNull(region.getAttributes().getCacheListeners()); @@ -133,31 +135,30 @@ public class TemplateRegionsNamespaceTests { } } - protected void assertCacheLoader(final Region region, final String expectedName) { + private void assertCacheLoader(Region region, String expectedName) { + assertNotNull(region); assertNotNull(region.getAttributes()); assertTrue(region.getAttributes().getCacheLoader() instanceof TestCacheLoader); assertEquals(expectedName, region.getAttributes().getCacheLoader().toString()); } - protected void assertCacheWriter(final Region region, final String expectedName) { + private void assertCacheWriter(Region region, String expectedName) { + assertNotNull(region); assertNotNull(region.getAttributes()); assertTrue(region.getAttributes().getCacheWriter() instanceof TestCacheWriter); assertEquals(expectedName, region.getAttributes().getCacheWriter().toString()); } - protected void assertDefaultEvictionAttributes(final EvictionAttributes evictionAttributes) { + private void assertDefaultEvictionAttributes(EvictionAttributes evictionAttributes) { assumeNotNull(evictionAttributes); assertEvictionAttributes(evictionAttributes, EvictionAction.NONE, EvictionAlgorithm.NONE, 0, null); } - protected void assertEvictionAttributes(final EvictionAttributes evictionAttributes, - final EvictionAction expectedAction, - final EvictionAlgorithm expectedAlgorithm, - final int expectedMaximum, - final ObjectSizer expectedObjectSizer) - { + private void assertEvictionAttributes(EvictionAttributes evictionAttributes, EvictionAction expectedAction, + EvictionAlgorithm expectedAlgorithm, int expectedMaximum, ObjectSizer expectedObjectSizer) { + assertNotNull("The 'EvictionAttributes' must not be null!", evictionAttributes); assertEquals(expectedAction, evictionAttributes.getAction()); assertEquals(expectedAlgorithm, evictionAttributes.getAlgorithm()); @@ -165,22 +166,23 @@ public class TemplateRegionsNamespaceTests { assertEquals(expectedObjectSizer, evictionAttributes.getObjectSizer()); } - protected void assertDefaultExpirationAttributes(final ExpirationAttributes expirationAttributes) { + private void assertDefaultExpirationAttributes(ExpirationAttributes expirationAttributes) { + assumeNotNull(expirationAttributes); assertEquals(ExpirationAction.INVALIDATE, expirationAttributes.getAction()); assertEquals(0, expirationAttributes.getTimeout()); } - protected void assertExpirationAttributes(final ExpirationAttributes expirationAttributes, - final ExpirationAction expectedAction, - final int expectedTimeout) - { + private void assertExpirationAttributes(ExpirationAttributes expirationAttributes, ExpirationAction expectedAction, + int expectedTimeout) { + assertNotNull("The 'ExpirationAttributes' must not be null!", expirationAttributes); assertEquals(expectedAction, expirationAttributes.getAction()); assertEquals(expectedTimeout, expirationAttributes.getTimeout()); } - protected void assertGatewaySenders(final Region region, final String... gatewaySenderIds) { + private void assertGatewaySenders(Region region, String... gatewaySenderIds) { + assertNotNull(region); assertNotNull(region.getAttributes()); assertNotNull(region.getAttributes().getGatewaySenderIds()); @@ -188,16 +190,15 @@ public class TemplateRegionsNamespaceTests { assertTrue(Arrays.asList(gatewaySenderIds).containsAll(region.getAttributes().getGatewaySenderIds())); } - protected void assertDefaultMembershipAttributes(final MembershipAttributes membershipAttributes) { + private void assertDefaultMembershipAttributes(MembershipAttributes membershipAttributes) { + assumeNotNull(membershipAttributes); assertMembershipAttributes(membershipAttributes, LossAction.FULL_ACCESS, ResumptionAction.NONE); } - protected void assertMembershipAttributes(final MembershipAttributes membershipAttributes, - final LossAction expectedLossAction, - final ResumptionAction expectedResumptionAction, - final String... expectedRequiredRoles) - { + private void assertMembershipAttributes(MembershipAttributes membershipAttributes, LossAction expectedLossAction, + ResumptionAction expectedResumptionAction, String... expectedRequiredRoles) { + assertNotNull("The 'MembershipAttributes' must not be null!", membershipAttributes); assertEquals(expectedLossAction, membershipAttributes.getLossAction()); assertEquals(expectedResumptionAction, membershipAttributes.getResumptionAction()); @@ -210,7 +211,8 @@ public class TemplateRegionsNamespaceTests { } } - protected void assertPartitionListener(final Region region, final String... expectedNames) { + private void assertPartitionListener(Region region, String... expectedNames) { + assertNotNull(region); assertNotNull(region.getAttributes()); assertNotNull(region.getAttributes().getPartitionAttributes()); @@ -223,16 +225,17 @@ public class TemplateRegionsNamespaceTests { } } - protected void assertPartitionResolver(final Region region, final String expectedName) { + private void assertPartitionResolver(Region region, String expectedName) { + assertNotNull(region); assertNotNull(region.getAttributes()); assertNotNull(region.getAttributes().getPartitionAttributes()); - assertTrue( - region.getAttributes().getPartitionAttributes().getPartitionResolver() instanceof TestPartitionResolver); + assertTrue(region.getAttributes().getPartitionAttributes().getPartitionResolver() instanceof TestPartitionResolver); assertEquals(expectedName, region.getAttributes().getPartitionAttributes().getPartitionResolver().toString()); } - protected void assertDefaultRegionAttributes(final Region region) { + private void assertDefaultRegionAttributes(Region region) { + assertNotNull("The Region must not be null!", region); assertNotNull(String.format("Region (%1$s) must have 'RegionAttributes' defined!", region.getFullPath()), region.getAttributes()); @@ -246,35 +249,37 @@ public class TemplateRegionsNamespaceTests { assertDefaultExpirationAttributes(region.getAttributes().getRegionIdleTimeout()); } - protected void assertDefaultSubscriptionAttributes(final SubscriptionAttributes subscriptionAttributes) { + private void assertDefaultSubscriptionAttributes(SubscriptionAttributes subscriptionAttributes) { + assumeNotNull(subscriptionAttributes); assertSubscriptionAttributes(subscriptionAttributes, InterestPolicy.DEFAULT); } - protected void assertSubscriptionAttributes(final SubscriptionAttributes subscriptionAttributes, - final InterestPolicy expectedInterestPolicy) - { + private void assertSubscriptionAttributes(SubscriptionAttributes subscriptionAttributes, + InterestPolicy expectedInterestPolicy) { + assertNotNull("The 'SubscriptionAttributes' must not be null!", subscriptionAttributes); assertEquals(expectedInterestPolicy, subscriptionAttributes.getInterestPolicy()); } - protected static void assertEmpty(final Object[] array) { + private static void assertEmpty(Object[] array) { assertTrue((array == null || array.length == 0)); } - protected static void assertEmpty(final Iterable collection) { + private static void assertEmpty(Iterable collection) { assertTrue(collection == null || !collection.iterator().hasNext()); } - protected static void assertNullEmpty(final String value) { + private static void assertNullEmpty(String value) { assertFalse(StringUtils.hasText(value)); } - protected static void assertRegionMetaData(final Region region, final String expectedRegionName) { + private static void assertRegionMetaData(Region region, String expectedRegionName) { assertRegionMetaData(region, expectedRegionName, Region.SEPARATOR + expectedRegionName); } - protected static void assertRegionMetaData(final Region region, final String expectedRegionName, final String expectedRegionPath) { + private static void assertRegionMetaData(Region region, String expectedRegionName, String expectedRegionPath) { + assertNotNull(String.format("The '%1$s' Region was not properly configured and initialized!", expectedRegionName), region); assertEquals(expectedRegionName, region.getName()); @@ -285,6 +290,7 @@ public class TemplateRegionsNamespaceTests { @Test public void testNoAbstractRegionTemplateBeans() { + String[] beanNames = { "BaseRegionTemplate", "ExtendedRegionTemplate", @@ -311,6 +317,7 @@ public class TemplateRegionsNamespaceTests { @Test public void testNonTemplateBasedReplicateRegion() { + assertRegionMetaData(nonTemplateBasedReplicateRegion, "NonTemplateBasedReplicateRegion"); assertDefaultRegionAttributes(nonTemplateBasedReplicateRegion); assertEmpty(nonTemplateBasedReplicateRegion.getAttributes().getAsyncEventQueueIds()); @@ -344,6 +351,7 @@ public class TemplateRegionsNamespaceTests { @Test public void testTemplateBasedReplicateRegion() { + assertRegionMetaData(templateBasedReplicateRegion, "TemplateBasedReplicateRegion"); assertDefaultRegionAttributes(templateBasedReplicateRegion); assertEmpty(templateBasedReplicateRegion.getAttributes().getAsyncEventQueueIds()); @@ -381,6 +389,7 @@ public class TemplateRegionsNamespaceTests { @Test public void testTemplateBasedReplicateSubRegion() { + assertRegionMetaData(templateBasedReplicateSubRegion, "TemplateBasedReplicateSubRegion", "/TemplateBasedReplicateRegion/TemplateBasedReplicateSubRegion"); assertDefaultRegionAttributes(templateBasedReplicateSubRegion); @@ -418,6 +427,7 @@ public class TemplateRegionsNamespaceTests { @Test public void testTemplateBasedReplicateRegionNoOverrides() { + assertRegionMetaData(templateBasedReplicateRegionNoOverrides, "TemplateBasedReplicateRegionNoOverrides"); assertDefaultRegionAttributes(templateBasedReplicateRegionNoOverrides); assertEmpty(templateBasedReplicateRegionNoOverrides.getAttributes().getAsyncEventQueueIds()); @@ -457,6 +467,7 @@ public class TemplateRegionsNamespaceTests { @Test public void testTemplateBasedPartitionRegion() { + assertRegionMetaData(templateBasedPartitionRegion, "TemplateBasedPartitionRegion"); assertDefaultRegionAttributes(templateBasedPartitionRegion); assertAsyncEventQueues(templateBasedPartitionRegion, "TestAsyncEventQueue"); @@ -504,6 +515,7 @@ public class TemplateRegionsNamespaceTests { @Test public void testTemplateBasedLocalRegion() { + assertRegionMetaData(templateBasedLocalRegion, "TemplateBasedLocalRegion"); assertDefaultRegionAttributes(templateBasedLocalRegion); assertEmpty(templateBasedLocalRegion.getAttributes().getAsyncEventQueueIds()); @@ -542,18 +554,17 @@ public class TemplateRegionsNamespaceTests { private String name; - public void setName(final String name) { + public void setName(String name) { this.name = name; } @Override - public boolean processEvents(final List asyncEvents) { + public boolean processEvents(List asyncEvents) { return false; } @Override - public void close() { - } + public void close() { } @Override public String toString() { @@ -565,7 +576,7 @@ public class TemplateRegionsNamespaceTests { private String name; - public void setName(final String name) { + public void setName(String name) { this.name = name; } @@ -579,18 +590,17 @@ public class TemplateRegionsNamespaceTests { private String name; - public void setName(final String name) { + public void setName(String name) { this.name = name; } @Override - public Object load(final LoaderHelper loaderHelper) throws CacheLoaderException { + public Object load(LoaderHelper loaderHelper) throws CacheLoaderException { return null; } @Override - public void close() { - } + public void close() { } @Override public String toString() { @@ -602,7 +612,7 @@ public class TemplateRegionsNamespaceTests { private String name; - public void setName(final String name) { + public void setName(String name) { this.name = name; } @@ -616,7 +626,7 @@ public class TemplateRegionsNamespaceTests { private String name; - public void setName(final String name) { + public void setName(String name) { this.name = name; } @@ -630,12 +640,12 @@ public class TemplateRegionsNamespaceTests { private String name; - public void setName(final String name) { + public void setName(String name) { this.name = name; } @Override - public Object getRoutingObject(final EntryOperation entryOperation) { + public Object getRoutingObject(EntryOperation entryOperation) { return null; } @@ -645,13 +655,11 @@ public class TemplateRegionsNamespaceTests { } @Override - public void close() { - } + public void close() { } @Override public String toString() { return name; } } - } diff --git a/src/test/java/org/springframework/data/gemfire/expiration/AnnotationBasedExpirationConfigurationIntegrationTest.java b/src/test/java/org/springframework/data/gemfire/expiration/AnnotationBasedExpirationConfigurationIntegrationTest.java index 7d052c91..e2c0a65d 100644 --- a/src/test/java/org/springframework/data/gemfire/expiration/AnnotationBasedExpirationConfigurationIntegrationTest.java +++ b/src/test/java/org/springframework/data/gemfire/expiration/AnnotationBasedExpirationConfigurationIntegrationTest.java @@ -44,7 +44,7 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.data.gemfire.test.GemfireTestApplicationContextInitializer; import org.springframework.expression.EvaluationException; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; /** * The AnnotationBasedExpirationConfigurationIntegrationTest class is a test suite of test cases testing @@ -64,13 +64,13 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; * @see org.apache.geode.cache.ExpirationAttributes * @since 1.7.0 */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration(initializers = GemfireTestApplicationContextInitializer.class) @SuppressWarnings("unused") public class AnnotationBasedExpirationConfigurationIntegrationTest { @Rule - public ExpectedException expectedException = ExpectedException.none(); + public ExpectedException exception = ExpectedException.none(); @Autowired @Qualifier("genericExpiration") @@ -107,11 +107,11 @@ public class AnnotationBasedExpirationConfigurationIntegrationTest { assertThat(timeToLiveExpiration.getDefaultExpirationAttributes(), is(sameInstance(defaultExpirationAttributes))); } - protected void assertExpiration(ExpirationAttributes expected, ExpirationAttributes actual) { + private void assertExpiration(ExpirationAttributes expected, ExpirationAttributes actual) { assertExpiration(actual, expected.getTimeout(), expected.getAction()); } - protected void assertExpiration(ExpirationAttributes expirationAttributes, int expectedTimeout, + private void assertExpiration(ExpirationAttributes expirationAttributes, int expectedTimeout, ExpirationAction expectedAction) { assertThat(expirationAttributes, is(not(nullValue()))); @@ -120,7 +120,8 @@ public class AnnotationBasedExpirationConfigurationIntegrationTest { } @SuppressWarnings("unchecked") - protected Region.Entry mockRegionEntry(Object value) { + private Region.Entry mockRegionEntry(Object value) { + Region.Entry mockRegionEntry = mock(Region.Entry.class, "MockRegionEntry"); when(mockRegionEntry.getValue()).thenReturn(value); @@ -130,6 +131,7 @@ public class AnnotationBasedExpirationConfigurationIntegrationTest { @Test public void exampleRegionIdleTimeoutExpirationPolicy() { + CustomExpiry expiration = example.getAttributes().getCustomEntryIdleTimeout(); assertExpiration(expiration.getExpiry(mockRegionEntry(new ApplicationDomainObjectWithTimeToLiveAndGenericExpirationPolicies())), @@ -148,6 +150,7 @@ public class AnnotationBasedExpirationConfigurationIntegrationTest { @Test public void exampleRegionTimeToLiveExpirationPolicy() { + CustomExpiry expiration = example.getAttributes().getCustomEntryTimeToLive(); assertExpiration(expiration.getExpiry(mockRegionEntry(new ApplicationDomainObjectWithTimeToLiveAndGenericExpirationPolicies())), @@ -165,6 +168,7 @@ public class AnnotationBasedExpirationConfigurationIntegrationTest { @Test public void genericExpirationPolicy() { + assertExpiration(genericExpiration.getExpiry(mockRegionEntry( new ApplicationDomainObjectWithTimeToLiveAndGenericExpirationPolicies())), 60, ExpirationAction.INVALIDATE); assertThat(genericExpiration.getExpiry(mockRegionEntry( @@ -183,58 +187,54 @@ public class AnnotationBasedExpirationConfigurationIntegrationTest { @Test public void invalidExpirationAction() { - expectedException.expect(EvaluationException.class); - expectedException.expectCause(isA(IllegalArgumentException.class)); - expectedException.expectMessage(String.format("[%s] is not resolvable as an ExpirationAction(Type)", + + exception.expect(EvaluationException.class); + exception.expectCause(isA(IllegalArgumentException.class)); + exception.expectMessage(String.format("[%s] is not resolvable as an ExpirationAction(Type)", "@expirationProperties['gemfire.region.entry.expiration.invalid.action.string']")); + genericExpiration.getExpiry(mockRegionEntry(new RegionEntryWithInvalidExpirationAction())); } @Test public void invalidExpirationTimeout() { - expectedException.expect(IllegalArgumentException.class); - expectedException.expectCause(is(nullValue(Throwable.class))); + + exception.expect(IllegalArgumentException.class); + exception.expectCause(is(nullValue(Throwable.class))); + genericExpiration.getExpiry(mockRegionEntry(new RegionEntryWithInvalidExpirationTimeout())); } @Expiration(timeout = "60", action = "INVALIDATE") @TimeToLiveExpiration(timeout = "300", action = "DESTROY") - protected static class ApplicationDomainObjectWithTimeToLiveAndGenericExpirationPolicies { - } + protected static class ApplicationDomainObjectWithTimeToLiveAndGenericExpirationPolicies { } @IdleTimeoutExpiration(timeout = "120", action = "INVALIDATE") - protected static class ApplicationDomainObjectWithIdleTimeoutExpirationPolicy { - } + protected static class ApplicationDomainObjectWithIdleTimeoutExpirationPolicy { } @Expiration(timeout = "60", action = "DESTROY") - protected static class ApplicationDomainObjectWithGenericExpirationPolicy { - } + protected static class ApplicationDomainObjectWithGenericExpirationPolicy { } - protected static class ApplicationDomainObjectWithNoExpirationPolicy { - } + protected static class ApplicationDomainObjectWithNoExpirationPolicy { } @TimeToLiveExpiration(timeout = "${gemfire.region.entry.expiration.timeout}", action = "${gemfire.region.entry.expiration.action.string}") - protected static class RegionEntryTimeToLiveExpirationPolicy { - } + protected static class RegionEntryTimeToLiveExpirationPolicy { } @IdleTimeoutExpiration(timeout = "@expirationProperties['gemfire.region.entry.expiration.timeout']", action = "@expirationProperties['gemfire.region.entry.expiration.action.gemfire.type']") - protected static class RegionEntryIdleTimeoutExpirationPolicy { - } + protected static class RegionEntryIdleTimeoutExpirationPolicy { } @Expiration(timeout = "${gemfire.region.entry.expiration.timeout}", action = "@expirationProperties['gemfire.region.entry.expiration.action.spring.type']") - protected static class RegionEntryGenericExpirationPolicy { - } + protected static class RegionEntryGenericExpirationPolicy { } @Expiration(timeout = "${gemfire.region.entry.expiration.timeout}", action = "@expirationProperties['gemfire.region.entry.expiration.invalid.action.string']") - protected static class RegionEntryWithInvalidExpirationAction { - } + protected static class RegionEntryWithInvalidExpirationAction { } @Expiration(timeout = "${gemfire.region.entry.expiration.invalid.timeout}", action = "@expirationProperties['gemfire.region.entry.expiration.action.spring.type']") - protected static class RegionEntryWithInvalidExpirationTimeout { - } + protected static class RegionEntryWithInvalidExpirationTimeout { } + }