SGF-747 - Properly enable statistics when Annotation-based Expiration Policies are enabled with EnableExpiration.

This commit is contained in:
John Blum
2018-05-16 19:45:21 -07:00
parent 3ed1599cc9
commit c7e1a2c95d
25 changed files with 1190 additions and 557 deletions

View File

@@ -36,9 +36,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;
@@ -57,6 +60,8 @@ import org.springframework.context.SmartLifecycle;
import org.springframework.core.io.Resource;
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.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.ReflectionUtils;
@@ -93,8 +98,9 @@ import org.springframework.util.StringUtils;
* @see org.springframework.data.gemfire.config.annotation.RegionConfigurer
*/
@SuppressWarnings("unused")
// TODO: Rename to PeerRegionFactoryBean in SD Lovelace
public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
implements DisposableBean, SmartLifecycle {
implements EvictingRegionFactoryBean, ExpiringRegionFactoryBean<K, V>, DisposableBean, SmartLifecycle {
protected final Log log = LogFactory.getLog(getClass());
@@ -104,6 +110,7 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
private Boolean offHeap;
private Boolean persistent;
private Boolean statisticsEnabled;
private AsyncEventQueue[] asyncEventQueues;
@@ -118,10 +125,18 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
private Compressor compressor;
private CustomExpiry<K, V> customEntryIdleTimeout;
private CustomExpiry<K, V> customEntryTimeToLive;
private DataPolicy dataPolicy;
private EvictionAttributes evictionAttributes;
private ExpirationAttributes entryIdleTimeout;
private ExpirationAttributes entryTimeToLive;
private ExpirationAttributes regionIdleTimeout;
private ExpirationAttributes regionTimeToLive;
private GatewaySender[] gatewaySenders;
private List<RegionConfigurer> regionConfigurers = Collections.emptyList();
@@ -294,6 +309,8 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
*/
protected RegionFactory<K, V> configure(RegionFactory<K, V> regionFactory) {
regionFactory.setStatisticsEnabled(resolveStatisticsEnabled());
stream(nullSafeArray(this.asyncEventQueues, AsyncEventQueue.class))
.forEach(asyncEventQueue -> regionFactory.addAsyncEventQueueId(asyncEventQueue.getId()));
@@ -305,12 +322,20 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
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))
@@ -318,6 +343,10 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
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);
@@ -378,7 +407,6 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
.orElseGet(() -> RegionShortcutToDataPolicyConverter.INSTANCE.convert(regionShortcut));
}
/* (non-Javadoc) */
@SuppressWarnings("unchecked")
private <T> Optional<T> getFieldValue(Object source, String fieldName, Class<T> targetType) {
@@ -461,9 +489,13 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
}
/**
* 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 <K, V> void mergePartitionAttributes(RegionFactory<K, V> regionFactory,
RegionAttributes<K, V> regionAttributes) {
@@ -573,7 +605,6 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
}
/**
<<<<<<< HEAD
* Validates that the settings for Data Policy and the 'persistent' attribute in &lt;gfe:*-region&gt; elements
* are compatible.
*
@@ -597,14 +628,8 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
}
/**
=======
>>>>>>> c22ebe6... DATAGEODE-12 - Introduce Spring Configurers to flexibly alter Spring Data GemFire configuration when using Annotation config.
* Validates and sets the Data Policy on the RegionFactory used to create and configure the Region from this
* FactoryBean.
=======
* Validates and sets the {@link DataPolicy} on the {@link RegionFactory} used to create and configure
* the {@link Region} from this {@link FactoryBean}.
>>>>>>> 12126a1... SGF-732 - Change branding from Spring Data GemFire to Spring Data for Pivotal GemFire.
*
* @param regionFactory the RegionFactory used by this FactoryBean to create and configure the Region.
* @param persistent a boolean value indicating whether the Region should be persistent and persist it's
@@ -661,7 +686,6 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
}
}
/* (non-Javadoc) */
private DataPolicy getDataPolicy(RegionAttributes regionAttributes, DataPolicy defaultDataPolicy) {
return Optional.ofNullable(regionAttributes).map(RegionAttributes::getDataPolicy).orElse(defaultDataPolicy);
}
@@ -669,8 +693,10 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
/**
* 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 {
@@ -694,30 +720,34 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
}
/**
* 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<K, V> 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<K, V> getAttributes() {
@@ -725,42 +755,58 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
}
/**
* 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<K, V>[] 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<K, V> 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<K, V> 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) {
@@ -768,29 +814,40 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
}
/**
* 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<K, V> customEntryIdleTimeout) {
this.customEntryIdleTimeout = customEntryIdleTimeout;
}
public void setCustomEntryTimeToLive(CustomExpiry<K, V> 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 Pivotal 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) {
@@ -798,11 +855,12 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
}
/**
* 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) {
@@ -810,10 +868,12 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
}
/**
* 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() {
@@ -822,31 +882,47 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
}
/**
* 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) {
@@ -854,30 +930,50 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
}
/**
* 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<K> 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;
}
@@ -907,43 +1003,95 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
this.regionConfigurers = Optional.ofNullable(regionConfigurers).orElseGet(Collections::emptyList);
}
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<V> valueConstraint) {
this.valueConstraint = valueConstraint;
}
/**
* @inheritDoc
*/
@Override
@SuppressWarnings("all")
public void start() {
@@ -961,18 +1109,12 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
this.running = true;
}
/**
* @inheritDoc
*/
@Override
public void stop(Runnable callback) {
stop();
callback.run();
}
/**
* @inheritDoc
*/
@Override
public void stop() {
@@ -987,25 +1129,16 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
this.running = false;
}
/**
* @inheritDoc
*/
@Override
public boolean isRunning() {
return this.running;
}
/**
* @inheritDoc
*/
@Override
public int getPhase() {
return Integer.MAX_VALUE;
}
/**
* @inheritDoc
*/
@Override
public boolean isAutoStartup() {
return true;

View File

@@ -31,8 +31,10 @@ import java.util.stream.StreamSupport;
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.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;
@@ -50,6 +52,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.util.Assert;
import org.springframework.util.StringUtils;
@@ -75,7 +79,8 @@ import org.springframework.util.StringUtils;
* @see org.springframework.data.gemfire.config.annotation.RegionConfigurer
*/
@SuppressWarnings("unused")
public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> implements DisposableBean {
public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
implements EvictingRegionFactoryBean, ExpiringRegionFactoryBean<K, V>, DisposableBean {
public static final String DEFAULT_POOL_NAME = "DEFAULT";
public static final String GEMFIRE_POOL_NAME = GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME;
@@ -84,6 +89,7 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
private boolean destroy = false;
private Boolean persistent;
private Boolean statisticsEnabled;
private CacheListener<K, V>[] cacheListeners;
@@ -98,10 +104,18 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
private Compressor compressor;
private CustomExpiry<K, V> customEntryIdleTimeout;
private CustomExpiry<K, V> customEntryTimeToLive;
private DataPolicy dataPolicy;
private EvictionAttributes evictionAttributes;
private ExpirationAttributes entryIdleTimeout;
private ExpirationAttributes entryTimeToLive;
private ExpirationAttributes regionIdleTimeout;
private ExpirationAttributes regionTimeToLive;
private Interest<K>[] interests;
private List<RegionConfigurer> regionConfigurers = Collections.emptyList();
@@ -394,11 +408,21 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
stream(nullSafeArray(this.cacheListeners, CacheListener.class)).forEach(clientRegionFactory::addCacheListener);
clientRegionFactory.setStatisticsEnabled(resolveStatisticsEnabled());
Optional.ofNullable(this.compressor).ifPresent(clientRegionFactory::setCompressor);
Optional.ofNullable(this.customEntryIdleTimeout).ifPresent(clientRegionFactory::setCustomEntryIdleTimeout);
Optional.ofNullable(this.customEntryTimeToLive).ifPresent(clientRegionFactory::setCustomEntryTimeToLive);
Optional.ofNullable(this.diskStoreName).filter(StringUtils::hasText)
.ifPresent(clientRegionFactory::setDiskStoreName);
Optional.ofNullable(this.entryIdleTimeout).ifPresent(clientRegionFactory::setEntryIdleTimeout);
Optional.ofNullable(this.entryTimeToLive).ifPresent(clientRegionFactory::setEntryTimeToLive);
Optional.ofNullable(this.evictionAttributes).ifPresent(clientRegionFactory::setEvictionAttributes);
Optional.ofNullable(this.keyConstraint).ifPresent(clientRegionFactory::setKeyConstraint);
@@ -407,6 +431,10 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
.map(this::eagerlyInitializePool)
.ifPresent(clientRegionFactory::setPoolName);
Optional.ofNullable(this.regionIdleTimeout).ifPresent(clientRegionFactory::setRegionIdleTimeout);
Optional.ofNullable(this.regionTimeToLive).ifPresent(clientRegionFactory::setRegionTimeToLive);
Optional.ofNullable(this.valueConstraint).ifPresent(clientRegionFactory::setValueConstraint);
return clientRegionFactory;
@@ -575,6 +603,14 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
this.compressor = compressor;
}
public void setCustomEntryIdleTimeout(CustomExpiry<K, V> customEntryIdleTimeout) {
this.customEntryIdleTimeout = customEntryIdleTimeout;
}
public void setCustomEntryTimeToLive(CustomExpiry<K, V> customEntryTimeToLive) {
this.customEntryTimeToLive = customEntryTimeToLive;
}
/**
* Sets the Data Policy. Used only when a new Region is created.
*
@@ -627,6 +663,14 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
this.diskStoreName = diskStoreName;
}
public void setEntryIdleTimeout(ExpirationAttributes entryIdleTimeout) {
this.entryIdleTimeout = entryIdleTimeout;
}
public void setEntryTimeToLive(ExpirationAttributes entryTimeToLive) {
this.entryTimeToLive = entryTimeToLive;
}
public void setEvictionAttributes(EvictionAttributes evictionAttributes) {
this.evictionAttributes = evictionAttributes;
}
@@ -724,6 +768,14 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
this.regionConfigurers = Optional.ofNullable(regionConfigurers).orElseGet(Collections::emptyList);
}
public void setRegionIdleTimeout(ExpirationAttributes regionIdleTimeout) {
this.regionIdleTimeout = regionIdleTimeout;
}
public void setRegionTimeToLive(ExpirationAttributes regionTimeToLive) {
this.regionTimeToLive = regionTimeToLive;
}
/**
* Initializes the client {@link Region} using the given {@link ClientRegionShortcut}.
*
@@ -734,6 +786,32 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
this.shortcut = 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(this.attributes)
.map(RegionAttributes::getStatisticsEnabled)
.orElse(false);
}
/**
* Sets a {@link Class type} constraint on this {@link Region Region's} values.
*

View File

@@ -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
*/

View File

@@ -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 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 org.apache.geode.cache.Region
* @see <a href="http://docs.spring.io/spring-data-gemfire/docs/current/reference/html/#bootstrap:region:expiration:annotation">Annotation-based Data Expiration</a>
* @see <a href="http://gemfire.docs.pivotal.io/docs-gemfire/latest/developing/expiration/chapter_overview.html">Pivotal GemFire Expiration</a>
* @see <a href="http://geode.incubator.apache.org/docs/guide/developing/expiration/chapter_overview.html">Geode Expiration</a>
@@ -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;

View File

@@ -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;
@@ -58,23 +59,27 @@ import org.springframework.util.StringUtils;
* Eviction policy configuration on cache {@link Region Regions}.
*
* @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.beans.factory.config.BeanPostProcessor
* @see org.springframework.context.ApplicationContext
* @see org.springframework.context.ApplicationContextAware
* @see org.springframework.context.annotation.Bean
* @see org.springframework.context.annotation.Configuration
* @see org.springframework.context.annotation.ImportAware
* @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.springframework.data.gemfire.RegionFactoryBean
* @see org.springframework.data.gemfire.client.ClientRegionFactoryBean
* @see org.apache.geode.cache.EvictionAttributes
* @see org.apache.geode.cache.Region
* @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<? extends Annotation> 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<String, Object> 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<String> 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;
}
}
}

View File

@@ -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<String, Object> 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<Object, Object>) 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<String> 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;
}
/**

View File

@@ -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<? extends Annotation> getAnnotationType() {
return EnableStatistics.class;
}
/* (non-Javadoc) */
@Override
protected Properties toGemFireProperties(Map<String, Object> annotationAttributes) {

View File

@@ -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<K, V> extends RegionLookupFactoryBean<K, V> {
public class CacheTypeAwareRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
implements EvictingRegionFactoryBean, ExpiringRegionFactoryBean<K, V> {
private GemFireCache gemfireCache;
private Boolean close = false;
private Boolean offHeap = false;
private Boolean statisticsEnabled = false;
private Class<K> keyConstraint;
private Class<V> valueConstraint;
@@ -88,8 +100,18 @@ public class CacheTypeAwareRegionFactoryBean<K, V> extends RegionLookupFactoryBe
private Compressor compressor;
private CustomExpiry<K, V> customEntryIdleTimeout;
private CustomExpiry<K, V> customEntryTimeToLive;
private DataPolicy dataPolicy = DataPolicy.DEFAULT;
private EvictionAttributes evictionAttributes;
private ExpirationAttributes entryIdleTimeout;
private ExpirationAttributes entryTimeToLive;
private ExpirationAttributes regionIdleTimeout;
private ExpirationAttributes regionTimeToLive;
private List<RegionConfigurer> regionConfigurers = Collections.emptyList();
private RegionAttributes<K, V> regionAttributes;
@@ -108,8 +130,9 @@ public class CacheTypeAwareRegionFactoryBean<K, V> extends RegionLookupFactoryBe
@Override
public Region<K, V> 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<K, V> extends RegionLookupFactoryBe
getPoolName().ifPresent(clientRegionFactory::setPoolName);
configureEviction(clientRegionFactory);
configureExpiration(clientRegionFactory);
clientRegionFactory.afterPropertiesSet();
return clientRegionFactory.getObject();
@@ -194,6 +220,9 @@ public class CacheTypeAwareRegionFactoryBean<K, V> extends RegionLookupFactoryBe
serverRegionFactory.setShortcut(getServerRegionShortcut());
serverRegionFactory.setValueConstraint(getValueConstraint());
configureEviction(serverRegionFactory);
configureExpiration(serverRegionFactory);
serverRegionFactory.afterPropertiesSet();
return serverRegionFactory.getObject();
@@ -224,14 +253,31 @@ public class CacheTypeAwareRegionFactoryBean<K, V> extends RegionLookupFactoryBe
return new PartitionedRegionFactoryBean<>();
}
else if (resolvedDataPolicy.withReplication()) {
ReplicatedRegionFactoryBean<K, V> replicatedRegionFactoryBean = new ReplicatedRegionFactoryBean<>();
replicatedRegionFactoryBean.setScope(getScope());
return replicatedRegionFactoryBean;
}
return new GenericRegionFactoryBean<>();
}
protected void configureEviction(EvictingRegionFactoryBean regionFactoryBean) {
regionFactoryBean.setEvictionAttributes(getEvictionAttributes());
}
protected void configureExpiration(ExpiringRegionFactoryBean<K, V> regionFactoryBean) {
regionFactoryBean.setCustomEntryIdleTimeout(getCustomEntryIdleTimeout());
regionFactoryBean.setCustomEntryTimeToLive(getCustomEntryTimeToLive());
regionFactoryBean.setEntryIdleTimeout(getEntryIdleTimeout());
regionFactoryBean.setEntryTimeToLive(getEntryTimeToLive());
regionFactoryBean.setRegionIdleTimeout(getRegionIdleTimeout());
regionFactoryBean.setRegionTimeToLive(getRegionTimeToLive());
}
public void setAttributes(RegionAttributes<K, V> regionAttributes) {
this.regionAttributes = regionAttributes;
}
@@ -280,6 +326,22 @@ public class CacheTypeAwareRegionFactoryBean<K, V> extends RegionLookupFactoryBe
return this.compressor;
}
public void setCustomEntryIdleTimeout(CustomExpiry<K, V> customEntryIdleTimeout) {
this.customEntryIdleTimeout = customEntryIdleTimeout;
}
protected CustomExpiry<K, V> getCustomEntryIdleTimeout() {
return customEntryIdleTimeout;
}
public void setCustomEntryTimeToLive(CustomExpiry<K, V> customEntryTimeToLive) {
this.customEntryTimeToLive = customEntryTimeToLive;
}
protected CustomExpiry<K, V> getCustomEntryTimeToLive() {
return customEntryTimeToLive;
}
public void setDataPolicy(DataPolicy dataPolicy) {
this.dataPolicy = dataPolicy;
}
@@ -296,6 +358,30 @@ public class CacheTypeAwareRegionFactoryBean<K, V> 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<K> keyConstraint) {
this.keyConstraint = keyConstraint;
}
@@ -360,6 +446,22 @@ public class CacheTypeAwareRegionFactoryBean<K, V> 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;
}

View File

@@ -108,6 +108,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) {
@@ -143,8 +144,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());
}
/**
@@ -238,6 +239,7 @@ abstract class ParsingUtils {
Element evictionElement = DomUtils.getChildElementByTagName(element, "eviction");
if (evictionElement != null) {
BeanDefinitionBuilder evictionAttributesBuilder = BeanDefinitionBuilder.genericBeanDefinition(
EvictionAttributesFactoryBean.class);
@@ -248,8 +250,10 @@ abstract class ParsingUtils {
Element objectSizerElement = DomUtils.getChildElementByTagName(evictionElement, "object-sizer");
if (objectSizerElement != null) {
Object sizer = parseRefOrNestedBeanDeclaration(objectSizerElement, parserContext,
evictionAttributesBuilder);
evictionAttributesBuilder.addPropertyValue("objectSizer", sizer);
}
@@ -272,13 +276,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");
@@ -292,6 +298,7 @@ abstract class ParsingUtils {
}
static void parseTransportFilters(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
Element transportFilterElement = DomUtils.getChildElementByTagName(element, "transport-filter");
if (transportFilterElement != null) {
@@ -314,9 +321,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);
@@ -327,7 +335,7 @@ abstract class ParsingUtils {
regionAttributesBuilder);
if (result) {
// turn on statistics
// enable statistics
regionAttributesBuilder.addPropertyValue("statisticsEnabled", Boolean.TRUE);
}
@@ -408,6 +416,7 @@ abstract class ParsingUtils {
}
static void parseScope(Element element, BeanDefinitionBuilder builder) {
String scopeAttributeValue = element.getAttribute("scope");
if (StringUtils.hasText(scopeAttributeValue)) {
@@ -421,8 +430,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");
@@ -440,6 +450,7 @@ abstract class ParsingUtils {
Element expirationElement = DomUtils.getChildElementByTagName(rootElement, elementName);
if (expirationElement != null) {
Object customExpiry =
parseRefOrSingleNestedBeanDeclaration(expirationElement, parserContext, regionAttributesBuilder);

View File

@@ -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);
}

View File

@@ -27,6 +27,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);
@@ -54,7 +55,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;
}
/**
@@ -67,6 +68,7 @@ public enum EvictionActionType {
* @see #getEvictionAction()
*/
public static EvictionActionType valueOf(final EvictionAction evictionAction) {
for (EvictionActionType evictionActionType : values()) {
if (evictionActionType.getEvictionAction().equals(evictionAction)) {
return evictionActionType;
@@ -86,6 +88,7 @@ public enum EvictionActionType {
* @see #name()
*/
public static EvictionActionType valueOfIgnoreCase(final String name) {
for (EvictionActionType evictionActionType : values()) {
if (evictionActionType.name().equalsIgnoreCase(name)) {
return evictionActionType;
@@ -102,7 +105,6 @@ public enum EvictionActionType {
* @see org.apache.geode.cache.EvictionAction
*/
public EvictionAction getEvictionAction() {
return evictionAction;
return this.evictionAction;
}
}

View File

@@ -29,6 +29,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),
@@ -55,7 +56,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;
}
/**
@@ -67,6 +68,7 @@ public enum EvictionPolicyType {
* @see #getEvictionAlgorithm()
*/
public static EvictionPolicyType valueOf(final EvictionAlgorithm evictionAlgorithm) {
for (EvictionPolicyType evictionPolicyType : values()) {
if (evictionPolicyType.getEvictionAlgorithm().equals(evictionAlgorithm)) {
return evictionPolicyType;
@@ -85,6 +87,7 @@ public enum EvictionPolicyType {
* @see #name()
*/
public static EvictionPolicyType valueOfIgnoreCase(final String name) {
for (EvictionPolicyType evictionPolicyType : values()) {
if (evictionPolicyType.name().equalsIgnoreCase(name)) {
return evictionPolicyType;
@@ -101,7 +104,6 @@ public enum EvictionPolicyType {
* @see org.apache.geode.cache.EvictionAlgorithm
*/
public EvictionAlgorithm getEvictionAlgorithm() {
return evictionAlgorithm;
return this.evictionAlgorithm;
}
}

View File

@@ -128,10 +128,15 @@ public class AnnotationBasedExpiration<K, V> implements BeanFactoryAware, Custom
* @see #AnnotationBasedExpiration(ExpirationAttributes)
*/
public static <K, V> AnnotationBasedExpiration<K, V> forIdleTimeout(ExpirationAttributes defaultExpirationAttributes) {
return new AnnotationBasedExpiration<K, V>(defaultExpirationAttributes) {
@Override protected ExpirationMetaData getExpirationMetaData(Region.Entry<K, V> entry) {
return (isIdleTimeoutConfigured(entry) ? ExpirationMetaData.from(getIdleTimeout(entry))
: super.getExpirationMetaData(entry));
@Override
protected ExpirationMetaData getExpirationMetaData(Region.Entry<K, V> entry) {
return isIdleTimeoutConfigured(entry)
? ExpirationMetaData.from(getIdleTimeout(entry))
: super.getExpirationMetaData(entry);
}
};
}
@@ -169,10 +174,15 @@ public class AnnotationBasedExpiration<K, V> implements BeanFactoryAware, Custom
* @see #AnnotationBasedExpiration(ExpirationAttributes)
*/
public static <K, V> AnnotationBasedExpiration<K, V> forTimeToLive(ExpirationAttributes defaultExpirationAttributes) {
return new AnnotationBasedExpiration<K, V>(defaultExpirationAttributes) {
@Override protected ExpirationMetaData getExpirationMetaData(Region.Entry<K, V> entry) {
return (isTimeToLiveConfigured(entry) ? ExpirationMetaData.from(getTimeToLive(entry))
: super.getExpirationMetaData(entry));
@Override
protected ExpirationMetaData getExpirationMetaData(Region.Entry<K, V> entry) {
return isTimeToLiveConfigured(entry)
? ExpirationMetaData.from(getTimeToLive(entry))
: super.getExpirationMetaData(entry);
}
};
}
@@ -182,9 +192,11 @@ public class AnnotationBasedExpiration<K, V> 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<K, V> 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<K, V> 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<K, V> implements BeanFactoryAware, Custom
*/
protected ExpirationAttributes getDefaultExpirationAttributes() {
//return (defaultExpirationAttributes != null ? defaultExpirationAttributes : ExpirationAttributes.DEFAULT);
return defaultExpirationAttributes;
return this.defaultExpirationAttributes;
}
/**
@@ -290,7 +303,7 @@ public class AnnotationBasedExpiration<K, V> implements BeanFactoryAware, Custom
* @see org.springframework.data.gemfire.expiration.AnnotationBasedExpiration.ExpirationMetaData
*/
protected ExpirationMetaData getExpirationMetaData(Region.Entry<K, V> entry) {
return (isExpirationConfigured(entry) ? ExpirationMetaData.from(getExpiration(entry)) : null);
return isExpirationConfigured(entry) ? ExpirationMetaData.from(getExpiration(entry)) : null;
}
/**
@@ -308,8 +321,10 @@ public class AnnotationBasedExpiration<K, V> 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<K, V> implements BeanFactoryAware, Custom
* @see #isAnnotationPresent(Object, Class)
*/
protected boolean isExpirationConfigured(Region.Entry<K, V> 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<K, V> 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<K, V> implements BeanFactoryAware, Custom
* @see #isAnnotationPresent(Object, Class)
*/
protected boolean isIdleTimeoutConfigured(Region.Entry<K, V> 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<K, V> 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<K, V> implements BeanFactoryAware, Custom
* @see #isAnnotationPresent(Object, Class)
*/
protected boolean isTimeToLiveConfigured(Region.Entry<K, V> 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<K, V> implements BeanFactoryAware, Custom
return getTimeToLive(entry.getValue());
}
/* (non-Javadoc) */
private TimeToLiveExpiration getTimeToLive(Object obj) {
return getAnnotation(obj, TimeToLiveExpiration.class);
}
/* (non-Javadoc) */
private <T extends Annotation> boolean isAnnotationPresent(Object obj, Class<T> annotationType) {
return (obj != null && obj.getClass().isAnnotationPresent(annotationType));
}
/* (non-Javadoc) */
private <T extends Annotation> T getAnnotation(Object obj, Class<T> annotationType) {
return AnnotationUtils.getAnnotation(obj.getClass(), annotationType);
}
@@ -432,8 +439,7 @@ public class AnnotationBasedExpiration<K, V> 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<K, V> 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<K, V> 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<K, V> 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<K, V> 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<K, V> 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<K, V> 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<K, V> 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<K, V> 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());
}
}
}

View File

@@ -27,6 +27,7 @@ import org.apache.geode.cache.ExpirationAction;
*/
@SuppressWarnings("unused")
public enum ExpirationActionType {
DESTROY(ExpirationAction.DESTROY),
INVALIDATE(ExpirationAction.INVALIDATE),
LOCAL_DESTROY(ExpirationAction.LOCAL_DESTROY),
@@ -55,7 +56,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;
}
/**
@@ -68,6 +69,7 @@ public enum ExpirationActionType {
* @see #getExpirationAction()
*/
public static ExpirationActionType valueOf(final ExpirationAction expirationAction) {
for (ExpirationActionType expirationActionType : values()) {
if (expirationActionType.getExpirationAction().equals(expirationAction)) {
return expirationActionType;
@@ -87,6 +89,7 @@ public enum ExpirationActionType {
* @see #name()
*/
public static ExpirationActionType valueOfIgnoreCase(final String name) {
for (ExpirationActionType expirationActionType : values()) {
if (expirationActionType.name().equalsIgnoreCase(name)) {
return expirationActionType;
@@ -103,7 +106,6 @@ public enum ExpirationActionType {
* @see org.apache.geode.cache.ExpirationAction
*/
public ExpirationAction getExpirationAction() {
return expirationAction;
return this.expirationAction;
}
}

View File

@@ -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<K, V> {
void setCustomEntryIdleTimeout(CustomExpiry<K, V> customEntryIdleTimeout);
void setCustomEntryTimeToLive(CustomExpiry<K, V> customEntryTimeToLive);
void setEntryIdleTimeout(ExpirationAttributes entryIdleTimeout);
void setEntryTimeToLive(ExpirationAttributes entryTimeToLive);
void setRegionIdleTimeout(ExpirationAttributes regionIdleTimeout);
void setRegionTimeToLive(ExpirationAttributes regionTimeToLive);
}