SGF-738 - Avoid Pool Already Exists Exception on Spring container initialization.

This commit is contained in:
John Blum
2018-04-14 13:17:18 -07:00
parent 75c81c4fa7
commit b13dcffe80
97 changed files with 2999 additions and 2934 deletions

View File

@@ -351,17 +351,17 @@ Building on our examples above, the client's `application.properties` would defi
[source, java]
----
spring.data.gemfire.cache.log-level=info
spring.data.gemfire.pool.venus.servers=venus[48484]
spring.data.gemfire.pool.venus.max-connections=200
spring.data.gemfire.pool.venus.min-connections=50
spring.data.gemfire.pool.venus.ping-interval=15000
spring.data.gemfire.pool.venus.pr-single-hop-enabled=true
spring.data.gemfire.pool.venus.read-timeout=20000
spring.data.gemfire.pool.venus.subscription-enabled=true
spring.data.gemfire.pool.saturn.locators=skullbox[20668]
spring.data.gemfire.pool.saturn.subscription-enabled=true
spring.data.gemfire.pool.neptune.servers=saturn[41414],neptune[42424]
spring.data.gemfire.pool.neptune.min-connections=25
spring.data.gemfire.pool.Venus.servers=venus[48484]
spring.data.gemfire.pool.Venus.max-connections=200
spring.data.gemfire.pool.Venus.min-connections=50
spring.data.gemfire.pool.Venus.ping-interval=15000
spring.data.gemfire.pool.Venus.pr-single-hop-enabled=true
spring.data.gemfire.pool.Venus.read-timeout=20000
spring.data.gemfire.pool.Venus.subscription-enabled=true
spring.data.gemfire.pool.Saturn.locators=skullbox[20668]
spring.data.gemfire.pool.Saturn.subscription-enabled=true
spring.data.gemfire.pool.Neptune.servers=saturn[41414],neptune[42424]
spring.data.gemfire.pool.Neptune.min-connections=25
----
And, the server's application.properties would define...
@@ -384,9 +384,9 @@ Then, we can simplify the `@ClientCacheApplication` class to...
@SpringBootApplication
@ClientCacheApplication
@EnablePools(pools = {
@EnablePool(name = "VenusPool"),
@EnablePool(name = "SaturnPool"),
@EnablePool(name = "NeptunePool")
@EnablePool(name = "Venus"),
@EnablePool(name = "Saturn"),
@EnablePool(name = "Neptune")
})
class ClientApplication { .. }
----

View File

@@ -29,8 +29,8 @@ import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newR
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@@ -72,12 +72,13 @@ import org.springframework.util.StringUtils;
* Spring {@link FactoryBean} used to construct, configure and initialize a Pivotal GemFire/Apache Geode
* {@link Cache peer cache).
*
* Allows either retrieval of an existing, opened {@link Cache} or creation of a new {@link Cache}.
* Allows either retrieval of an existing, open {@link Cache} or creation of a new {@link Cache}.
*
* This class implements the {@link PersistenceExceptionTranslator} interface and is auto-detected by Spring's
* {@link org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor} for AOP-based translation
* of native persistent store exceptions to Spring's {@link DataAccessException} hierarchy. Therefore, the presence
* of this class automatically enables a {@link org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor}
* of native persistent data store exceptions to Spring's {@link DataAccessException} hierarchy. Therefore, the presence
* of this class automatically enables a
* {@link org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor}
* to translate Pivotal GemFire/Apache Geode exceptions appropriately.
*
* @author Costin Leau
@@ -119,10 +120,10 @@ public class CacheFactoryBean extends AbstractFactoryBeanSupport<GemFireCache>
private Boolean pdxReadSerialized;
private Boolean useClusterConfiguration;
private GemFireCache cache;
private CacheFactoryInitializer<?> cacheFactoryInitializer;
private GemFireCache cache;
private DynamicRegionSupport dynamicRegionSupport;
private Float criticalHeapPercentage;
@@ -139,7 +140,7 @@ public class CacheFactoryBean extends AbstractFactoryBeanSupport<GemFireCache>
private Integer messageSyncInterval;
private Integer searchTimeout;
private List<PeerCacheConfigurer> peerCacheConfigurers = Collections.emptyList();
private List<PeerCacheConfigurer> peerCacheConfigurers = new ArrayList<>();
private List<JndiDataSource> jndiDataSources;
@@ -165,13 +166,65 @@ public class CacheFactoryBean extends AbstractFactoryBeanSupport<GemFireCache>
*
* @throws Exception if initialization fails.
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
* @see #applyCacheConfigurers()
* @see #initBeanFactoryLocator()
* @see #postProcessBeforeCacheInitialization(Properties)
*/
@Override
public void afterPropertiesSet() throws Exception {
applyCacheConfigurers();
initBeanFactoryLocator();
postProcessBeforeCacheInitialization(resolveProperties());
}
/**
* Applies the composite {@link PeerCacheConfigurer PeerCacheConfigurers} to this {@link CacheFactoryBean}
* before creating the {@link Cache peer Cache}.
*
* @see #getCompositePeerCacheConfigurer()
* @see #applyPeerCacheConfigurers(PeerCacheConfigurer...)
*/
protected void applyCacheConfigurers() {
PeerCacheConfigurer autoReconnectClusterConfigurationConfigurer = (beanName, cacheFactoryBean) -> {
Properties gemfireProperties = resolveProperties();
gemfireProperties.setProperty("disable-auto-reconnect",
String.valueOf(!Boolean.TRUE.equals(getEnableAutoReconnect())));
gemfireProperties.setProperty("use-cluster-configuration",
String.valueOf(Boolean.TRUE.equals(getUseClusterConfiguration())));
};
this.peerCacheConfigurers.add(autoReconnectClusterConfigurationConfigurer);
applyPeerCacheConfigurers(getCompositePeerCacheConfigurer());
}
/**
* Applies the given array of {@link PeerCacheConfigurer PeerCacheConfigurers} to this {@link CacheFactoryBean}.
*
* @param peerCacheConfigurers array of {@link PeerCacheConfigurer PeerCacheConfigurers} applied to
* this {@link CacheFactoryBean}.
* @see org.springframework.data.gemfire.config.annotation.PeerCacheConfigurer
* @see #applyPeerCacheConfigurers(Iterable)
*/
protected void applyPeerCacheConfigurers(PeerCacheConfigurer... peerCacheConfigurers) {
applyPeerCacheConfigurers(Arrays.asList(nullSafeArray(peerCacheConfigurers, PeerCacheConfigurer.class)));
}
/**
* Applies the given {@link Iterable} of {@link PeerCacheConfigurer PeerCacheConfigurers}
* to this {@link CacheFactoryBean}.
*
* @param peerCacheConfigurers {@link Iterable} of {@link PeerCacheConfigurer PeerCacheConfigurers}
* applied to this {@link CacheFactoryBean}.
* @see org.springframework.data.gemfire.config.annotation.PeerCacheConfigurer
* @see java.lang.Iterable
* @see #applyPeerCacheConfigurers(PeerCacheConfigurer...)
*/
protected void applyPeerCacheConfigurers(Iterable<PeerCacheConfigurer> peerCacheConfigurers) {
stream(nullSafeIterable(peerCacheConfigurers).spliterator(), false)
.forEach(clientCacheConfigurer -> clientCacheConfigurer.configure(getBeanName(), this));
}
/**
@@ -184,64 +237,13 @@ public class CacheFactoryBean extends AbstractFactoryBeanSupport<GemFireCache>
* @see #getBeanFactory()
* @see #getBeanName()
*/
private void initBeanFactoryLocator() {
if (isUseBeanFactoryLocator() && getBeanFactoryLocator() == null) {
void initBeanFactoryLocator() {
if (isUseBeanFactoryLocator() && this.beanFactoryLocator == null) {
this.beanFactoryLocator = newBeanFactoryLocator(getBeanFactory(), getBeanName());
}
}
/**
* Post processes this {@link CacheFactoryBean} before cache initialization.
*
* This is also the point at which any configured {@link PeerCacheConfigurer} beans are called.
*
* @param gemfireProperties {@link Properties} used to configure Pivotal GemFire/Apache Geode.
* @see org.springframework.data.gemfire.config.annotation.PeerCacheConfigurer
* @see java.util.Properties
*/
protected void postProcessBeforeCacheInitialization(Properties gemfireProperties) {
gemfireProperties.setProperty("disable-auto-reconnect", String.valueOf(
!Boolean.TRUE.equals(getEnableAutoReconnect())));
gemfireProperties.setProperty("use-cluster-configuration", String.valueOf(
Boolean.TRUE.equals(getUseClusterConfiguration())));
applyPeerCacheConfigurers();
}
/* (non-Javadoc) */
private void applyPeerCacheConfigurers() {
applyPeerCacheConfigurers(getCompositePeerCacheConfigurer());
}
/**
* Null-safe operation to apply the given array of {@link PeerCacheConfigurer PeerCacheConfigurers}
* to this {@link CacheFactoryBean}.
*
* @param peerCacheConfigurers array of {@link PeerCacheConfigurer PeerCacheConfigurers} applied to
* this {@link CacheFactoryBean}.
* @see org.springframework.data.gemfire.config.annotation.PeerCacheConfigurer
* @see #applyPeerCacheConfigurers(Iterable)
*/
protected void applyPeerCacheConfigurers(PeerCacheConfigurer... peerCacheConfigurers) {
applyPeerCacheConfigurers(Arrays.asList(nullSafeArray(peerCacheConfigurers, PeerCacheConfigurer.class)));
}
/**
* Null-safe operation to apply the given {@link Iterable} of {@link PeerCacheConfigurer PeerCacheConfigurers}
* to this {@link CacheFactoryBean}.
*
* @param peerCacheConfigurers {@link Iterable} of {@link PeerCacheConfigurer PeerCacheConfigurers}
* applied to this {@link CacheFactoryBean}.
* @see org.springframework.data.gemfire.config.annotation.PeerCacheConfigurer
* @see java.lang.Iterable
*/
protected void applyPeerCacheConfigurers(Iterable<PeerCacheConfigurer> peerCacheConfigurers) {
stream(nullSafeIterable(peerCacheConfigurers).spliterator(), false)
.forEach(clientCacheConfigurer -> clientCacheConfigurer.configure(getBeanName(), this));
}
/**
* Initializes the {@link Cache}.
*
@@ -257,14 +259,15 @@ public class CacheFactoryBean extends AbstractFactoryBeanSupport<GemFireCache>
ClassLoader currentThreadContextClassLoader = Thread.currentThread().getContextClassLoader();
try {
// use bean ClassLoader to load Spring configured, Pivotal GemFire/Apache Geode classes
// Use Spring Bean ClassLoader to load Spring configured, Pivotal GemFire/Apache Geode classes
Thread.currentThread().setContextClassLoader(getBeanClassLoader());
setCache(postProcess(resolveCache()));
Optional.<GemFireCache>ofNullable(this.getCache()).ifPresent(cache -> {
Optional.<GemFireCache>ofNullable(getCache()).ifPresent(cache -> {
Optional.ofNullable(cache.getDistributedSystem()).map(DistributedSystem::getDistributedMember)
Optional.ofNullable(cache.getDistributedSystem())
.map(DistributedSystem::getDistributedMember)
.ifPresent(member ->
logInfo(() -> String.format("Connected to Distributed System [%1$s] as Member [%2$s]"
.concat(" in Group(s) [%3$s] with Role(s) [%4$s] on Host [%5$s] having PID [%6$d]"),
@@ -278,8 +281,8 @@ public class CacheFactoryBean extends AbstractFactoryBeanSupport<GemFireCache>
return getCache();
}
catch (Exception e) {
throw newRuntimeException(e, "Error occurred when initializing peer cache");
catch (Exception cause) {
throw newRuntimeException(cause, "Error occurred when initializing peer cache");
}
finally {
Thread.currentThread().setContextClassLoader(currentThreadContextClassLoader);
@@ -297,19 +300,24 @@ public class CacheFactoryBean extends AbstractFactoryBeanSupport<GemFireCache>
* @see #fetchCache()
* @see #resolveProperties()
* @see #createFactory(java.util.Properties)
* @see #prepareFactory(Object)
* @see #configureFactory(Object)
* @see #createCache(Object)
*/
@SuppressWarnings("unchecked")
protected <T extends GemFireCache> T resolveCache() {
try {
this.cacheResolutionMessagePrefix = "Found existing";
return (T) fetchCache();
}
catch (CacheClosedException ex) {
catch (CacheClosedException cause) {
this.cacheResolutionMessagePrefix = "Created new";
initDynamicRegionFactory();
return (T) createCache(prepareFactory(initializeFactory(createFactory(resolveProperties()))));
return (T) createCache(postProcess(configureFactory(initializeFactory(createFactory(resolveProperties())))));
}
}
@@ -352,7 +360,7 @@ public class CacheFactoryBean extends AbstractFactoryBeanSupport<GemFireCache>
/**
* Constructs a new instance of {@link CacheFactory} initialized with the given Pivotal GemFire/Apache Geode
* {@link Properties} used to create an instance of a {@link Cache}.
* {@link Properties} used to construct, configure and initialize an instance of a {@link Cache}.
*
* @param gemfireProperties {@link Properties} used by the {@link CacheFactory} to configure the {@link Cache}.
* @return a new instance of {@link CacheFactory} initialized with the given Pivotal GemFire/Apache Geode
@@ -365,11 +373,12 @@ public class CacheFactoryBean extends AbstractFactoryBeanSupport<GemFireCache>
}
/**
* Initializes the given cache factory with the configured {@link CacheFactoryInitializer}.
* Initializes the given {@link CacheFactory} with the configured {@link CacheFactoryInitializer}.
*
* @param factory cache factory to initialize; may be {@literal null}.
* @return the given cache factory.
* @param factory {@link CacheFactory} to initialize; may be {@literal null}.
* @return the initialized {@link CacheFactory}.
* @see org.springframework.data.gemfire.CacheFactoryBean.CacheFactoryInitializer#initialize(Object)
* @see org.apache.geode.cache.CacheFactory
* @see #getCacheFactoryInitializer()
*/
@Nullable
@@ -382,16 +391,17 @@ public class CacheFactoryBean extends AbstractFactoryBeanSupport<GemFireCache>
}
/**
* Prepares and initializes the {@link CacheFactory} used to create the {@link Cache}.
* Configures the {@link CacheFactory} used to create the {@link Cache}.
*
* Sets PDX options specified by the user.
*
* @param factory {@link CacheFactory} used to create the {@link Cache}.
* @return the prepared and initialized {@link CacheFactory}.
* @see #initializePdx(CacheFactory)
* @return the configured {@link CacheFactory}.
* @see org.apache.geode.cache.CacheFactory
* @see #configurePdx(CacheFactory)
*/
protected Object prepareFactory(Object factory) {
return initializePdx((CacheFactory) factory);
protected Object configureFactory(Object factory) {
return configurePdx((CacheFactory) factory);
}
/**
@@ -401,7 +411,7 @@ public class CacheFactoryBean extends AbstractFactoryBeanSupport<GemFireCache>
* @return the given {@link CacheFactory}.
* @see org.apache.geode.cache.CacheFactory
*/
private CacheFactory initializePdx(CacheFactory cacheFactory) {
private CacheFactory configurePdx(CacheFactory cacheFactory) {
Optional.ofNullable(getPdxSerializer()).ifPresent(cacheFactory::setPdxSerializer);
@@ -418,17 +428,28 @@ public class CacheFactoryBean extends AbstractFactoryBeanSupport<GemFireCache>
}
/**
* Creates a new {@link Cache} instance using the provided factory.
* Post processes the {@link CacheFactory} used to create the {@link Cache}.
*
* @param <T> parameterized {@link Class} type extension of {@link GemFireCache}.
* @param factory {@link CacheFactory} used to create the {@link Cache}.
* @return the post processed {@link CacheFactory}.
* @see org.apache.geode.cache.CacheFactory
*/
protected Object postProcess(Object factory) {
return factory;
}
/**
* Creates a new {@link Cache} instance using the provided {@link Object factory}.
*
* @param <T> {@link Class sub-type} of {@link GemFireCache}.
* @param factory instance of {@link CacheFactory}.
* @return a new instance of {@link Cache} created by the provided factory.
* @return a new instance of {@link Cache} created by the provided {@link Object factory}.
* @see org.apache.geode.cache.CacheFactory#create()
* @see org.apache.geode.cache.GemFireCache
*/
@SuppressWarnings("unchecked")
protected <T extends GemFireCache> T createCache(Object factory) {
return (T) Optional.ofNullable(getCache()).orElseGet(((CacheFactory) factory)::create);
return (T) ((CacheFactory) factory).create();
}
/**
@@ -449,16 +470,7 @@ public class CacheFactoryBean extends AbstractFactoryBeanSupport<GemFireCache>
@SuppressWarnings("all")
protected <T extends GemFireCache> T postProcess(T cache) {
// load cache.xml Resource and initialize the cache
Optional.ofNullable(getCacheXml()).ifPresent(cacheXml -> {
try {
logDebug("Initializing cache with [%s]", cacheXml);
cache.loadCacheXml(cacheXml.getInputStream());
}
catch (IOException e) {
throw newRuntimeException(e, "Failed to load cache.xml [%s]", cacheXml);
}
});
loadCacheXml(cache);
Optional.ofNullable(getCopyOnRead()).ifPresent(cache::setCopyOnRead);
@@ -472,20 +484,34 @@ public class CacheFactoryBean extends AbstractFactoryBeanSupport<GemFireCache>
configureHeapPercentages(cache);
configureOffHeapPercentages(cache);
registerJndiDataSources();
registerJndiDataSources(cache);
registerTransactionListeners(cache);
registerTransactionWriter(cache);
return cache;
}
/* (non-Javadoc) */
private boolean isHeapPercentageValid(Float heapPercentage) {
return (heapPercentage >= 0.0f && heapPercentage <= 100.0f);
private <T extends GemFireCache> T loadCacheXml(T cache) {
// Load cache.xml Resource and initialize the cache
Optional.ofNullable(getCacheXml()).ifPresent(cacheXml -> {
try {
logDebug("Initializing cache with [%s]", cacheXml);
cache.loadCacheXml(cacheXml.getInputStream());
}
catch (IOException cause) {
throw newRuntimeException(cause, "Failed to load cache.xml [%s]", cacheXml);
}
});
return cache;
}
/* (non-Javadoc) */
private void configureHeapPercentages(GemFireCache cache) {
private boolean isHeapPercentageValid(Float heapPercentage) {
return heapPercentage >= 0.0f && heapPercentage <= 100.0f;
}
private GemFireCache configureHeapPercentages(GemFireCache cache) {
Optional.ofNullable(getCriticalHeapPercentage()).ifPresent(criticalHeapPercentage -> {
@@ -502,10 +528,11 @@ public class CacheFactoryBean extends AbstractFactoryBeanSupport<GemFireCache>
cache.getResourceManager().setEvictionHeapPercentage(evictionHeapPercentage);
});
return cache;
}
/* (non-Javadoc) */
private void configureOffHeapPercentages(GemFireCache cache) {
private GemFireCache configureOffHeapPercentages(GemFireCache cache) {
Optional.ofNullable(getCriticalOffHeapPercentage()).ifPresent(criticalOffHeapPercentage -> {
@@ -522,10 +549,11 @@ public class CacheFactoryBean extends AbstractFactoryBeanSupport<GemFireCache>
cache.getResourceManager().setEvictionOffHeapPercentage(evictionOffHeapPercentage);
});
return cache;
}
/* (non-Javadoc) */
private void registerJndiDataSources() {
private GemFireCache registerJndiDataSources(GemFireCache cache) {
nullSafeCollection(getJndiDataSources()).forEach(jndiDataSource -> {
@@ -533,41 +561,30 @@ public class CacheFactoryBean extends AbstractFactoryBeanSupport<GemFireCache>
JndiDataSourceType jndiDataSourceType = JndiDataSourceType.valueOfIgnoreCase(type);
Assert.notNull(jndiDataSourceType, String.format(
"'jndi-binding' 'type' [%1$s] is invalid; 'type' must be one of %2$s", type,
Arrays.toString(JndiDataSourceType.values())));
Assert.notNull(jndiDataSourceType,
String.format("'jndi-binding' 'type' [%1$s] is invalid; 'type' must be one of %2$s",
type, Arrays.toString(JndiDataSourceType.values())));
jndiDataSource.getAttributes().put("type", jndiDataSourceType.getName());
JNDIInvoker.mapDatasource(jndiDataSource.getAttributes(), jndiDataSource.getProps());
});
return cache;
}
/* (non-Javadoc) */
private void registerTransactionListeners(GemFireCache cache) {
private GemFireCache registerTransactionListeners(GemFireCache cache) {
nullSafeCollection(getTransactionListeners())
.forEach(transactionListener -> cache.getCacheTransactionManager().addListener(transactionListener));
return cache;
}
/* (non-Javadoc) */
private void registerTransactionWriter(GemFireCache cache) {
private GemFireCache registerTransactionWriter(GemFireCache cache) {
Optional.ofNullable(getTransactionWriter()).ifPresent(it -> cache.getCacheTransactionManager().setWriter(it));
}
/**
* Destroys the {@link Cache} bean on Spring container shutdown.
*
* @throws Exception if an error occurs while closing the cache.
* @see org.springframework.beans.factory.DisposableBean#destroy()
* @see #destroyBeanFactoryLocator()
* @see #close(GemFireCache)
* @see #isClose()
*/
@Override
public void destroy() throws Exception {
if (isClose()) {
close(fetchCache());
destroyBeanFactoryLocator();
}
return cache;
}
/**
@@ -584,7 +601,25 @@ public class CacheFactoryBean extends AbstractFactoryBeanSupport<GemFireCache>
.filter(it -> !it.isClosed())
.ifPresent(RegionService::close);
this.cache = null;
setCache(null);
}
/**
* Destroys the {@link Cache} bean on Spring container shutdown.
*
* @throws Exception if an error occurs while closing the cache.
* @see org.springframework.beans.factory.DisposableBean#destroy()
* @see #destroyBeanFactoryLocator()
* @see #close(GemFireCache)
* @see #isClose()
*/
@Override
public void destroy() throws Exception {
if (isClose()) {
close(fetchCache());
destroyBeanFactoryLocator();
}
}
/**
@@ -612,7 +647,9 @@ public class CacheFactoryBean extends AbstractFactoryBeanSupport<GemFireCache>
public DataAccessException translateExceptionIfPossible(RuntimeException exception) {
if (exception instanceof IllegalArgumentException) {
DataAccessException wrapped = GemfireCacheUtils.convertQueryExceptions(exception);
// ignore conversion if generic exception is returned
if (!(wrapped instanceof GemfireSystemException)) {
return wrapped;
@@ -701,11 +738,12 @@ public class CacheFactoryBean extends AbstractFactoryBeanSupport<GemFireCache>
* @see #getCacheXml()
*/
private File getCacheXmlFile() {
try {
return getCacheXml().getFile();
}
catch (Throwable e) {
throw newIllegalStateException(e, "Resource [%s] is not resolvable as a file", getCacheXml());
catch (Throwable cause) {
throw newIllegalStateException(cause, "Resource [%s] is not resolvable as a file", getCacheXml());
}
}
@@ -715,9 +753,11 @@ public class CacheFactoryBean extends AbstractFactoryBeanSupport<GemFireCache>
* @return boolean value indicating whether a {@link Resource cache.xml} {@link File} is present.
* @see #getCacheXmlFile()
*/
@SuppressWarnings("all")
private boolean isCacheXmlAvailable() {
try {
return (getCacheXmlFile() != null);
return getCacheXmlFile() != null;
}
catch (Throwable ignore) {
return false;
@@ -735,7 +775,7 @@ public class CacheFactoryBean extends AbstractFactoryBeanSupport<GemFireCache>
@Override
@SuppressWarnings("all")
public GemFireCache getObject() throws Exception {
return Optional.ofNullable(this.<GemFireCache>getCache()).orElseGet(this::init);
return Optional.<GemFireCache>ofNullable(getCache()).orElseGet(this::init);
}
/**
@@ -751,26 +791,25 @@ public class CacheFactoryBean extends AbstractFactoryBeanSupport<GemFireCache>
}
/**
* Set the phase for the {@link Cache} bean in the lifecycle managed by the Spring container.
* Set the {@link CacheFactoryInitializer} that will be called to initialize the cache factory used to create
* the cache constructed by this {@link CacheFactoryBean}.
*
* @param phase {@link Integer#TYPE int} value indicating the phase of this {@link Cache} bean
* in the lifecycle managed by the Spring container.
* @see org.springframework.context.Phased#getPhase()
* @param cacheFactoryInitializer {@link CacheFactoryInitializer} configured to initialize the cache factory.
* @see org.springframework.data.gemfire.CacheFactoryBean.CacheFactoryInitializer
*/
protected void setPhase(int phase) {
this.phase = phase;
public void setCacheFactoryInitializer(CacheFactoryInitializer cacheFactoryInitializer) {
this.cacheFactoryInitializer = cacheFactoryInitializer;
}
/**
* Returns the configured phase of the {@link Cache} bean in the lifecycle managed by the Spring container.
* Return the {@link CacheFactoryInitializer} that will be called to initialize the cache factory used to create
* the cache constructed by this {@link CacheFactoryBean}.
*
* @return an {@link Integer#TYPE int} value indicating the phase of this {@link Cache} bean in the lifecycle
* managed by the Spring container.
* @see org.springframework.context.Phased#getPhase()
* @return the {@link CacheFactoryInitializer} configured to initialize the cache factory.
* @see org.springframework.data.gemfire.CacheFactoryBean.CacheFactoryInitializer
*/
@Override
public int getPhase() {
return this.phase;
public CacheFactoryInitializer getCacheFactoryInitializer() {
return this.cacheFactoryInitializer;
}
/**
@@ -807,28 +846,6 @@ public class CacheFactoryBean extends AbstractFactoryBeanSupport<GemFireCache>
return this.properties;
}
/**
* Set the {@link CacheFactoryInitializer} that will be called to initialize the cache factory used to create
* the cache constructed by this {@link CacheFactoryBean}.
*
* @param cacheFactoryInitializer {@link CacheFactoryInitializer} configured to initialize the cache factory.
* @see org.springframework.data.gemfire.CacheFactoryBean.CacheFactoryInitializer
*/
public void setCacheFactoryInitializer(CacheFactoryInitializer cacheFactoryInitializer) {
this.cacheFactoryInitializer = cacheFactoryInitializer;
}
/**
* Return the {@link CacheFactoryInitializer} that will be called to initialize the cache factory used to create
* the cache constructed by this {@link CacheFactoryBean}.
*
* @return the {@link CacheFactoryInitializer} configured to initialize the cache factory.
* @see org.springframework.data.gemfire.CacheFactoryBean.CacheFactoryInitializer
*/
public CacheFactoryInitializer getCacheFactoryInitializer() {
return this.cacheFactoryInitializer;
}
/**
* Sets a value to indicate whether the cache will be closed on shutdown of the Spring container.
*
@@ -939,7 +956,7 @@ public class CacheFactoryBean extends AbstractFactoryBeanSupport<GemFireCache>
* or not.
*/
public Boolean getEnableAutoReconnect() {
return enableAutoReconnect;
return this.enableAutoReconnect;
}
/**
@@ -1056,6 +1073,29 @@ public class CacheFactoryBean extends AbstractFactoryBeanSupport<GemFireCache>
return messageSyncInterval;
}
/**
* Set the phase for the {@link Cache} bean in the lifecycle managed by the Spring container.
*
* @param phase {@link Integer#TYPE int} value indicating the phase of this {@link Cache} bean
* in the lifecycle managed by the Spring container.
* @see org.springframework.context.Phased#getPhase()
*/
protected void setPhase(int phase) {
this.phase = phase;
}
/**
* Returns the configured phase of the {@link Cache} bean in the lifecycle managed by the Spring container.
*
* @return an {@link Integer#TYPE int} value indicating the phase of this {@link Cache} bean in the lifecycle
* managed by the Spring container.
* @see org.springframework.context.Phased#getPhase()
*/
@Override
public int getPhase() {
return this.phase;
}
/**
* Set the disk store that is used for PDX meta data. Applicable on GemFire
* 6.6 or higher.
@@ -1163,7 +1203,7 @@ public class CacheFactoryBean extends AbstractFactoryBeanSupport<GemFireCache>
* @see org.springframework.data.gemfire.config.annotation.PeerCacheConfigurer
*/
public void setPeerCacheConfigurers(List<PeerCacheConfigurer> peerCacheConfigurers) {
this.peerCacheConfigurers = Optional.ofNullable(peerCacheConfigurers).orElseGet(Collections::emptyList);
Optional.ofNullable(peerCacheConfigurers).ifPresent(this.peerCacheConfigurers::addAll);
}
/**
@@ -1278,9 +1318,9 @@ public class CacheFactoryBean extends AbstractFactoryBeanSupport<GemFireCache>
* @see org.apache.geode.cache.client.ClientCacheFactory
*/
T initialize(T cacheFactory);
}
/* (non-Javadoc) */
public static class DynamicRegionSupport {
private Boolean persistent = Boolean.TRUE;
@@ -1322,23 +1362,25 @@ public class CacheFactoryBean extends AbstractFactoryBeanSupport<GemFireCache>
}
public void initializeDynamicRegionFactory() {
File localDiskDirectory = (this.diskDirectory != null ? new File(this.diskDirectory) : null);
DynamicRegionFactory.Config config = new DynamicRegionFactory.Config(localDiskDirectory, poolName,
persistent, registerInterest);
File localDiskDirectory = this.diskDirectory != null ? new File(this.diskDirectory) : null;
DynamicRegionFactory.Config config =
new DynamicRegionFactory.Config(localDiskDirectory, this.poolName, this.persistent,
this.registerInterest);
DynamicRegionFactory.get().open(config);
}
}
/* (non-Javadoc) */
public static class JndiDataSource {
private List<ConfigProperty> props;
private List<ConfigProperty> configProperties;
private Map<String, String> attributes;
public Map<String, String> getAttributes() {
return attributes;
return this.attributes;
}
public void setAttributes(Map<String, String> attributes) {
@@ -1346,11 +1388,11 @@ public class CacheFactoryBean extends AbstractFactoryBeanSupport<GemFireCache>
}
public List<ConfigProperty> getProps() {
return props;
return this.configProperties;
}
public void setProps(List<ConfigProperty> props) {
this.props = props;
this.configProperties = props;
}
}
}

View File

@@ -0,0 +1,139 @@
/*
* 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;
import static org.springframework.data.gemfire.util.ArrayUtils.nullSafeArray;
import static org.springframework.data.gemfire.util.CollectionUtils.nullSafeCollection;
import static org.springframework.data.gemfire.util.CollectionUtils.nullSafeIterable;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.StreamSupport;
import org.apache.geode.cache.Region;
import org.springframework.data.gemfire.client.ClientRegionFactoryBean;
import org.springframework.data.gemfire.config.annotation.RegionConfigurer;
/**
* The ConfigurableRegionFactoryBean class...
*
* @author John Blum
* @see org.springframework.data.gemfire.RegionLookupFactoryBean
* @since 2.1.0
*/
@SuppressWarnings("unused")
public abstract class ConfigurableRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> {
private List<RegionConfigurer> regionConfigurers = Collections.emptyList();
private RegionConfigurer compositeRegionConfigurer = new RegionConfigurer() {
@Override
public void configure(String beanName, ClientRegionFactoryBean<?, ?> bean) {
nullSafeCollection(regionConfigurers)
.forEach(regionConfigurer -> regionConfigurer.configure(beanName, bean));
}
};
/**
* Returns a reference to the Composite {@link RegionConfigurer} used to apply additional configuration
* to this {@link ClientRegionFactoryBean} on Spring container initialization.
*
* @return the Composite {@link RegionConfigurer}.
* @see org.springframework.data.gemfire.config.annotation.RegionConfigurer
*/
protected RegionConfigurer getCompositeRegionConfigurer() {
return this.compositeRegionConfigurer;
}
/**
* Null-safe operation to set an array of {@link RegionConfigurer RegionConfigurers} used to apply
* additional configuration to this {@link ClientRegionFactoryBean} when using Annotation-based configuration.
*
* @param regionConfigurers array of {@link RegionConfigurer RegionConfigurers} used to apply
* additional configuration to this {@link ClientRegionFactoryBean}.
* @see org.springframework.data.gemfire.config.annotation.RegionConfigurer
* @see #setRegionConfigurers(List)
*/
public void setRegionConfigurers(RegionConfigurer... regionConfigurers) {
setRegionConfigurers(Arrays.asList(nullSafeArray(regionConfigurers, RegionConfigurer.class)));
}
/**
* Null-safe operation to set an {@link Iterable} of {@link RegionConfigurer RegionConfigurers} used to apply
* additional configuration to this {@link ClientRegionFactoryBean} when using Annotation-based configuration.
*
* @param regionConfigurers {@link Iterable} of {@link RegionConfigurer RegionConfigurers} used to apply
* additional configuration to this {@link ClientRegionFactoryBean}.
* @see org.springframework.data.gemfire.config.annotation.RegionConfigurer
*/
public void setRegionConfigurers(List<RegionConfigurer> regionConfigurers) {
this.regionConfigurers = Optional.ofNullable(regionConfigurers).orElseGet(Collections::emptyList);
}
/**
* Null-safe operation to apply the composite {@link RegionConfigurer RegionConfigurers}
* to this {@link ConfigurableRegionFactoryBean}.
*
* @param regionName {@link String} containing the name of the {@link Region}.
* to this {@link ConfigurableRegionFactoryBean}.
* @see org.springframework.data.gemfire.config.annotation.RegionConfigurer
* @see #applyRegionConfigurers(String, Iterable)
* @see #getCompositeRegionConfigurer()
*/
protected void applyRegionConfigurers(String regionName) {
applyRegionConfigurers(regionName, getCompositeRegionConfigurer());
}
/**
* Null-safe operation to apply the given array of {@link RegionConfigurer RegionConfigurers}
* to this {@link ConfigurableRegionFactoryBean}.
*
* @param regionName {@link String} containing the name of the {@link Region}.
* @param regionConfigurers array of {@link RegionConfigurer RegionConfigurers} applied
* to this {@link ConfigurableRegionFactoryBean}.
* @see org.springframework.data.gemfire.config.annotation.RegionConfigurer
* @see #applyRegionConfigurers(String, Iterable)
*/
protected void applyRegionConfigurers(String regionName, RegionConfigurer... regionConfigurers) {
applyRegionConfigurers(regionName, Arrays.asList(nullSafeArray(regionConfigurers, RegionConfigurer.class)));
}
/**
* Null-safe operation to apply the given {@link Iterable} of {@link RegionConfigurer RegionConfigurers}
* to this {@link ConfigurableRegionFactoryBean}.
*
* @param regionName {@link String} containing the name of the {@link Region}.
* @param regionConfigurers {@link Iterable} of {@link RegionConfigurer RegionConfigurers} applied
* to this {@link ConfigurableRegionFactoryBean}.
* @see org.springframework.data.gemfire.config.annotation.RegionConfigurer
* @see #applyRegionConfigurers(String, RegionConfigurer...)
*/
protected void applyRegionConfigurers(String regionName, Iterable<RegionConfigurer> regionConfigurers) {
if (this instanceof RegionFactoryBean) {
StreamSupport.stream(nullSafeIterable(regionConfigurers).spliterator(), false)
.forEach(regionConfigurer -> regionConfigurer.configure(regionName, (RegionFactoryBean<K, V>) this));
}
else if (this instanceof ClientRegionFactoryBean) {
StreamSupport.stream(nullSafeIterable(regionConfigurers).spliterator(), false)
.forEach(regionConfigurer -> regionConfigurer.configure(regionName, (ClientRegionFactoryBean<K, V>) this));
}
}
}

View File

@@ -21,8 +21,10 @@ import java.util.concurrent.ConcurrentMap;
import org.apache.geode.cache.CacheFactory;
import org.apache.geode.cache.Region;
import org.apache.geode.internal.GemFireVersion;
import org.springframework.data.gemfire.config.support.GemfireFeature;
import org.springframework.data.gemfire.util.RegionUtils;
import org.springframework.util.ClassUtils;
import org.w3c.dom.Element;
/**
* {@link GemfireUtils} is an abstract utility class encapsulating common functionality to access features
@@ -37,11 +39,20 @@ import org.springframework.util.ClassUtils;
@SuppressWarnings("unused")
public abstract class GemfireUtils extends RegionUtils {
public final static String APACHE_GEODE_NAME = "Apache Geode";
public final static String APACHE_GEODE_NAME = "Aache Geode";
public final static String GEMFIRE_NAME = apacheGeodeProductName();
public final static String GEMFIRE_VERSION = apacheGeodeVersion();
public final static String UNKNOWN = "unknown";
private static final String ASYNC_EVENT_QUEUE_ELEMENT_NAME = "async-event-queue";
private static final String ASYNC_EVENT_QUEUE_TYPE_NAME = "org.apache.geode.cache.asyncqueue.AsyncEventQueue";
private static final String CQ_ELEMENT_NAME = "cq-listener-container";
private static final String CQ_TYPE_NAME = "org.apache.geode.cache.query.internal.cq.CqServiceFactoryImpl";
private static final String GATEWAY_RECEIVER_ELEMENT_NAME = "gateway-receiver";
private static final String GATEWAY_RECEIVER_TYPE_NAME = "org.apache.geode.internal.cache.wan.GatewayReceiverFactoryImpl";
private static final String GATEWAY_SENDER_ELEMENT_NAME = "gateway-sender";
private static final String GATEWAY_SENDER_TYPE_NAME = "org.apache.geode.internal.cache.wan.GatewaySenderFactoryImpl";
/* (non-Javadoc) */
public static String apacheGeodeProductName() {
@@ -65,52 +76,78 @@ public abstract class GemfireUtils extends RegionUtils {
}
/* (non-Javadoc) */
public static boolean isGemfireVersionGreaterThanEqualTo(double expectedVersion) {
double actualVersion = Double.parseDouble(GEMFIRE_VERSION.substring(0, 3));
return actualVersion >= expectedVersion;
public static boolean isClassAvailable(String fullyQualifiedClassName) {
return ClassUtils.isPresent(fullyQualifiedClassName, GemfireUtils.class.getClassLoader());
}
/* (non-Javadoc) */
public static boolean isGemfireVersion65OrAbove() {
// expected 'major.minor'
try {
double version = Double.parseDouble(GEMFIRE_VERSION.substring(0, 3));
return version >= 6.5;
}
catch (NumberFormatException e) {
// NOTE based on logic from the PartitionedRegionFactoryBean class...
return ConcurrentMap.class.isAssignableFrom(Region.class);
}
public static boolean isGemfireFeatureAvailable(GemfireFeature feature) {
boolean featureAvailable = (!GemfireFeature.AEQ.equals(feature) || isAsyncEventQueueAvailable());
featureAvailable &= (!GemfireFeature.CONTINUOUS_QUERY.equals(feature) || isContinuousQueryAvailable());
featureAvailable &= (!GemfireFeature.WAN.equals(feature) || isGatewayAvailable());
return featureAvailable;
}
/* (non-Javadoc) */
public static boolean isGemfireVersion7OrAbove() {
try {
return isGemfireVersionGreaterThanEqualTo(7.0);
}
catch (NumberFormatException e) {
// NOTE the org.apache.geode.distributed.ServerLauncher class only exists in GemFire v 7.0.x or above...
return ClassUtils.isPresent("org.apache.geode.distributed.ServerLauncher",
Thread.currentThread().getContextClassLoader());
}
public static boolean isGemfireFeatureAvailable(Element element) {
boolean featureAvailable = (!isAsyncEventQueue(element) || isAsyncEventQueueAvailable());
featureAvailable &= (!isContinuousQuery(element) || isContinuousQueryAvailable());
featureAvailable &= (!isGateway(element) || isGatewayAvailable());
return featureAvailable;
}
/* (non-Javadoc) */
public static boolean isGemfireVersion8OrAbove() {
public static boolean isGemfireFeatureUnavailable(GemfireFeature feature) {
return !isGemfireFeatureAvailable(feature);
}
try {
return isGemfireVersionGreaterThanEqualTo(8.0);
}
catch (NumberFormatException e) {
// NOTE the org.apache.geode.management.internal.web.domain.LinkIndex class only exists
// in GemFire v 8.0.0 or above...
return ClassUtils.isPresent("org.apache.geode.management.internal.web.domain.LinkIndex",
Thread.currentThread().getContextClassLoader());
}
/* (non-Javadoc) */
public static boolean isGemfireFeatureUnavailable(Element element) {
return !isGemfireFeatureAvailable(element);
}
/* (non-Javadoc) */
private static boolean isAsyncEventQueue(Element element) {
return ASYNC_EVENT_QUEUE_ELEMENT_NAME.equals(element.getLocalName());
}
/* (non-Javadoc) */
private static boolean isAsyncEventQueueAvailable() {
return isClassAvailable(ASYNC_EVENT_QUEUE_TYPE_NAME);
}
/* (non-Javadoc) */
private static boolean isContinuousQuery(Element element) {
return CQ_ELEMENT_NAME.equals(element.getLocalName());
}
/* (non-Javadoc) */
private static boolean isContinuousQueryAvailable() {
return isClassAvailable(CQ_TYPE_NAME);
}
/* (non-Javadoc) */
private static boolean isGateway(Element element) {
String elementLocalName = element.getLocalName();
return (GATEWAY_RECEIVER_ELEMENT_NAME.equals(elementLocalName)
|| GATEWAY_SENDER_ELEMENT_NAME.equals(elementLocalName));
}
/* (non-Javadoc) */
private static boolean isGatewayAvailable() {
return isClassAvailable(GATEWAY_SENDER_TYPE_NAME);
}
public static void main(final String... args) {
System.out.printf("GemFire Version %1$s%n", GEMFIRE_VERSION);
System.out.printf("GemFire Product Name (%1$s) Version (%2$s)%n", GEMFIRE_NAME, GEMFIRE_VERSION);
//System.out.printf("Is GemFire Version 6.5 of Above? %1$s%n", isGemfireVersion65OrAbove());
//System.out.printf("Is GemFire Version 7.0 of Above? %1$s%n", isGemfireVersion7OrAbove());
}

View File

@@ -16,36 +16,38 @@
package org.springframework.data.gemfire;
import org.apache.geode.cache.AttributesMutator;
import static org.springframework.data.gemfire.util.ArrayUtils.nullSafeArray;
import java.util.Arrays;
import java.util.Optional;
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.EvictionAttributesMutator;
import org.apache.geode.cache.ExpirationAttributes;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.asyncqueue.AsyncEventQueue;
import org.apache.geode.cache.wan.GatewaySender;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
/**
* The LookupRegionFactoryBean class is a concrete implementation of RegionLookupFactoryBean for handling
* &gt;gfe:lookup-region/&lt; SDG XML namespace (XSD) elements.
*
* @author John Blum
* @see org.springframework.data.gemfire.RegionLookupFactoryBean
* @see RegionLookupFactoryBean
* @see org.apache.geode.cache.AttributesMutator
* @since 1.6.0
*/
@SuppressWarnings("unused")
public class LookupRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> {
private AsyncEventQueue[] asyncEventQueues;
private Boolean cloningEnabled;
private Boolean enableStatistics;
private AsyncEventQueue[] asyncEventQueues;
private CacheListener<K, V>[] cacheListeners;
private CacheLoader<K, V> cacheLoader;
@@ -66,166 +68,123 @@ public class LookupRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
@Override
public void afterPropertiesSet() throws Exception {
super.afterPropertiesSet();
AttributesMutator<K, V> attributesMutator = getRegion().getAttributesMutator();
Optional.ofNullable(getRegion().getAttributesMutator()).ifPresent(attributesMutator -> {
if (!ObjectUtils.isEmpty(asyncEventQueues)) {
for (AsyncEventQueue asyncEventQueue : asyncEventQueues) {
attributesMutator.addAsyncEventQueueId(asyncEventQueue.getId());
}
}
Arrays.stream(nullSafeArray(this.asyncEventQueues, AsyncEventQueue.class))
.map(AsyncEventQueue::getId)
.forEach(attributesMutator::addAsyncEventQueueId);
if (!ObjectUtils.isEmpty(cacheListeners)) {
for (CacheListener<K, V> cacheListener : cacheListeners) {
attributesMutator.addCacheListener(cacheListener);
}
}
Arrays.stream(nullSafeArray(this.cacheListeners, CacheListener.class))
.forEach(attributesMutator::addCacheListener);
if (cacheLoader != null) {
attributesMutator.setCacheLoader(cacheLoader);
}
Optional.ofNullable(this.cacheLoader).ifPresent(attributesMutator::setCacheLoader);
Optional.ofNullable(this.cacheWriter).ifPresent(attributesMutator::setCacheWriter);
Optional.ofNullable(this.cloningEnabled).ifPresent(attributesMutator::setCloningEnabled);
if (cacheWriter != null) {
attributesMutator.setCacheWriter(cacheWriter);
}
// Eviction
Optional.ofNullable(attributesMutator.getEvictionAttributesMutator())
.ifPresent(evictionAttributesMutator -> Optional.ofNullable(this.evictionMaximum)
.ifPresent(evictionAttributesMutator::setMaximum));
if (cloningEnabled != null) {
attributesMutator.setCloningEnabled(cloningEnabled);
}
// Expiration
if (isStatisticsEnabled()) {
if (isStatisticsEnabled()) {
assertStatisticsEnabled();
assertStatisticsEnabled();
if (customEntryIdleTimeout != null) {
attributesMutator.setCustomEntryIdleTimeout(customEntryIdleTimeout);
Optional.ofNullable(this.customEntryIdleTimeout).ifPresent(attributesMutator::setCustomEntryIdleTimeout);
Optional.ofNullable(this.customEntryTimeToLive).ifPresent(attributesMutator::setCustomEntryTimeToLive);
Optional.ofNullable(this.entryIdleTimeout).ifPresent(attributesMutator::setEntryIdleTimeout);
Optional.ofNullable(this.entryTimeToLive).ifPresent(attributesMutator::setEntryTimeToLive);
Optional.ofNullable(this.regionIdleTimeout).ifPresent(attributesMutator::setRegionIdleTimeout);
Optional.ofNullable(this.regionTimeToLive).ifPresent(attributesMutator::setRegionTimeToLive);
}
if (customEntryTimeToLive != null) {
attributesMutator.setCustomEntryTimeToLive(customEntryTimeToLive);
}
if (entryIdleTimeout != null) {
attributesMutator.setEntryIdleTimeout(entryIdleTimeout);
}
if (entryTimeToLive != null) {
attributesMutator.setEntryTimeToLive(entryTimeToLive);
}
if (regionIdleTimeout != null) {
attributesMutator.setRegionIdleTimeout(regionIdleTimeout);
}
if (regionTimeToLive != null) {
attributesMutator.setRegionTimeToLive(regionTimeToLive);
}
}
if (evictionMaximum != null) {
EvictionAttributesMutator evictionAttributesMutator = attributesMutator.getEvictionAttributesMutator();
evictionAttributesMutator.setMaximum(evictionMaximum);
}
if (!ObjectUtils.isEmpty(gatewaySenders)) {
for (GatewaySender gatewaySender : gatewaySenders) {
attributesMutator.addGatewaySenderId(gatewaySender.getId());
}
}
Arrays.stream(nullSafeArray(this.gatewaySenders, GatewaySender.class))
.map(GatewaySender::getId)
.forEach(attributesMutator::addGatewaySenderId);
});
}
@Override
final boolean isLookupEnabled() {
public final boolean isLookupEnabled() {
return true;
}
/* (non-Javadoc) */
public void setAsyncEventQueues(AsyncEventQueue[] asyncEventQueues) {
this.asyncEventQueues = asyncEventQueues;
}
/* (non-Javadoc) */
public void setCacheListeners(CacheListener<K, V>[] cacheListeners) {
this.cacheListeners = cacheListeners;
}
/* (non-Javadoc) */
public void setCacheLoader(CacheLoader<K, V> cacheLoader) {
this.cacheLoader = cacheLoader;
}
/* (non-Javadoc) */
public void setCacheWriter(CacheWriter<K, V> cacheWriter) {
this.cacheWriter = cacheWriter;
}
/* (non-Javadoc) */
public void setCloningEnabled(Boolean cloningEnabled) {
this.cloningEnabled = cloningEnabled;
}
/* (non-Javadoc) */
public void setCustomEntryIdleTimeout(CustomExpiry<K, V> customEntryIdleTimeout) {
setStatisticsEnabled(customEntryIdleTimeout != null);
this.customEntryIdleTimeout = customEntryIdleTimeout;
}
/* (non-Javadoc) */
public void setCustomEntryTimeToLive(CustomExpiry<K, V> customEntryTimeToLive) {
setStatisticsEnabled(customEntryTimeToLive != null);
this.customEntryTimeToLive = customEntryTimeToLive;
}
/* (non-Javadoc) */
public void setEntryIdleTimeout(ExpirationAttributes entryIdleTimeout) {
setStatisticsEnabled(entryIdleTimeout != null);
this.entryIdleTimeout = entryIdleTimeout;
}
/* (non-Javadoc) */
public void setEntryTimeToLive(ExpirationAttributes entryTimeToLive) {
setStatisticsEnabled(entryTimeToLive != null);
this.entryTimeToLive = entryTimeToLive;
}
/* (non-Javadoc) */
public void setEvictionMaximum(final Integer evictionMaximum) {
this.evictionMaximum = evictionMaximum;
}
/* (non-Javadoc) */
public void setGatewaySenders(GatewaySender[] gatewaySenders) {
this.gatewaySenders = gatewaySenders;
}
/* (non-Javadoc) */
public void setRegionIdleTimeout(ExpirationAttributes regionIdleTimeout) {
setStatisticsEnabled(regionIdleTimeout != null);
this.regionIdleTimeout = regionIdleTimeout;
}
/* (non-Javadoc) */
public void setRegionTimeToLive(ExpirationAttributes regionTimeToLive) {
setStatisticsEnabled(regionTimeToLive != null);
this.regionTimeToLive = regionTimeToLive;
}
/* (non-Javadoc) */
public void setStatisticsEnabled(Boolean enableStatistics) {
this.enableStatistics = enableStatistics;
}
/* (non-Javadoc) */
protected boolean isStatisticsEnabled() {
return Boolean.TRUE.equals(this.enableStatistics);
}
/* (non-Javadoc) */
private void assertStatisticsEnabled() {
Region localRegion = getRegion();
Assert.state(localRegion.getAttributes().getStatisticsEnabled(), String.format(
"Statistics for Region '%1$s' must be enabled to change Entry & Region TTL/TTI Expiration settings",
Assert.state(localRegion.getAttributes().getStatisticsEnabled(),
String.format("Statistics for Region [%s] must be enabled to change Entry & Region TTL/TTI Expiration settings",
localRegion.getFullPath()));
}
}

View File

@@ -15,9 +15,9 @@
*/
package org.springframework.data.gemfire;
import org.apache.geode.cache.CacheFactory;
import org.apache.geode.cache.DataPolicy;
import org.apache.geode.cache.RegionFactory;
import org.springframework.data.gemfire.util.RegionUtils;
import org.springframework.util.Assert;
/**
@@ -29,11 +29,6 @@ public class PartitionedRegionFactoryBean<K, V> extends RegionFactoryBean<K, V>
@Override
protected void resolveDataPolicy(RegionFactory<K, V> regionFactory, Boolean persistent, DataPolicy dataPolicy) {
// First, verify the GemFire version is 6.5 or Higher when Persistence is specified...
Assert.isTrue(!DataPolicy.PERSISTENT_PARTITION.equals(dataPolicy) || GemfireUtils.isGemfireVersion65OrAbove(),
String.format("Persistent PARTITION Regions can only be used from GemFire 6.5 onwards; current version is [%s].",
CacheFactory.getVersion()));
if (dataPolicy == null) {
dataPolicy = (isPersistent() ? DataPolicy.PERSISTENT_PARTITION : DataPolicy.PARTITION);
}
@@ -45,7 +40,7 @@ public class PartitionedRegionFactoryBean<K, V> extends RegionFactoryBean<K, V>
}
// Validate the data-policy and persistent attributes are compatible when specified!
assertDataPolicyAndPersistentAttributesAreCompatible(dataPolicy);
RegionUtils.assertDataPolicyAndPersistentAttributeAreCompatible(dataPolicy, persistent);
regionFactory.setDataPolicy(dataPolicy);
setDataPolicy(dataPolicy);

View File

@@ -18,19 +18,11 @@ package org.springframework.data.gemfire;
import static java.util.Arrays.stream;
import static org.springframework.data.gemfire.util.ArrayUtils.nullSafeArray;
import static org.springframework.data.gemfire.util.CollectionUtils.nullSafeCollection;
import static org.springframework.data.gemfire.util.CollectionUtils.nullSafeIterable;
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalArgumentException;
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalStateException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.StreamSupport;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.geode.cache.AttributesFactory;
import org.apache.geode.cache.Cache;
import org.apache.geode.cache.CacheListener;
@@ -56,7 +48,7 @@ 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.config.annotation.RegionConfigurer;
import org.springframework.data.gemfire.util.RegionUtils;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.ReflectionUtils;
@@ -88,16 +80,15 @@ import org.springframework.util.StringUtils;
* @see org.apache.geode.cache.asyncqueue.AsyncEventQueue
* @see org.springframework.beans.factory.DisposableBean
* @see org.springframework.context.SmartLifecycle
* @see org.springframework.data.gemfire.RegionLookupFactoryBean
* @see RegionLookupFactoryBean
* @see org.springframework.data.gemfire.client.ClientRegionFactoryBean
* @see org.springframework.data.gemfire.config.annotation.RegionConfigurer
*/
@SuppressWarnings("unused")
public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
// TODO: Rename to PeerRegionFatoryBean in SD Lovelace
public abstract class RegionFactoryBean<K, V> extends ConfigurableRegionFactoryBean<K, V>
implements DisposableBean, SmartLifecycle {
protected final Log log = LogFactory.getLog(getClass());
private boolean close = true;
private boolean destroy = false;
private boolean running;
@@ -124,19 +115,8 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
private GatewaySender[] gatewaySenders;
private List<RegionConfigurer> regionConfigurers = Collections.emptyList();
private RegionAttributes<K, V> attributes;
private RegionConfigurer compositeRegionConfigurer = new RegionConfigurer() {
@Override
public void configure(String beanName, RegionFactoryBean<?, ?> bean) {
nullSafeCollection(regionConfigurers)
.forEach(regionConfigurer -> regionConfigurer.configure(beanName, bean));
}
};
private RegionShortcut shortcut;
private Resource snapshot;
@@ -170,40 +150,6 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
return enableAsLockGrantor(region);
}
/* (non-Javadoc) */
private void applyRegionConfigurers(String regionName) {
applyRegionConfigurers(regionName, getCompositeRegionConfigurer());
}
/**
* Null-safe operation to apply the given array of {@link RegionConfigurer RegionConfigurers}
* to this {@link RegionFactoryBean}.
*
* @param regionName {@link String} containing the name of the {@link Region}.
* @param regionConfigurers array of {@link RegionConfigurer RegionConfigurers} applied
* to this {@link RegionFactoryBean}.
* @see org.springframework.data.gemfire.config.annotation.RegionConfigurer
* @see #applyRegionConfigurers(String, Iterable)
*/
protected void applyRegionConfigurers(String regionName, RegionConfigurer... regionConfigurers) {
applyRegionConfigurers(regionName, Arrays.asList(nullSafeArray(regionConfigurers, RegionConfigurer.class)));
}
/**
* Null-safe operation to apply the given {@link Iterable} of {@link RegionConfigurer RegionConfigurers}
* to this {@link RegionFactoryBean}.
*
* @param regionName {@link String} containing the name of the {@link Region}.
* @param regionConfigurers {@link Iterable} of {@link RegionConfigurer RegionConfigurers} applied
* to this {@link RegionFactoryBean}.
* @see org.springframework.data.gemfire.config.annotation.RegionConfigurer
*/
protected void applyRegionConfigurers(String regionName, Iterable<RegionConfigurer> regionConfigurers) {
StreamSupport.stream(nullSafeIterable(regionConfigurers).spliterator(), false)
.forEach(regionConfigurer -> regionConfigurer.configure(regionName, this));
}
/* (non-Javadoc) */
private Region<K, V> enableAsLockGrantor(Region<K, V> region) {
Optional.ofNullable(region)
@@ -213,7 +159,6 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
return region;
}
/* (non-Javadoc) */
private Region<K, V> newRegion(RegionFactory<K, V> regionFactory, Region<?, ?> parentRegion, String regionName) {
return Optional.ofNullable(parentRegion)
@@ -230,7 +175,6 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
});
}
/* (non-Javadoc) */
private Cache resolveCache(GemFireCache gemfireCache) {
return Optional.ofNullable(gemfireCache)
@@ -239,7 +183,6 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
.orElseThrow(() -> newIllegalArgumentException("Peer Cache is required"));
}
/* (non-Javadoc) */
private RegionAttributes<K, V> verifyLockGrantorEligibility(RegionAttributes<K, V> regionAttributes, Scope scope) {
Optional.ofNullable(regionAttributes).ifPresent(attributes ->
@@ -249,9 +192,8 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
return regionAttributes;
}
/* (non-Javadoc) */
private boolean verifyScope(Scope scope) {
return (scope == null || Scope.GLOBAL.equals(scope));
return scope == null || Scope.GLOBAL.equals(scope);
}
/**
@@ -314,7 +256,7 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
Optional.ofNullable(this.evictionAttributes).ifPresent(regionFactory::setEvictionAttributes);
stream(nullSafeArray(this.gatewaySenders, GatewaySender.class))
.forEach(gatewaySender -> regionFactory.addGatewaySenderId(((GatewaySender) gatewaySender).getId()));
.forEach(gatewaySender -> regionFactory.addGatewaySenderId(gatewaySender.getId()));
Optional.ofNullable(this.keyConstraint).ifPresent(regionFactory::setKeyConstraint);
@@ -343,23 +285,12 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
return regionFactory;
}
/**
* Returns a reference to the Composite {@link RegionConfigurer} used to apply additional configuration
* to this {@link RegionFactoryBean} on Spring container initialization.
*
* @return the Composite {@link RegionConfigurer}.
* @see org.springframework.data.gemfire.config.annotation.RegionConfigurer
*/
protected RegionConfigurer getCompositeRegionConfigurer() {
return this.compositeRegionConfigurer;
}
/*
* (non-Javadoc)
*
* This method is not considered part of the RegionFactoryBean API and is strictly used for testing purposes!
*
* NOTE cannot pass RegionAttributes.class as the "targetType" in the second invocation of getFieldValue(..)
* NOTE: Cannot pass RegionAttributes.class as the "targetType" in the second invocation of getFieldValue(..)
* since the "regionAttributes" field is naively declared as a instance of the implementation class type
* (RegionAttributesImpl) rather than the interface type (RegionAttributes)...
* so much for 'programming to interfaces' in GemFire!
@@ -378,7 +309,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) {
@@ -470,27 +400,30 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
// NOTE: PartitionAttributes are created by certain RegionShortcuts; need the null check since RegionAttributes
// can technically return null!
// NOTE: most likely, the PartitionAttributes will never be null since the PartitionRegionFactoryBean always
// NOTE: Most likely, the PartitionAttributes will never be null since the PartitionRegionFactoryBean always
// sets a PartitionAttributesFactoryBean BeanBuilder on the RegionAttributesFactoryBean "partitionAttributes"
// property.
if (regionAttributes.getPartitionAttributes() != null) {
PartitionAttributes partitionAttributes = regionAttributes.getPartitionAttributes();
PartitionAttributesFactory partitionAttributesFactory = new PartitionAttributesFactory(partitionAttributes);
RegionShortcutWrapper shortcutWrapper = RegionShortcutWrapper.valueOf(shortcut);
// NOTE however, since the default value of redundancy is 0, we need to account for 'redundant'
// NOTE: However, since the default value of redundancy is 0, we need to account for 'redundant'
// RegionShortcut types, which specify a redundancy of 1.
if (shortcutWrapper.isRedundant() && partitionAttributes.getRedundantCopies() == 0) {
partitionAttributesFactory.setRedundantCopies(1);
}
// NOTE and, since the default value of localMaxMemory is based on the system memory, we need to account for
// 'proxy' RegionShortcut types, which specify a local max memory of 0.
// NOTE: And, since the default value of localMaxMemory is based on the system memory, we need to
// account for 'proxy' RegionShortcut types, which specify a local max memory of 0.
if (shortcutWrapper.isProxy()) {
partitionAttributesFactory.setLocalMaxMemory(0);
}
// NOTE internally, RegionFactory.setPartitionAttributes handles merging the PartitionAttributes, hooray!
// NOTE: Internally, RegionFactory.setPartitionAttributes handles merging the PartitionAttributes, hooray!
regionFactory.setPartitionAttributes(partitionAttributesFactory.create());
}
}
@@ -521,12 +454,12 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
&& ((UserSpecifiedRegionAttributes) regionAttributes).hasEvictionAttributes());
}
/* (non-Javadoc) */
private boolean isDiskStoreConfigurationAllowed() {
boolean allow = StringUtils.hasText(this.diskStoreName);
allow &= (getDataPolicy().withPersistence() || (getAttributes() != null
allow &= (getDataPolicy().withPersistence()
|| (getAttributes() != null
&& getAttributes().getEvictionAttributes() != null
&& EvictionAction.OVERFLOW_TO_DISK.equals(attributes.getEvictionAttributes().getAction())));
@@ -541,23 +474,11 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
* @return true when the user specified an explicit value for the persistent attribute and it is true;
* false otherwise.
* @see #isNotPersistent()
* @see #isPersistentUnspecified()
*/
protected boolean isPersistent() {
return Boolean.TRUE.equals(persistent);
}
/**
* Determines whether the user explicitly set the 'persistent' attribute or not.
*
* @return a boolean value indicating whether the user explicitly set the 'persistent' attribute to true or false.
* @see #isPersistent()
* @see #isNotPersistent()
*/
protected boolean isPersistentUnspecified() {
return (persistent == null);
}
/**
* Returns true when the user explicitly specified a value for the persistent attribute and it is false. If the
* persistent attribute was not explicitly specified, then the persistence setting is implicitly undefined
@@ -566,38 +487,16 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
* @return true when the user specified an explicit value for the persistent attribute and it is false;
* false otherwise.
* @see #isPersistent()
* @see #isPersistentUnspecified()
*/
protected boolean isNotPersistent() {
return Boolean.FALSE.equals(persistent);
}
/**
* Validates that the settings for Data Policy and the 'persistent' attribute in &lt;gfe:*-region&gt; elements
* are compatible.
*
* @param resolvedDataPolicy the GemFire Data Policy resolved form the Spring GemFire XML namespace configuration
* meta-data.
* @see #isPersistent()
* @see #isNotPersistent()
* @see org.apache.geode.cache.DataPolicy
*/
protected void assertDataPolicyAndPersistentAttributesAreCompatible(DataPolicy resolvedDataPolicy) {
if (resolvedDataPolicy.withPersistence()) {
Assert.isTrue(isPersistentUnspecified() || isPersistent(), String.format(
"Data Policy [%s] is invalid when persistent is false.", resolvedDataPolicy));
}
else {
// NOTE otherwise, the Data Policy is not persistent, so...
Assert.isTrue(isPersistentUnspecified() || isNotPersistent(), String.format(
"Data Policy [%s] is invalid when persistent is true.", resolvedDataPolicy));
}
}
/**
=======
>>>>>>> c22ebe6... DATAGEODE-12 - Introduce Spring Configurers to flexibly alter Spring Data GemFire configuration when using Annotation config.
=======
>>>>>>> 1fd41c9... DATAGEODE-100 - Avoid Pool Already Exists Exception on Spring container initialization.
* Validates and sets the Data Policy on the RegionFactory used to create and configure the Region from this
* FactoryBean.
*
@@ -612,7 +511,7 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
protected void resolveDataPolicy(RegionFactory<K, V> regionFactory, Boolean persistent, DataPolicy dataPolicy) {
if (dataPolicy != null) {
assertDataPolicyAndPersistentAttributesAreCompatible(dataPolicy);
RegionUtils.assertDataPolicyAndPersistentAttributeAreCompatible(dataPolicy, this.persistent);
regionFactory.setDataPolicy(dataPolicy);
setDataPolicy(dataPolicy);
}
@@ -637,8 +536,9 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
DataPolicy resolvedDataPolicy = new DataPolicyConverter().convert(dataPolicy);
Assert.notNull(resolvedDataPolicy, String.format("Data Policy [%s] is invalid.", dataPolicy));
assertDataPolicyAndPersistentAttributesAreCompatible(resolvedDataPolicy);
Assert.notNull(resolvedDataPolicy, String.format("Data Policy [%s] is invalid", dataPolicy));
RegionUtils.assertDataPolicyAndPersistentAttributeAreCompatible(resolvedDataPolicy, this.persistent);
regionFactory.setDataPolicy(resolvedDataPolicy);
setDataPolicy(resolvedDataPolicy);
@@ -646,17 +546,17 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
else {
DataPolicy regionAttributesDataPolicy = getDataPolicy(getAttributes(), DataPolicy.DEFAULT);
DataPolicy resolvedDataPolicy = (isPersistent() && DataPolicy.DEFAULT.equals(regionAttributesDataPolicy)
? DataPolicy.PERSISTENT_REPLICATE : regionAttributesDataPolicy);
assertDataPolicyAndPersistentAttributesAreCompatible(resolvedDataPolicy);
DataPolicy resolvedDataPolicy = isPersistent() && DataPolicy.DEFAULT.equals(regionAttributesDataPolicy)
? DataPolicy.PERSISTENT_REPLICATE : regionAttributesDataPolicy;
RegionUtils.assertDataPolicyAndPersistentAttributeAreCompatible(resolvedDataPolicy, this.persistent);
regionFactory.setDataPolicy(resolvedDataPolicy);
setDataPolicy(resolvedDataPolicy);
}
}
/* (non-Javadoc) */
private DataPolicy getDataPolicy(RegionAttributes regionAttributes, DataPolicy defaultDataPolicy) {
return Optional.ofNullable(regionAttributes).map(RegionAttributes::getDataPolicy).orElse(defaultDataPolicy);
}
@@ -877,31 +777,6 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
this.persistent = persistent;
}
/**
* Null-safe operation to set an array of {@link RegionConfigurer RegionConfigurers} used to apply
* additional configuration to this {@link RegionFactoryBean} when using Annotation-based configuration.
*
* @param regionConfigurers array of {@link RegionConfigurer RegionConfigurers} used to apply
* additional configuration to this {@link RegionFactoryBean}.
* @see org.springframework.data.gemfire.config.annotation.RegionConfigurer
* @see #setRegionConfigurers(List)
*/
public void setRegionConfigurers(RegionConfigurer... regionConfigurers) {
setRegionConfigurers(Arrays.asList(nullSafeArray(regionConfigurers, RegionConfigurer.class)));
}
/**
* Null-safe operation to set an {@link Iterable} of {@link RegionConfigurer RegionConfigurers} used to apply
* additional configuration to this {@link RegionFactoryBean} when using Annotation-based configuration.
*
* @param regionConfigurers {@link Iterable} of {@link RegionConfigurer RegionConfigurers} used to apply
* additional configuration to this {@link RegionFactoryBean}.
* @see org.springframework.data.gemfire.config.annotation.RegionConfigurer
*/
public void setRegionConfigurers(List<RegionConfigurer> regionConfigurers) {
this.regionConfigurers = Optional.ofNullable(regionConfigurers).orElseGet(Collections::emptyList);
}
public Scope getScope() {
return this.scope;
}
@@ -936,16 +811,14 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
this.valueConstraint = valueConstraint;
}
/**
* @inheritDoc
*/
@Override
@SuppressWarnings("all")
public void start() {
if (!ObjectUtils.isEmpty(gatewaySenders)) {
synchronized (gatewaySenders) {
for (GatewaySender gatewaySender: gatewaySenders) {
if (!ObjectUtils.isEmpty(this.gatewaySenders)) {
synchronized (this.gatewaySenders) {
for (Object obj : this.gatewaySenders) {
GatewaySender gatewaySender = (GatewaySender) obj;
if (!(gatewaySender.isManualStart() || gatewaySender.isRunning())) {
gatewaySender.start();
}
@@ -956,24 +829,19 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
this.running = true;
}
/**
* @inheritDoc
*/
@Override
public void stop(Runnable callback) {
stop();
callback.run();
}
/**
* @inheritDoc
*/
@Override
@SuppressWarnings("all")
public void stop() {
if (!ObjectUtils.isEmpty(gatewaySenders)) {
synchronized (gatewaySenders) {
for (GatewaySender gatewaySender : gatewaySenders) {
if (!ObjectUtils.isEmpty(this.gatewaySenders)) {
synchronized (this.gatewaySenders) {
for (GatewaySender gatewaySender : this.gatewaySenders) {
gatewaySender.stop();
}
}
@@ -982,25 +850,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

@@ -47,6 +47,7 @@ import org.springframework.util.StringUtils;
* @see org.springframework.data.gemfire.support.AbstractFactoryBeanSupport
*/
@SuppressWarnings("unused")
// TODO: Rename to ResolvableRegionFactoryBean in SD Lovelace
public abstract class RegionLookupFactoryBean<K, V> extends AbstractFactoryBeanSupport<Region<K, V>>
implements InitializingBean {
@@ -74,15 +75,12 @@ public abstract class RegionLookupFactoryBean<K, V> extends AbstractFactoryBeanS
@SuppressWarnings("all")
public void afterPropertiesSet() throws Exception {
GemFireCache cache = getCache();
GemFireCache cache = requireCache();
Assert.notNull(cache, "Cache is required");
String regionName = resolveRegionName();
Assert.hasText(regionName, "regionName, name or beanName property must be set");
String regionName = requireRegionName();
synchronized (cache) {
setRegion(isLookupEnabled()
? Optional.ofNullable(getParent())
.map(parentRegion -> parentRegion.<K, V>getSubregion(regionName))
@@ -101,6 +99,35 @@ public abstract class RegionLookupFactoryBean<K, V> extends AbstractFactoryBeanS
}
}
private GemFireCache requireCache() {
GemFireCache cache = getCache();
Assert.notNull(cache, "Cache is required");
return cache;
}
private String requireRegionName() {
String regionName = resolveRegionName();
Assert.hasText(regionName, "regionName, name or the beanName property must be set");
return regionName;
}
/**
* Resolves the {@link String name} of the {@link Region}.
*
* @return a {@link String} containing the name of the {@link Region}.
* @see org.apache.geode.cache.Region#getName()
*/
public String resolveRegionName() {
return StringUtils.hasText(this.regionName) ? this.regionName
: (StringUtils.hasText(this.name) ? this.name : getBeanName());
}
/**
* Creates a new {@link Region} with the given {@link String name}.
*
@@ -134,8 +161,8 @@ public abstract class RegionLookupFactoryBean<K, V> extends AbstractFactoryBeanS
try {
region.loadSnapshot(snapshot.getInputStream());
}
catch (Exception e) {
throw newRuntimeException(e, "Failed to load snapshot [%s]", snapshot);
catch (Exception cause) {
throw newRuntimeException(cause, "Failed to load snapshot [%s]", snapshot);
}
});
@@ -177,17 +204,6 @@ public abstract class RegionLookupFactoryBean<K, V> extends AbstractFactoryBeanS
return Optional.ofNullable(getRegion()).map(Region::getClass).orElse((Class) Region.class);
}
/**
* Resolves the {@link String name} of the {@link Region}.
*
* @return a {@link String} containing the name of the {@link Region}.
* @see org.apache.geode.cache.Region#getName()
*/
public String resolveRegionName() {
return (StringUtils.hasText(this.regionName) ? this.regionName
: (StringUtils.hasText(this.name) ? this.name : getBeanName()));
}
/**
* Returns a reference to the {@link GemFireCache} used to create the {@link Region}.
*
@@ -208,17 +224,14 @@ public abstract class RegionLookupFactoryBean<K, V> extends AbstractFactoryBeanS
this.cache = cache;
}
/* (non-Javadoc) */
boolean isLookupEnabled() {
public boolean isLookupEnabled() {
return Boolean.TRUE.equals(getLookupEnabled());
}
/* (non-Javadoc) */
public void setLookupEnabled(Boolean lookupEnabled) {
this.lookupEnabled = lookupEnabled;
}
/* (non-Javadoc) */
public Boolean getLookupEnabled() {
return this.lookupEnabled;
}

View File

@@ -17,6 +17,7 @@ package org.springframework.data.gemfire;
import org.apache.geode.cache.DataPolicy;
import org.apache.geode.cache.RegionFactory;
import org.springframework.data.gemfire.util.RegionUtils;
import org.springframework.util.Assert;
/**
@@ -27,6 +28,7 @@ public class ReplicatedRegionFactoryBean<K, V> extends RegionFactoryBean<K, V> {
@Override
protected void resolveDataPolicy(RegionFactory<K, V> regionFactory, Boolean persistent, DataPolicy dataPolicy) {
if (dataPolicy == null) {
dataPolicy = (isPersistent() ? DataPolicy.PERSISTENT_REPLICATE : DataPolicy.REPLICATE);
}
@@ -41,7 +43,7 @@ public class ReplicatedRegionFactoryBean<K, V> extends RegionFactoryBean<K, V> {
}
// Validate that the data-policy and persistent attributes are compatible when both are specified!
assertDataPolicyAndPersistentAttributesAreCompatible(dataPolicy);
RegionUtils.assertDataPolicyAndPersistentAttributeAreCompatible(dataPolicy, persistent);
regionFactory.setDataPolicy(dataPolicy);
setDataPolicy(dataPolicy);
@@ -49,6 +51,7 @@ public class ReplicatedRegionFactoryBean<K, V> extends RegionFactoryBean<K, V> {
@Override
protected void resolveDataPolicy(RegionFactory<K, V> regionFactory, Boolean persistent, String dataPolicy) {
DataPolicy resolvedDataPolicy = null;
if (dataPolicy != null) {
@@ -58,5 +61,4 @@ public class ReplicatedRegionFactoryBean<K, V> extends RegionFactoryBean<K, V> {
resolveDataPolicy(regionFactory, persistent, resolvedDataPolicy);
}
}

View File

@@ -25,7 +25,6 @@ import java.net.InetSocketAddress;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -37,9 +36,6 @@ import org.apache.geode.cache.client.ClientCacheFactory;
import org.apache.geode.cache.client.Pool;
import org.apache.geode.cache.client.PoolManager;
import org.apache.geode.distributed.DistributedSystem;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ApplicationContextEvent;
@@ -122,21 +118,14 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
clientCacheConfigurer.configure(beanName, bean));
/**
* Post processes this {@link ClientCacheFactoryBean} before cache initialization.
* Applies the composite {@link ClientCacheConfigurer ClientCacheConfigurers}
* to this {@link ClientCacheFactoryBean}.
*
* This is also the point at which any configured {@link ClientCacheConfigurer} beans are called.
*
* @param gemfireProperties {@link Properties} used to configure Pivotal GemFire/Apache Geode.
* @see org.springframework.data.gemfire.config.annotation.ClientCacheConfigurer
* @see java.util.Properties
* @see #getCompositeClientCacheConfigurer()
* @see #applyClientCacheConfigurers(ClientCacheConfigurer...)
*/
@Override
protected void postProcessBeforeCacheInitialization(Properties gemfireProperties) {
applyClientCacheConfigurers();
}
/* (non-Javadoc) */
private void applyClientCacheConfigurers() {
protected void applyCacheConfigurers() {
applyClientCacheConfigurers(getCompositeClientCacheConfigurer());
}
@@ -221,12 +210,12 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
/**
* Constructs a new instance of {@link ClientCacheFactory} initialized with the given Pivotal GemFire/Apache Geode
* {@link Properties} used to create an instance of a {@link ClientCache}.
* {@link Properties} used to construct, configure and initialize an instance of a {@link ClientCache}.
*
* @param gemfireProperties {@link Properties} used by the {@link ClientCacheFactory}
* to configure the {@link ClientCache}.
* @return a new instance of {@link ClientCacheFactory} initialized with the given Pivotal GemFire/Apache Geode
* {@link Properties}.
* @return a new instance of {@link ClientCacheFactory} initialized with
* the given Pivotal GemFire/Apache Geode {@link Properties}.
* @see org.apache.geode.cache.client.ClientCacheFactory
* @see java.util.Properties
*/
@@ -236,17 +225,19 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
}
/**
* Prepares and initializes the {@link ClientCacheFactory} used to create the {@link ClientCache}.
* Configures the {@link ClientCacheFactory} used to create the {@link ClientCache}.
*
* Sets PDX options specified by the user.
*
* Sets Pool options specified by the user.
*
* @param factory {@link ClientCacheFactory} used to create the {@link ClientCache}.
* @return the prepared and initialized {@link ClientCacheFactory}.
* @see #initializePdx(ClientCacheFactory)
* @return the configured {@link ClientCacheFactory}.
* @see #configurePdx(ClientCacheFactory)
*/
@Override
protected Object prepareFactory(Object factory) {
return initializePool(initializePdx((ClientCacheFactory) factory));
protected Object configureFactory(Object factory) {
return configurePool(configurePdx((ClientCacheFactory) factory));
}
/**
@@ -256,7 +247,7 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
* @return the given {@link ClientCacheFactory}
* @see org.apache.geode.cache.client.ClientCacheFactory
*/
ClientCacheFactory initializePdx(ClientCacheFactory clientCacheFactory) {
ClientCacheFactory configurePdx(ClientCacheFactory clientCacheFactory) {
Optional.ofNullable(getPdxSerializer()).ifPresent(clientCacheFactory::setPdxSerializer);
@@ -280,10 +271,10 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
* @see org.apache.geode.cache.client.ClientCacheFactory
* @see org.apache.geode.cache.client.Pool
*/
ClientCacheFactory initializePool(ClientCacheFactory clientCacheFactory) {
ClientCacheFactory configurePool(ClientCacheFactory clientCacheFactory) {
DefaultableDelegatingPoolAdapter pool = DefaultableDelegatingPoolAdapter.from(
DelegatingPoolAdapter.from(resolvePool())).preferDefault();
DefaultableDelegatingPoolAdapter pool =
DefaultableDelegatingPoolAdapter.from(DelegatingPoolAdapter.from(resolvePool())).preferDefault();
clientCacheFactory.setPoolFreeConnectionTimeout(pool.getFreeConnectionTimeout(getFreeConnectionTimeout()));
clientCacheFactory.setPoolIdleTimeout(pool.getIdleTimeout(getIdleTimeout()));
@@ -291,8 +282,8 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
clientCacheFactory.setPoolMaxConnections(pool.getMaxConnections(getMaxConnections()));
clientCacheFactory.setPoolMinConnections(pool.getMinConnections(getMinConnections()));
clientCacheFactory.setPoolMultiuserAuthentication(pool.getMultiuserAuthentication(getMultiUserAuthentication()));
clientCacheFactory.setPoolPRSingleHopEnabled(pool.getPRSingleHopEnabled(getPrSingleHopEnabled()));
clientCacheFactory.setPoolPingInterval(pool.getPingInterval(getPingInterval()));
clientCacheFactory.setPoolPRSingleHopEnabled(pool.getPRSingleHopEnabled(getPrSingleHopEnabled()));
clientCacheFactory.setPoolReadTimeout(pool.getReadTimeout(getReadTimeout()));
clientCacheFactory.setPoolRetryAttempts(pool.getRetryAttempts(getRetryAttempts()));
clientCacheFactory.setPoolServerGroup(pool.getServerGroup(getServerGroup()));
@@ -305,13 +296,14 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
clientCacheFactory.setPoolSubscriptionRedundancy(pool.getSubscriptionRedundancy(getSubscriptionRedundancy()));
clientCacheFactory.setPoolThreadLocalConnections(pool.getThreadLocalConnections(getThreadLocalConnections()));
final AtomicBoolean noServers = new AtomicBoolean(getServers().isEmpty());
AtomicBoolean noServers = new AtomicBoolean(getServers().isEmpty());
boolean hasServers = !noServers.get();
boolean noLocators = getLocators().isEmpty();
boolean hasLocators = !noLocators;
boolean hasServers = !noServers.get();
if (hasServers || noLocators) {
Iterable<InetSocketAddress> servers = pool.getServers(getServers().toInetSocketAddresses());
stream(servers.spliterator(), false).forEach(server -> {
@@ -321,6 +313,7 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
}
if (hasLocators || noServers.get()) {
Iterable<InetSocketAddress> locators = pool.getLocators(getLocators().toInetSocketAddresses());
stream(locators.spliterator(), false).forEach(locator ->
@@ -331,63 +324,58 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
}
/**
* Resolves an appropriate {@link Pool} from the Spring container that will be used to configure
* the {@link ClientCache}.
* Resolves the {@link Pool} used to configure the {@link ClientCache}, {@literal DEFAULT} {@link Pool}.
*
* @return the resolved {@link Pool}.
* @return the resolved {@link Pool} used to configure the {@link ClientCache}, {@literal DEFAULT} {@link Pool}.
* @see org.apache.geode.cache.client.PoolManager#find(String)
* @see org.apache.geode.cache.client.Pool
* @see #getPoolName()
* @see #getPool()
* @see #findPool(String)
* @see #isPoolNameResolvable(String)
*/
Pool resolvePool() {
Pool localPool = getPool();
Pool pool = getPool();
if (localPool == null) {
if (pool == null) {
String poolName = Optional.ofNullable(getPoolName()).filter(StringUtils::hasText)
.orElse(GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME);
String poolName = resolvePoolName();
localPool = findPool(poolName);
pool = findPool(poolName);
if (localPool == null) {
if (pool == null && isPoolNameResolvable(poolName)) {
BeanFactory beanFactory = getBeanFactory();
String dereferencedPoolName = SpringUtils.dereferenceBean(poolName);
if (beanFactory instanceof ListableBeanFactory) {
try {
Map<String, PoolFactoryBean> poolFactoryBeanMap =
((ListableBeanFactory) beanFactory).getBeansOfType(PoolFactoryBean.class, false, false);
PoolFactoryBean poolFactoryBean =
getBeanFactory().getBean(dereferencedPoolName, PoolFactoryBean.class);
String dereferencedPoolName = SpringUtils.dereferenceBean(poolName);
if (poolFactoryBeanMap.containsKey(dereferencedPoolName)) {
return poolFactoryBeanMap.get(dereferencedPoolName).getPool();
}
}
catch (BeansException e) {
logInfo("Unable to resolve bean of type [%1$s] with name [%2$s]",
PoolFactoryBean.class.getName(), poolName);
}
}
return poolFactoryBean.getPool();
}
}
return localPool;
return pool;
}
String resolvePoolName() {
return Optional.ofNullable(getPoolName())
.filter(StringUtils::hasText)
.orElse(GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME);
}
/**
* Attempts to find a {@link Pool} with the given {@link String name}.
*
* @param name {@link String} containing the name of the {@link Pool} to find.
* @return a {@link Pool} instance with the given {@link String name} registered in GemFire/Geode
* or {@literal null} if no {@link Pool} with the given {@link String name} exists.
* @see org.apache.geode.cache.client.PoolManager#find(String)
* @see org.apache.geode.cache.client.Pool
*/
Pool findPool(String name) {
return PoolManager.find(name);
}
private boolean isPoolNameResolvable(String poolName) {
return Optional.ofNullable(poolName)
.filter(getBeanFactory()::containsBean)
.isPresent();
}
/**
* Creates a new {@link ClientCache} instance using the provided factory.
*
@@ -420,7 +408,7 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
this.<ClientCache>fetchCache().readyForEvents();
}
catch (IllegalStateException | CacheClosedException ignore) {
// thrown if clientCache.readyForEvents() is called on a non-durable client
// Thrown when clientCache.readyForEvents() is called on a non-durable client
}
}
}
@@ -449,22 +437,18 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
return Optional.ofNullable(getCache()).map(Object::getClass).orElse((Class) ClientCache.class);
}
/* (non-Javadoc) */
public void addLocators(ConnectionEndpoint... locators) {
this.locators.add(locators);
}
/* (non-Javadoc) */
public void addLocators(Iterable<ConnectionEndpoint> locators) {
this.locators.add(locators);
}
/* (non-Javadoc) */
public void addServers(ConnectionEndpoint... servers) {
this.servers.add(servers);
}
/* (non-Javadoc) */
public void addServers(Iterable<ConnectionEndpoint> servers) {
this.servers.add(servers);
}
@@ -546,40 +530,30 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
return this.durableClientTimeout;
}
/**
* @inheritDoc
*/
@Override
public final void setEnableAutoReconnect(Boolean enableAutoReconnect) {
throw new UnsupportedOperationException("Auto-reconnect does not apply to clients");
}
/**
* @inheritDoc
*/
@Override
public final Boolean getEnableAutoReconnect() {
return Boolean.FALSE;
}
/* (non-Javadoc) */
public void setFreeConnectionTimeout(Integer freeConnectionTimeout) {
this.freeConnectionTimeout = freeConnectionTimeout;
}
/* (non-Javadoc) */
public Integer getFreeConnectionTimeout() {
return freeConnectionTimeout;
return this.freeConnectionTimeout;
}
/* (non-Javadoc) */
public void setIdleTimeout(Long idleTimeout) {
this.idleTimeout = idleTimeout;
}
/* (non-Javadoc) */
public Long getIdleTimeout() {
return idleTimeout;
return this.idleTimeout;
}
/**
@@ -599,7 +573,7 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
* @return a boolean value indicating whether the server should keep the durable client's queues alive.
*/
public Boolean getKeepAlive() {
return keepAlive;
return this.keepAlive;
}
/**
@@ -612,60 +586,49 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
return Boolean.TRUE.equals(getKeepAlive());
}
/* (non-Javadoc) */
public void setLoadConditioningInterval(Integer loadConditioningInterval) {
this.loadConditioningInterval = loadConditioningInterval;
}
/* (non-Javadoc) */
public Integer getLoadConditioningInterval() {
return loadConditioningInterval;
return this.loadConditioningInterval;
}
/* (non-Javadoc) */
public void setLocators(ConnectionEndpoint[] locators) {
setLocators(ConnectionEndpointList.from(locators));
}
/* (non-Javadoc) */
public void setLocators(Iterable<ConnectionEndpoint> locators) {
getLocators().clear();
addLocators(locators);
}
/* (non-Javadoc) */
protected ConnectionEndpointList getLocators() {
return locators;
return this.locators;
}
/* (non-Javadoc) */
public void setMaxConnections(Integer maxConnections) {
this.maxConnections = maxConnections;
}
/* (non-Javadoc) */
public Integer getMaxConnections() {
return maxConnections;
return this.maxConnections;
}
/* (non-Javadoc) */
public void setMinConnections(Integer minConnections) {
this.minConnections = minConnections;
}
/* (non-Javadoc) */
public Integer getMinConnections() {
return minConnections;
return this.minConnections;
}
/* (non-Javadoc) */
public void setMultiUserAuthentication(Boolean multiUserAuthentication) {
this.multiUserAuthentication = multiUserAuthentication;
}
/* (non-Javadoc) */
public Boolean getMultiUserAuthentication() {
return multiUserAuthentication;
return this.multiUserAuthentication;
}
/**
@@ -705,37 +668,31 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
* @return the name of the GemFire {@link Pool} used by this GemFire cache client.
*/
public String getPoolName() {
return poolName;
return this.poolName;
}
/* (non-Javadoc) */
public void setPingInterval(Long pingInterval) {
this.pingInterval = pingInterval;
}
/* (non-Javadoc) */
public Long getPingInterval() {
return pingInterval;
return this.pingInterval;
}
/* (non-Javadoc) */
public void setPrSingleHopEnabled(Boolean prSingleHopEnabled) {
this.prSingleHopEnabled = prSingleHopEnabled;
}
/* (non-Javadoc) */
public Boolean getPrSingleHopEnabled() {
return prSingleHopEnabled;
return this.prSingleHopEnabled;
}
/* (non-Javadoc) */
public void setReadTimeout(Integer readTimeout) {
this.readTimeout = readTimeout;
}
/* (non-Javadoc) */
public Integer getReadTimeout() {
return readTimeout;
return this.readTimeout;
}
/**
@@ -756,7 +713,7 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
* @return a boolean value indicating the state of the 'readyForEvents' property.
*/
public Boolean getReadyForEvents(){
return readyForEvents;
return this.readyForEvents;
}
/**
@@ -784,133 +741,104 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
}
}
/* (non-Javadoc) */
public void setRetryAttempts(Integer retryAttempts) {
this.retryAttempts = retryAttempts;
}
/* (non-Javadoc) */
public Integer getRetryAttempts() {
return retryAttempts;
return this.retryAttempts;
}
/* (non-Javadoc) */
public void setServerGroup(String serverGroup) {
this.serverGroup = serverGroup;
}
/* (non-Javadoc) */
public String getServerGroup() {
return serverGroup;
return this.serverGroup;
}
/* (non-Javadoc) */
public void setServers(ConnectionEndpoint[] servers) {
setServers(ConnectionEndpointList.from(servers));
}
/* (non-Javadoc) */
public void setServers(Iterable<ConnectionEndpoint> servers) {
getServers().clear();
addServers(servers);
}
/* (non-Javadoc) */
protected ConnectionEndpointList getServers() {
return servers;
return this.servers;
}
/* (non-Javadoc) */
public void setSocketBufferSize(Integer socketBufferSize) {
this.socketBufferSize = socketBufferSize;
}
/* (non-Javadoc) */
public Integer getSocketBufferSize() {
return socketBufferSize;
return this.socketBufferSize;
}
/* (non-Javadoc) */
public void setSocketConnectTimeout(Integer socketConnectTimeout) {
this.socketConnectTimeout = socketConnectTimeout;
}
/* (non-Javadoc) */
public Integer getSocketConnectTimeout() {
return this.socketConnectTimeout;
}
/* (non-Javadoc) */
public void setStatisticsInterval(Integer statisticsInterval) {
this.statisticsInterval = statisticsInterval;
}
/* (non-Javadoc) */
public Integer getStatisticsInterval() {
return statisticsInterval;
return this.statisticsInterval;
}
/* (non-Javadoc) */
public void setSubscriptionAckInterval(Integer subscriptionAckInterval) {
this.subscriptionAckInterval = subscriptionAckInterval;
}
/* (non-Javadoc) */
public Integer getSubscriptionAckInterval() {
return subscriptionAckInterval;
return this.subscriptionAckInterval;
}
/* (non-Javadoc) */
public void setSubscriptionEnabled(Boolean subscriptionEnabled) {
this.subscriptionEnabled = subscriptionEnabled;
}
/* (non-Javadoc) */
public Boolean getSubscriptionEnabled() {
return subscriptionEnabled;
return this.subscriptionEnabled;
}
/* (non-Javadoc) */
public void setSubscriptionMessageTrackingTimeout(Integer subscriptionMessageTrackingTimeout) {
this.subscriptionMessageTrackingTimeout = subscriptionMessageTrackingTimeout;
}
/* (non-Javadoc) */
public Integer getSubscriptionMessageTrackingTimeout() {
return subscriptionMessageTrackingTimeout;
return this.subscriptionMessageTrackingTimeout;
}
/* (non-Javadoc) */
public void setSubscriptionRedundancy(Integer subscriptionRedundancy) {
this.subscriptionRedundancy = subscriptionRedundancy;
}
/* (non-Javadoc) */
public Integer getSubscriptionRedundancy() {
return subscriptionRedundancy;
return this.subscriptionRedundancy;
}
/* (non-Javadoc) */
public void setThreadLocalConnections(Boolean threadLocalConnections) {
this.threadLocalConnections = threadLocalConnections;
}
/* (non-Javadoc) */
public Boolean getThreadLocalConnections() {
return threadLocalConnections;
return this.threadLocalConnections;
}
/**
* @inheritDoc
*/
@Override
public final void setUseClusterConfiguration(Boolean useClusterConfiguration) {
throw new UnsupportedOperationException("Cluster-based Configuration is not applicable for clients");
}
/**
* @inheritDoc
*/
@Override
public final Boolean getUseClusterConfiguration() {
return Boolean.FALSE;

View File

@@ -19,20 +19,20 @@ package org.springframework.data.gemfire.client;
import static java.util.Arrays.stream;
import static org.springframework.data.gemfire.util.ArrayUtils.nullSafeArray;
import static org.springframework.data.gemfire.util.CollectionUtils.nullSafeCollection;
import static org.springframework.data.gemfire.util.CollectionUtils.nullSafeIterable;
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalArgumentException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.StreamSupport;
import java.util.concurrent.atomic.AtomicReference;
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;
@@ -42,14 +42,16 @@ import org.apache.geode.cache.client.ClientRegionShortcut;
import org.apache.geode.cache.client.Pool;
import org.apache.geode.cache.client.PoolManager;
import org.apache.geode.compression.Compressor;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.data.gemfire.ConfigurableRegionFactoryBean;
import org.springframework.data.gemfire.DataPolicyConverter;
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.util.RegionUtils;
import org.springframework.data.gemfire.util.SpringUtils;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -71,11 +73,11 @@ import org.springframework.util.StringUtils;
* @see org.springframework.beans.factory.DisposableBean
* @see org.springframework.beans.factory.FactoryBean
* @see org.springframework.data.gemfire.DataPolicyConverter
* @see org.springframework.data.gemfire.RegionLookupFactoryBean
* @see RegionLookupFactoryBean
* @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 ConfigurableRegionFactoryBean<K, V> implements DisposableBean {
public static final String DEFAULT_POOL_NAME = "DEFAULT";
public static final String GEMFIRE_POOL_NAME = GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME;
@@ -83,7 +85,11 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
private boolean close = false;
private boolean destroy = false;
private Boolean cloningEnabled;
private Boolean concurrencyChecksEnabled;
private Boolean diskSynchronous;
private Boolean persistent;
private Boolean statisticsEnabled;
private CacheListener<K, V>[] cacheListeners;
@@ -98,12 +104,25 @@ 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 Integer concurrencyLevel;
private Integer initialCapacity;
private Interest<K>[] interests;
private Float loadFactor;
private List<RegionConfigurer> regionConfigurers = Collections.emptyList();
private RegionAttributes<K, V> attributes;
@@ -126,6 +145,8 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
* @param gemfireCache reference to the {@link GemFireCache}.
* @param regionName {@link String name} of the new {@link Region}.
* @return a new {@link Region} with the given {@link String name}.
* @see #createClientRegionFactory(ClientCache, ClientRegionShortcut)
* @see #newRegion(ClientRegionFactory, Region, String)
* @see org.apache.geode.cache.GemFireCache
* @see org.apache.geode.cache.Region
*/
@@ -139,109 +160,37 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
ClientRegionFactory<K, V> clientRegionFactory =
postProcess(configure(createClientRegionFactory(clientCache, resolveClientRegionShortcut())));
@SuppressWarnings("all")
Region<K, V> region = newRegion(clientRegionFactory, getParent(), regionName);
return region;
}
/* (non-Javadoc) */
private void applyRegionConfigurers(String regionName) {
applyRegionConfigurers(regionName, getCompositeRegionConfigurer());
return newRegion(clientRegionFactory, getParent(), regionName);
}
/**
* Null-safe operation to apply the given array of {@link RegionConfigurer RegionConfigurers}
* to this {@link ClientRegionFactoryBean}.
* Constructs a new {@link Region} using the provided {@link ClientRegionFactory} as either
* a {@link Region root Region} or a {@link Region sub-Region} if {@link Region parent}
* is not {@literal null}.
*
* @param regionName {@link String} containing the name of the {@link Region}.
* @param regionConfigurers array of {@link RegionConfigurer RegionConfigurers} applied
* to this {@link ClientRegionFactoryBean}.
* @see org.springframework.data.gemfire.config.annotation.RegionConfigurer
* @see #applyRegionConfigurers(String, Iterable)
* @param clientRegionFactory {@link ClientRegionFactory} containing the configuration
* for the new {@link Region}.
* @param parent {@link Region} designated as the parent of the new {@link Region}
* if the new {@link Region} is a {@link Region sub-Region}.
* @param regionName {@link String name} of the new {@link Region}.
* @return the new {@link Region} initialized with the given {@link String name}.
*/
protected void applyRegionConfigurers(String regionName, RegionConfigurer... regionConfigurers) {
applyRegionConfigurers(regionName, Arrays.asList(nullSafeArray(regionConfigurers, RegionConfigurer.class)));
}
/**
* Null-safe operation to apply the given {@link Iterable} of {@link RegionConfigurer RegionConfigurers}
* to this {@link ClientRegionFactoryBean}.
*
* @param regionName {@link String} containing the name of the {@link Region}.
* @param regionConfigurers {@link Iterable} of {@link RegionConfigurer RegionConfigurers} applied
* to this {@link ClientRegionFactoryBean}.
* @see org.springframework.data.gemfire.config.annotation.RegionConfigurer
*/
protected void applyRegionConfigurers(String regionName, Iterable<RegionConfigurer> regionConfigurers) {
StreamSupport.stream(nullSafeIterable(regionConfigurers).spliterator(), false)
.forEach(regionConfigurer -> regionConfigurer.configure(regionName, this));
}
/**
* Assert the settings for {@link ClientRegionShortcut} and the {@literal persistent} attribute
* in &lt;gfe:*-region&gt; elements are compatible.
*
* @param resolvedShortcut {@link ClientRegionShortcut} resolved from the SDG XML namespace.
* @see org.springframework.data.gemfire.client.ClientRegionShortcutWrapper
* @see org.apache.geode.cache.client.ClientRegionShortcut
* @see #isNotPersistent()
* @see #isPersistent()
*/
private void assertClientRegionShortcutAndPersistentAttributeAreCompatible(ClientRegionShortcut resolvedShortcut) {
final boolean persistentNotSpecified = (this.persistent == null);
if (ClientRegionShortcutWrapper.valueOf(resolvedShortcut).isPersistent()) {
Assert.isTrue(persistentNotSpecified || isPersistent(),
String.format("Client Region Shortcut [%s] is not valid when persistent is false", resolvedShortcut));
}
else {
Assert.isTrue(persistentNotSpecified || isNotPersistent(),
String.format("Client Region Shortcut [%s] is not valid when persistent is true", resolvedShortcut));
}
}
/**
* Assert the settings for {@link DataPolicy} and the persistent attribute
* in &lt;gfe:*-region&gt; elements are compatible.
*
* @param resolvedDataPolicy {@link DataPolicy} resolved from the SDG XML namespace.
* @see org.apache.geode.cache.DataPolicy
* @see #isNotPersistent()
* @see #isPersistent()
*/
private void assertDataPolicyAndPersistentAttributeAreCompatible(DataPolicy resolvedDataPolicy) {
if (resolvedDataPolicy.withPersistence()) {
Assert.isTrue(isPersistentUnspecified() || isPersistent(),
String.format("Data Policy [%s] is not valid when persistent is false", resolvedDataPolicy));
}
else {
Assert.isTrue(isPersistentUnspecified() || isNotPersistent(),
String.format("Data Policy [%s] is not valid when persistent is true", resolvedDataPolicy));
}
}
/* (non-Javadoc) */
private Region<K, V> newRegion(ClientRegionFactory<K, V> clientRegionFactory,
Region<?, ?> parentRegion, String regionName) {
Region<?, ?> parent, String regionName) {
return Optional.ofNullable(parentRegion)
.map(parent -> {
logInfo("Creating client Subregion [%1$s] with parent Region [%2$s]",
regionName, parent.getName());
if (parent != null) {
return clientRegionFactory.<K, V>createSubregion(parent, regionName);
})
.orElseGet(() -> {
logInfo("Created client Region [%s]", regionName);
logInfo("Creating client sub-Region [%1$s] with parent Region [%2$s]",
regionName, parent.getName());
return clientRegionFactory.create(regionName);
});
return clientRegionFactory.<K, V>createSubregion(parent, regionName);
}
else {
logInfo("Creating client Region [%s]", regionName);
return clientRegionFactory.create(regionName);
}
}
/* (non-Javadoc) */
private ClientCache resolveCache(GemFireCache gemfireCache) {
return Optional.ofNullable(gemfireCache)
@@ -251,9 +200,11 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
}
/**
* Resolves the {@link ClientRegionShortcut} used to configure the {@link DataPolicy} of the client {@link Region}.
* Resolves the {@link ClientRegionShortcut} used to configure the {@link DataPolicy}
* for the {@link Region client Region}.
*
* @return a {@link ClientRegionShortcut} used to configure the {@link DataPolicy} of the client {@link Region}.
* @return a {@link ClientRegionShortcut} used to configure the {@link DataPolicy}
* for the {@link Region client Region}.
* @see org.apache.geode.cache.client.ClientRegionShortcut
* @see org.apache.geode.cache.DataPolicy
*/
@@ -267,7 +218,7 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
if (dataPolicy != null) {
assertDataPolicyAndPersistentAttributeAreCompatible(dataPolicy);
RegionUtils.assertDataPolicyAndPersistentAttributeAreCompatible(dataPolicy, this.persistent);
if (DataPolicy.EMPTY.equals(dataPolicy)) {
resolvedShortcut = ClientRegionShortcut.PROXY;
@@ -279,57 +230,48 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
resolvedShortcut = ClientRegionShortcut.LOCAL_PERSISTENT;
}
else {
// NOTE the DataPolicy validation is based on the ClientRegionShortcut initialization logic
// in org.apache.geode.internal.cache.GemFireCacheImpl.initializeClientRegionShortcuts
// NOTE: DataPolicy validation is based on the ClientRegionShortcut initialization logic
// in org.apache.geode.internal.cache.GemFireCacheImpl.initializeClientRegionShortcuts.
throw newIllegalArgumentException("Data Policy [%s] is not valid for a client Region", dataPolicy);
}
}
else {
resolvedShortcut = (isPersistent() ? ClientRegionShortcut.LOCAL_PERSISTENT : ClientRegionShortcut.LOCAL);
resolvedShortcut = isPersistent() ? ClientRegionShortcut.LOCAL_PERSISTENT : ClientRegionShortcut.LOCAL;
}
}
// NOTE the ClientRegionShortcut and Persistent attribute will be compatible
// if the shortcut was derived from the Data Policy.
assertClientRegionShortcutAndPersistentAttributeAreCompatible(resolvedShortcut);
// NOTE: The ClientRegionShortcut and Persistent attribute will be compatible
// if the shortcut was derived from the DataPolicy.
RegionUtils.assertClientRegionShortcutAndPersistentAttributeAreCompatible(resolvedShortcut, this.persistent);
return resolvedShortcut;
}
/* (non-Javadoc) */
private String resolvePoolName() {
private String resolvePoolName(String factoryPoolName, String attributesPoolName) {
return getPoolName()
String resolvedPoolName = StringUtils.hasText(factoryPoolName) ? factoryPoolName : attributesPoolName;
return Optional.ofNullable(resolvedPoolName)
.filter(StringUtils::hasText)
.filter(this::isNotDefaultPool)
.filter(this::isPoolResolvable)
.filter(GemfireUtils::isNotDefaultPool)
.map(it -> {
Assert.isTrue(eagerlyInitializePool(it),
String.format("[%s] is not resolvable as a Pool in the application context", it));
return it;
})
.orElse(null);
}
/* (non-Javadoc) */
boolean isPoolResolvable(String poolName) {
return getBeanFactory().containsBean(poolName) || (PoolManager.find(poolName) != null);
}
@SuppressWarnings("all")
private boolean eagerlyInitializePool(String poolName) {
/* (non-Javadoc) */
boolean isNotDefaultPool(String poolName) {
return !DEFAULT_POOL_NAME.equals(poolName);
}
/* (non-Javadoc) */
private String eagerlyInitializePool(String poolName) {
try {
if (getBeanFactory().isTypeMatch(poolName, Pool.class)) {
logDebug("Found bean definition for Pool [%s]; Eagerly initializing...", poolName);
getBeanFactory().getBean(poolName, Pool.class);
}
}
catch (BeansException ignore) {
getLog().warn(ignore.getMessage(), ignore.getCause());
}
return poolName;
return Optional.ofNullable(PoolManager.find(poolName))
.map(it -> true)
.orElseGet(() ->
SpringUtils.safeGetValue(() ->
getBeanFactory().getBean(poolName, Pool.class) != null, false));
}
/**
@@ -337,81 +279,93 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
* and {@link ClientRegionShortcut}.
*
* @param clientCache reference to the {@link ClientCache}.
* @param shortcut {@link ClientRegionShortcut} used to specify the client {@link Region} {@link DataPolicy}.
* @param clientRegionShortcut {@link ClientRegionShortcut} used to configure
* the {@link Region client Region} {@link DataPolicy}.
* @return a new instance of {@link ClientRegionFactory}.
* @see org.apache.geode.cache.client.ClientCache#createClientRegionFactory(ClientRegionShortcut)
* @see org.apache.geode.cache.client.ClientRegionShortcut
* @see org.apache.geode.cache.client.ClientRegionFactory
*/
protected ClientRegionFactory<K, V> createClientRegionFactory(ClientCache clientCache,
ClientRegionShortcut shortcut) {
ClientRegionShortcut clientRegionShortcut) {
return clientCache.createClientRegionFactory(shortcut);
return clientCache.createClientRegionFactory(clientRegionShortcut);
}
/**
* Configures the given {@link ClientRegionFactoryBean} from the configuration settings
* of this {@link ClientRegionFactoryBean}.
* of this {@link ClientRegionFactoryBean} and any {@link RegionAttributes}.
*
* @param clientRegionFactory {@link ClientRegionFactory} to configure.
* @return the given {@link ClientRegionFactory}.
* @return the configured {@link ClientRegionFactory}.
* @see org.apache.geode.cache.client.ClientRegionFactory
*/
protected ClientRegionFactory<K, V> configure(ClientRegionFactory<K, V> clientRegionFactory) {
Optional.ofNullable(this.attributes).ifPresent(attributes -> {
stream(nullSafeArray(attributes.getCacheListeners(), CacheListener.class))
.forEach(clientRegionFactory::addCacheListener);
clientRegionFactory.setCloningEnabled(attributes.getCloningEnabled());
clientRegionFactory.setCompressor(attributes.getCompressor());
clientRegionFactory.setConcurrencyChecksEnabled(attributes.getConcurrencyChecksEnabled());
clientRegionFactory.setConcurrencyLevel(attributes.getConcurrencyLevel());
clientRegionFactory.setCustomEntryIdleTimeout(attributes.getCustomEntryIdleTimeout());
clientRegionFactory.setCustomEntryTimeToLive(attributes.getCustomEntryTimeToLive());
clientRegionFactory.setDiskStoreName(attributes.getDiskStoreName());
clientRegionFactory.setDiskSynchronous(attributes.isDiskSynchronous());
clientRegionFactory.setEntryIdleTimeout(attributes.getEntryIdleTimeout());
clientRegionFactory.setEntryTimeToLive(attributes.getEntryTimeToLive());
clientRegionFactory.setEvictionAttributes(attributes.getEvictionAttributes());
clientRegionFactory.setInitialCapacity(attributes.getInitialCapacity());
clientRegionFactory.setKeyConstraint(attributes.getKeyConstraint());
clientRegionFactory.setLoadFactor(attributes.getLoadFactor());
clientRegionFactory.setRegionIdleTimeout(attributes.getRegionIdleTimeout());
clientRegionFactory.setRegionTimeToLive(attributes.getRegionTimeToLive());
clientRegionFactory.setStatisticsEnabled(attributes.getStatisticsEnabled());
clientRegionFactory.setValueConstraint(attributes.getValueConstraint());
Optional.ofNullable(attributes.getPoolName())
.filter(StringUtils::hasText)
.filter(this::isNotDefaultPool)
.filter(this::isPoolResolvable)
.map(this::eagerlyInitializePool)
.ifPresent(clientRegionFactory::setPoolName);
});
Optional<String> regionAttributesPoolName = configureWithRegionAttributes(clientRegionFactory);
stream(nullSafeArray(this.cacheListeners, CacheListener.class)).forEach(clientRegionFactory::addCacheListener);
Optional.ofNullable(this.cloningEnabled).ifPresent(clientRegionFactory::setCloningEnabled);
Optional.ofNullable(this.compressor).ifPresent(clientRegionFactory::setCompressor);
Optional.ofNullable(this.diskStoreName).filter(StringUtils::hasText)
.ifPresent(clientRegionFactory::setDiskStoreName);
Optional.ofNullable(this.concurrencyChecksEnabled).ifPresent(clientRegionFactory::setConcurrencyChecksEnabled);
Optional.ofNullable(this.concurrencyLevel).ifPresent(clientRegionFactory::setConcurrencyLevel);
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.diskSynchronous).ifPresent(clientRegionFactory::setDiskSynchronous);
Optional.ofNullable(this.entryIdleTimeout).ifPresent(clientRegionFactory::setEntryIdleTimeout);
Optional.ofNullable(this.entryTimeToLive).ifPresent(clientRegionFactory::setEntryTimeToLive);
Optional.ofNullable(this.evictionAttributes).ifPresent(clientRegionFactory::setEvictionAttributes);
Optional.ofNullable(this.initialCapacity).ifPresent(clientRegionFactory::setInitialCapacity);
Optional.ofNullable(this.keyConstraint).ifPresent(clientRegionFactory::setKeyConstraint);
Optional.ofNullable(this.loadFactor).ifPresent(clientRegionFactory::setLoadFactor);
Optional.ofNullable(resolvePoolName())
.map(this::eagerlyInitializePool)
Optional.ofNullable(resolvePoolName(getPoolName().orElse(null), regionAttributesPoolName.orElse(null)))
.ifPresent(clientRegionFactory::setPoolName);
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;
}
private Optional<String> configureWithRegionAttributes(ClientRegionFactory<K, V> clientRegionFactory) {
AtomicReference<String> regionAttributesPoolName = new AtomicReference<>(null);
Optional.ofNullable(getAttributes()).ifPresent(regionAttributes -> {
regionAttributesPoolName.set(regionAttributes.getPoolName());
stream(nullSafeArray(regionAttributes.getCacheListeners(), CacheListener.class))
.forEach(clientRegionFactory::addCacheListener);
clientRegionFactory.setCloningEnabled(regionAttributes.getCloningEnabled());
clientRegionFactory.setCompressor(regionAttributes.getCompressor());
clientRegionFactory.setConcurrencyChecksEnabled(regionAttributes.getConcurrencyChecksEnabled());
clientRegionFactory.setConcurrencyLevel(regionAttributes.getConcurrencyLevel());
clientRegionFactory.setCustomEntryIdleTimeout(regionAttributes.getCustomEntryIdleTimeout());
clientRegionFactory.setCustomEntryTimeToLive(regionAttributes.getCustomEntryTimeToLive());
clientRegionFactory.setDiskStoreName(regionAttributes.getDiskStoreName());
clientRegionFactory.setDiskSynchronous(regionAttributes.isDiskSynchronous());
clientRegionFactory.setEntryIdleTimeout(regionAttributes.getEntryIdleTimeout());
clientRegionFactory.setEntryTimeToLive(regionAttributes.getEntryTimeToLive());
clientRegionFactory.setEvictionAttributes(regionAttributes.getEvictionAttributes());
clientRegionFactory.setInitialCapacity(regionAttributes.getInitialCapacity());
clientRegionFactory.setKeyConstraint(regionAttributes.getKeyConstraint());
clientRegionFactory.setLoadFactor(regionAttributes.getLoadFactor());
clientRegionFactory.setRegionIdleTimeout(regionAttributes.getRegionIdleTimeout());
clientRegionFactory.setRegionTimeToLive(regionAttributes.getRegionTimeToLive());
clientRegionFactory.setStatisticsEnabled(regionAttributes.getStatisticsEnabled());
clientRegionFactory.setValueConstraint(regionAttributes.getValueConstraint());
});
return Optional.ofNullable(regionAttributesPoolName.get()).filter(StringUtils::hasText);
}
/**
* Post-process the given {@link ClientRegionFactory} setup by this {@link ClientRegionFactoryBean}.
*
@@ -445,7 +399,6 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
return region;
}
/* (non-Javadoc) */
@SuppressWarnings("unchecked")
private Region<K, V> registerInterests(Region<K, V> region) {
@@ -459,6 +412,7 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
region.registerInterest(((Interest<K>) interest).getKey(), interest.getPolicy(),
interest.isDurable(), interest.isReceiveValues());
}
});
return region;
@@ -488,18 +442,8 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
if (isDestroy()) {
region.destroyRegion();
}
});
}
/**
* Returns a reference to the Composite {@link RegionConfigurer} used to apply additional configuration
* to this {@link ClientRegionFactoryBean} on Spring container initialization.
*
* @return the Composite {@link RegionConfigurer}.
* @see org.springframework.data.gemfire.config.annotation.RegionConfigurer
*/
protected RegionConfigurer getCompositeRegionConfigurer() {
return this.compositeRegionConfigurer;
});
}
/**
@@ -516,6 +460,17 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
this.attributes = attributes;
}
/**
* Gets the {@link RegionAttributes} used to configure the {@link Region client Region}
* created by this {@link ClientRegionFactoryBean}.
*
* @return the {@link RegionAttributes} used to configure the {@link Region client Region}.
* @see org.apache.geode.cache.RegionAttributes
*/
protected RegionAttributes<K, V> getAttributes() {
return this.attributes;
}
/**
* Sets the cache listeners used for the region used by this factory. Used
* only when a new region is created.Overrides the settings specified
@@ -547,7 +502,10 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
this.cacheWriter = cacheWriter;
}
/* (non-Javadoc) */
public void setCloningEnabled(Boolean cloningEnabled) {
this.cloningEnabled = cloningEnabled;
}
final boolean isClose() {
return this.close;
}
@@ -575,6 +533,22 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
this.compressor = compressor;
}
public void setConcurrencyChecksEnabled(Boolean concurrencyChecksEnabled) {
this.concurrencyChecksEnabled = concurrencyChecksEnabled;
}
public void setConcurrencyLevel(Integer concurrencyLevel) {
this.concurrencyLevel = concurrencyLevel;
}
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.
*
@@ -600,7 +574,6 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
setDataPolicy(resolvedDataPolicy);
}
/* (non-Javadoc) */
final boolean isDestroy() {
return this.destroy;
}
@@ -615,7 +588,7 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
*/
public void setDestroy(boolean destroy) {
this.destroy = destroy;
this.close = (this.close && !destroy); // retain previous value iff destroy is false;
this.close = this.close && !destroy; // retain previous value iff destroy is false;
}
/**
@@ -627,10 +600,26 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
this.diskStoreName = diskStoreName;
}
public void setDiskSynchronous(Boolean diskSynchronous) {
this.diskSynchronous = diskSynchronous;
}
public void setEntryIdleTimeout(ExpirationAttributes entryIdleTimeout) {
this.entryIdleTimeout = entryIdleTimeout;
}
public void setEntryTimeToLive(ExpirationAttributes entryTimeToLive) {
this.entryTimeToLive = entryTimeToLive;
}
public void setEvictionAttributes(EvictionAttributes evictionAttributes) {
this.evictionAttributes = evictionAttributes;
}
public void setInitialCapacity(Integer initialCapacity) {
this.initialCapacity = initialCapacity;
}
/**
* Set the interests for this client region. Both key and regex interest are
* supported.
@@ -641,17 +630,22 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
this.interests = interests;
}
/* (non-Javadoc) */
Interest<K>[] getInterests() {
return this.interests;
}
/**
* Sets a {@link Class type} constraint on this {@link Region client Region's} keys.
*
* @param keyConstraint {@link Class type} of this {@link Region client Region's} keys.
* @see java.lang.Class
*/
public void setKeyConstraint(Class<K> keyConstraint) {
this.keyConstraint = keyConstraint;
}
protected boolean isPersistentUnspecified() {
return (persistent == null);
public void setLoadFactor(Float loadFactor) {
this.loadFactor = loadFactor;
}
protected boolean isPersistent() {
@@ -662,14 +656,20 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
return Boolean.FALSE.equals(persistent);
}
public void setPersistent(final boolean persistent) {
/**
* Configures whether this {@link Region client Region} is persistent, i.e. stores data to disk.
*
* @param persistent boolean value used to enable disk persistence.
*/
public void setPersistent(boolean persistent) {
this.persistent = persistent;
}
/**
* Sets the {@link Pool} used by this client {@link Region}.
* Configures the {@link Pool} used by this {@link Region client Region}.
*
* @param pool client {@link Pool} to be used by this client {@link Region}.
* @param pool {@link Pool} used by this {@link Region client Region}
* to send/receive data to/from the server.
* @see org.apache.geode.cache.client.Pool
* @see #setPoolName(String)
*/
@@ -678,9 +678,10 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
}
/**
* Sets the {@link String name} of the {@link Pool} used by this client {@link Region}.
* Configures the {@link String name} of the {@link Pool} used by this {@link Region client Region}.
*
* @param poolName {@link String} containing the name of the client {@link Pool} used by this client {@link Region}.
* @param poolName {@link String} containing the name of the client {@link Pool}
* used by this {@link Region client Region}.
* @see #getPoolName()
* @see #setPool(Pool)
*/
@@ -689,55 +690,44 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
}
/**
* Returns the {@link String name} of the configured {@link Pool} to use with this client {@link Region}.
* Returns the {@link String name} of the configured {@link Pool} to use with this {@link Region client Region}.
*
* @return the {@link Optional} {@link String name} of the configured {@link Pool} to use
* with this client {@link Region}.
* with this {@link Region client Region}.
* @see #setPoolName(String)
*/
public Optional<String> getPoolName() {
return Optional.ofNullable(this.poolName);
}
/**
* Null-safe operation to set an array of {@link RegionConfigurer RegionConfigurers} used to apply
* additional configuration to this {@link ClientRegionFactoryBean} when using Annotation-based configuration.
*
* @param regionConfigurers array of {@link RegionConfigurer RegionConfigurers} used to apply
* additional configuration to this {@link ClientRegionFactoryBean}.
* @see org.springframework.data.gemfire.config.annotation.RegionConfigurer
* @see #setRegionConfigurers(List)
*/
public void setRegionConfigurers(RegionConfigurer... regionConfigurers) {
setRegionConfigurers(Arrays.asList(nullSafeArray(regionConfigurers, RegionConfigurer.class)));
public void setRegionIdleTimeout(ExpirationAttributes regionIdleTimeout) {
this.regionIdleTimeout = regionIdleTimeout;
}
public void setRegionTimeToLive(ExpirationAttributes regionTimeToLive) {
this.regionTimeToLive = regionTimeToLive;
}
/**
* Null-safe operation to set an {@link Iterable} of {@link RegionConfigurer RegionConfigurers} used to apply
* additional configuration to this {@link ClientRegionFactoryBean} when using Annotation-based configuration.
* Initializes the {@link DataPolicy} of the {@link Region client Region}
* using the given {@link ClientRegionShortcut}.
*
* @param regionConfigurers {@link Iterable} of {@link RegionConfigurer RegionConfigurers} used to apply
* additional configuration to this {@link ClientRegionFactoryBean}.
* @see org.springframework.data.gemfire.config.annotation.RegionConfigurer
*/
public void setRegionConfigurers(List<RegionConfigurer> regionConfigurers) {
this.regionConfigurers = Optional.ofNullable(regionConfigurers).orElseGet(Collections::emptyList);
}
/**
* Initializes the client {@link Region} using the given {@link ClientRegionShortcut}.
*
* @param shortcut {@link ClientRegionShortcut} used to initialize this client {@link Region}.
* @param shortcut {@link ClientRegionShortcut} used to initialize the {@link DataPolicy}
* of this {@link Region client Region}.
* @see org.apache.geode.cache.client.ClientRegionShortcut
*/
public void setShortcut(ClientRegionShortcut shortcut) {
this.shortcut = shortcut;
}
public void setStatisticsEnabled(Boolean statisticsEnabled) {
this.statisticsEnabled = statisticsEnabled;
}
/**
* Sets a {@link Class type} constraint on this {@link Region Region's} values.
* Sets a {@link Class type} constraint on this {@link Region client Region's} values.
*
* @param valueConstraint {@link Class type} of this client {@link Region Region's} values.
* @param valueConstraint {@link Class type} of this {@link Region client Region's} values.
* @see java.lang.Class
*/
public void setValueConstraint(Class<V> valueConstraint) {

View File

@@ -16,15 +16,14 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.client.ClientCache;
import org.apache.geode.cache.client.ClientRegionFactory;
import org.apache.geode.cache.client.ClientRegionShortcut;
import org.apache.geode.cache.execute.Function;
import org.apache.geode.management.internal.cli.domain.RegionInformation;
import org.apache.geode.management.internal.cli.functions.GetRegionsFunction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
@@ -52,7 +51,7 @@ import org.springframework.util.ObjectUtils;
*/
public class GemfireDataSourcePostProcessor implements BeanFactoryPostProcessor {
protected final Log logger = LogFactory.getLog(getClass());
protected final Logger logger = LoggerFactory.getLogger(getClass());
private final ClientCache clientCache;
@@ -64,7 +63,10 @@ public class GemfireDataSourcePostProcessor implements BeanFactoryPostProcessor
* @param clientCache the GemFire ClientCache instance.
* @see org.apache.geode.cache.client.ClientCache
*/
public GemfireDataSourcePostProcessor(final ClientCache clientCache) {
public GemfireDataSourcePostProcessor(ClientCache clientCache) {
Assert.notNull(clientCache, "ClientCache must not be null");
this.clientCache = clientCache;
}
@@ -77,21 +79,24 @@ public class GemfireDataSourcePostProcessor implements BeanFactoryPostProcessor
createClientRegionProxies(beanFactory, regionNames());
}
/* (non-Javadoc) */
// TODO remove this logic and delegate to o.s.d.g.config.remote.GemfireAdminOperations
// TODO: remove this logic and delegate to o.s.d.g.config.remote.GemfireAdminOperations
Iterable<String> regionNames() {
try {
return execute(new ListRegionsOnServerFunction());
}
catch (Exception ignore) {
try {
Object results = execute(new GetRegionsFunction());
List<String> regionNames = Collections.emptyList();
if (containsRegionInformation(results)) {
Object[] resultsArray = (Object[]) results;
regionNames = new ArrayList<String>(resultsArray.length);
regionNames = new ArrayList<>(resultsArray.length);
for (Object result : resultsArray) {
regionNames.add(((RegionInformation) result).getName());
@@ -100,39 +105,42 @@ public class GemfireDataSourcePostProcessor implements BeanFactoryPostProcessor
return regionNames;
}
catch (Exception e) {
log("Failed to determine the Regions available on the Server: %n%1$s", e);
catch (Exception cause) {
log("Failed to determine the Regions available on the Server: %n%1$s", cause);
return Collections.emptyList();
}
}
}
/* (non-Javadoc) */
@SuppressWarnings("unchecked")
<T> T execute(Function gemfireFunction, Object... arguments) {
return new GemfireOnServersFunctionTemplate(clientCache).executeAndExtract(gemfireFunction, arguments);
return new GemfireOnServersFunctionTemplate(this.clientCache).executeAndExtract(gemfireFunction, arguments);
}
/* (non-Javadoc) */
boolean containsRegionInformation(Object results) {
return (results instanceof Object[] && ((Object[]) results).length > 0
&& ((Object[]) results)[0] instanceof RegionInformation);
return results instanceof Object[] && ((Object[]) results).length > 0
&& ((Object[]) results)[0] instanceof RegionInformation;
}
/* (non-Javadoc) */
void createClientRegionProxies(ConfigurableListableBeanFactory beanFactory, Iterable<String> regionNames) {
if (regionNames.iterator().hasNext()) {
ClientRegionFactory<?, ?> clientRegionFactory = clientCache.createClientRegionFactory(ClientRegionShortcut.PROXY);
ClientRegionFactory<?, ?> clientRegionFactory =
this.clientCache.createClientRegionFactory(ClientRegionShortcut.PROXY);
for (String regionName : regionNames) {
boolean createRegion = true;
if (beanFactory.containsBean(regionName)) {
Object existingBean = beanFactory.getBean(regionName);
Assert.isTrue(existingBean instanceof Region, String.format(
"Cannot create a client PROXY Region bean named '%1$s'. A bean with this name of type '%2$s' already exists.",
regionName, ObjectUtils.nullSafeClassName(existingBean)));
if (logger.isWarnEnabled()) {
logger.warn("Cannot create a client PROXY Region bean named {}; A bean with name {} having type {} already exists",
regionName, regionName, ObjectUtils.nullSafeClassName(existingBean));
}
createRegion = false;
}
@@ -142,17 +150,15 @@ public class GemfireDataSourcePostProcessor implements BeanFactoryPostProcessor
beanFactory.registerSingleton(regionName, clientRegionFactory.create(regionName));
}
else {
log("A Region with name '%s' is already defined.", regionName);
log("A Region with name '%s' is already defined", regionName);
}
}
}
}
/* (non-Javadoc) */
void log(String message, Object... arguments) {
if (logger.isDebugEnabled()) {
logger.debug(String.format(message, arguments));
}
}
}

View File

@@ -24,13 +24,13 @@ import org.apache.geode.cache.client.Pool;
import org.apache.geode.cache.query.QueryService;
/**
* The PoolAdapter class is an abstract, default no-op implementation of the GemFire {@link Pool} interface
* that conveniently enables implementing classes to extend this adapter to adapt their interfaces and serve
* as a {@link Pool}.
* The {@link PoolAdapter} class is an abstract base class and default, no-op implementation of
* the {@link Pool} interface that conveniently enables implementing classes to extend this adapter
* and choose which {@link Pool} methods/operations are supported by this implementation.
*
* For instance, one possible implementation is Spring Data GemFire's {@link PoolFactoryBean}, which can act as
* a {@link Pool} in a context where only the {@link Pool}'s "configuration" and meta-data are required,
* but not actual connections or operating state information (e.g. pendingEventCount).
* but no actual connections or operating state information (e.g. pendingEventCount) is needed.
*
* @author John Blum
* @see org.springframework.data.gemfire.client.PoolFactoryBean
@@ -42,148 +42,119 @@ public abstract class PoolAdapter implements Pool {
public static final String NOT_IMPLEMENTED = "Not Implemented";
/* (non-Javadoc) */
public boolean isDestroyed() {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
/* (non-Javadoc) */
public int getFreeConnectionTimeout() {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
/* (non-Javadoc) */
public long getIdleTimeout() {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
/* (non-Javadoc) */
public int getLoadConditioningInterval() {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
/* (non-Javadoc) */
public List<InetSocketAddress> getLocators() {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
/* (non-Javadoc) */
public int getMaxConnections() {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
/* (non-Javadoc) */
public int getMinConnections() {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
/* (non-Javadoc) */
public boolean getMultiuserAuthentication() {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
/* (non-Javadoc) */
public String getName() {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
/* (non-Javadoc) */
@Override
public List<InetSocketAddress> getOnlineLocators() {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
/* (non-Javadoc) */
public int getPendingEventCount() {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
/* (non-Javadoc) */
public long getPingInterval() {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
/* (non-Javadoc) */
public boolean getPRSingleHopEnabled() {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
/* (non-Javadoc) */
public QueryService getQueryService() {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
/* (non-Javadoc) */
public int getReadTimeout() {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
/* (non-Javadoc) */
public int getRetryAttempts() {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
/* (non-Javadoc) */
public String getServerGroup() {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
/* (non-Javadoc) */
public List<InetSocketAddress> getServers() {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
/* (non-Javadoc) */
public int getSocketBufferSize() {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
/* (non-Javadoc) */
public int getSocketConnectTimeout() {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
/* (non-Javadoc) */
public int getStatisticInterval() {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
/* (non-Javadoc) */
public int getSubscriptionAckInterval() {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
/* (non-Javadoc) */
public boolean getSubscriptionEnabled() {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
/* (non-Javadoc) */
public int getSubscriptionMessageTrackingTimeout() {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
/* (non-Javadoc) */
public int getSubscriptionRedundancy() {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
/* (non-Javadoc) */
public boolean getThreadLocalConnections() {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
/* (non-Javadoc) */
public void destroy() {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
/* (non-Javadoc) */
public void destroy(final boolean keepAlive) {
public void destroy(boolean keepAlive) {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
/* (non-Javadoc) */
public void releaseThreadLocalConnection() {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}

View File

@@ -21,6 +21,7 @@ import static org.springframework.data.gemfire.util.ArrayUtils.nullSafeArray;
import static org.springframework.data.gemfire.util.CollectionUtils.nullSafeCollection;
import static org.springframework.data.gemfire.util.CollectionUtils.nullSafeIterable;
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalArgumentException;
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalStateException;
import java.net.InetSocketAddress;
import java.util.Arrays;
@@ -75,8 +76,8 @@ public class PoolFactoryBean extends AbstractFactoryBeanSupport<Pool> implements
protected static final int DEFAULT_LOCATOR_PORT = DistributedSystemUtils.DEFAULT_LOCATOR_PORT;
protected static final int DEFAULT_SERVER_PORT = DistributedSystemUtils.DEFAULT_CACHE_SERVER_PORT;
// indicates whether the Pool has been created internally (by this FactoryBean) or not
volatile boolean springBasedPool = true;
// Indicates whether the Pool has been created by this FactoryBean, or not
volatile boolean springManagedPool = true;
// GemFire Pool Configuration Settings
private boolean keepAlive = false;
@@ -109,7 +110,7 @@ public class PoolFactoryBean extends AbstractFactoryBeanSupport<Pool> implements
private volatile Pool pool;
private PoolConfigurer compositePoolConfigurer = (beanName, bean) ->
nullSafeCollection(poolConfigurers).forEach(poolConfigurer -> poolConfigurer.configure(beanName, bean));
nullSafeCollection(poolConfigurers).forEach(poolConfigurer -> poolConfigurer.configure(beanName, bean));
private PoolFactoryInitializer poolFactoryInitializer;
@@ -123,33 +124,44 @@ public class PoolFactoryBean extends AbstractFactoryBeanSupport<Pool> implements
* @see org.apache.geode.cache.client.PoolManager
* @see org.apache.geode.cache.client.PoolFactory
* @see org.apache.geode.cache.client.Pool
* @see #resolvePoolName()
*/
@Override
public void afterPropertiesSet() throws Exception {
init(Optional.ofNullable(PoolManager.find(validatePoolName())));
}
/* (non-Javadoc) */
@SuppressWarnings("all")
private void init(Optional<Pool> existingPool) {
Pool existingPool = find(resolvePoolName());
if (existingPool.isPresent()) {
this.pool = existingPool.get();
this.springBasedPool = false;
if (existingPool != null) {
logDebug(() -> String.format(
"Pool with name [%s] already exists; Using existing Pool; Pool Configurers [%d] will not be applied",
existingPool.get().getName(), this.poolConfigurers.size()));
this.pool = existingPool;
this.springManagedPool = false;
logDebug(() -> String.format("A Pool with name [%s] already exists; Using existing Pool",
this.pool.getName()));
logDebug("PoolConfigurers will not be applied");
}
else {
this.springBasedPool = true;
logDebug("Pool [%s] not found; Lazily creating new Pool...", getName());
applyPoolConfigurers();
logDebug("No Pool with name [%s] was found; Creating new Pool", getName());
}
}
/* (non-Javadoc) */
private String resolvePoolName() {
if (!StringUtils.hasText(getName())) {
setName(Optional.ofNullable(getBeanName())
.filter(StringUtils::hasText)
.orElseThrow(() -> newIllegalArgumentException("Pool name is required")));
}
return getName();
}
private Pool find(String name) {
return PoolManager.find(name);
}
private void applyPoolConfigurers() {
applyPoolConfigurers(getCompositePoolConfigurer());
}
@@ -179,17 +191,6 @@ public class PoolFactoryBean extends AbstractFactoryBeanSupport<Pool> implements
.forEach(poolConfigurer -> poolConfigurer.configure(getName(), this));
}
/* (non-Javadoc) */
private String validatePoolName() {
if (!StringUtils.hasText(getName())) {
setName(Optional.ofNullable(getBeanName()).filter(StringUtils::hasText)
.orElseThrow(() -> newIllegalArgumentException("Pool name is required")));
}
return getName();
}
/**
* Releases all system resources and destroys the {@link Pool} when created by this {@link PoolFactoryBean}.
*
@@ -200,7 +201,7 @@ public class PoolFactoryBean extends AbstractFactoryBeanSupport<Pool> implements
public void destroy() throws Exception {
Optional.ofNullable(this.pool)
.filter(pool -> this.springBasedPool)
.filter(pool -> this.springManagedPool)
.filter(pool -> !pool.isDestroyed())
.ifPresent(pool -> {
pool.releaseThreadLocalConnection();
@@ -210,17 +211,6 @@ public class PoolFactoryBean extends AbstractFactoryBeanSupport<Pool> implements
});
}
/**
* Returns a reference to the Composite {@link PoolConfigurer} used to apply additional configuration
* to this {@link PoolFactoryBean} on Spring container initialization.
*
* @return the Composite {@link PoolConfigurer}.
* @see org.springframework.data.gemfire.config.annotation.PoolConfigurer
*/
protected PoolConfigurer getCompositePoolConfigurer() {
return this.compositePoolConfigurer;
}
/**
* Returns an object reference to the {@link Pool} created by this {@link PoolFactoryBean}.
*
@@ -233,28 +223,17 @@ public class PoolFactoryBean extends AbstractFactoryBeanSupport<Pool> implements
return Optional.ofNullable(this.pool).orElseGet(() -> {
eagerlyInitializeClientCacheIfNotPresent();
eagerlyInitializeClientCache();
PoolFactory poolFactory = configure(initialize(createPoolFactory()));
Pool namedPool = find(getName());
this.pool = create(poolFactory, getName());
this.pool = namedPool != null ? namedPool
: postProcess(create(postProcess(configure(initialize(createPoolFactory()))), getName()));
return this.pool;
});
}
/**
* Determines whether the {@link DistributedSystem} exists yet or not.
*
* @return a boolean value indicating whether the single, {@link DistributedSystem} has already been created.
* @see org.springframework.data.gemfire.GemfireUtils#getDistributedSystem()
* @see org.springframework.data.gemfire.GemfireUtils#isConnected(DistributedSystem)
* @see org.apache.geode.distributed.DistributedSystem
*/
boolean isDistributedSystemPresent() {
return GemfireUtils.isConnected(GemfireUtils.getDistributedSystem());
}
/**
* Attempts to eagerly initialize the {@link ClientCache} if not already present so that a single
* {@link DistributedSystem} will exist, which is required to create a {@link Pool} instance.
@@ -262,14 +241,33 @@ public class PoolFactoryBean extends AbstractFactoryBeanSupport<Pool> implements
* @see org.springframework.beans.factory.BeanFactory#getBean(Class)
* @see org.apache.geode.cache.client.ClientCache
* @see org.apache.geode.distributed.DistributedSystem
* @see #isDistributedSystemPresent()
* @see #isClientCachePresent()
*/
private void eagerlyInitializeClientCacheIfNotPresent() {
if (!isDistributedSystemPresent()) {
private void eagerlyInitializeClientCache() {
if (!isClientCachePresent()) {
getBeanFactory().getBean(ClientCache.class);
}
}
/**
* Determines whether the {@link ClientCache} exists yet or not.
*
* @return a boolean value indicating whether the single {@link ClientCache} instance
* has been created yet.
* @see org.springframework.data.gemfire.GemfireUtils#getClientCache()
* @see org.apache.geode.distributed.DistributedSystem
* @see org.apache.geode.cache.client.ClientCache
*/
boolean isClientCachePresent() {
return Optional.ofNullable(GemfireUtils.getClientCache())
.filter(clientCache -> !clientCache.isClosed())
.map(ClientCache::getDistributedSystem)
.filter(GemfireUtils::isConnected)
.isPresent();
}
/**
* Creates an instance of the {@link PoolFactory} interface to construct, configure and initialize a {@link Pool}.
*
@@ -336,6 +334,17 @@ public class PoolFactoryBean extends AbstractFactoryBeanSupport<Pool> implements
.orElse(poolFactory);
}
/**
* Post processes the fully configured {@link PoolFactory}.
*
* @param poolFactory {@link PoolFactory} to post process.
* @return the post processed {@link PoolFactory}.
* @see org.apache.geode.cache.client.PoolFactory
*/
protected PoolFactory postProcess(PoolFactory poolFactory) {
return poolFactory;
}
/**
* Creates a {@link Pool} with the given {@link String name} using the provided {@link PoolFactory}.
*
@@ -350,61 +359,77 @@ public class PoolFactoryBean extends AbstractFactoryBeanSupport<Pool> implements
}
/**
* Returns the {@link Class} type of the {@link Pool} produced by this {@link PoolFactoryBean}.
* Post processes the {@link Pool} created by this {@link PoolFactoryBean}.
*
* @return the {@link Class} type of the {@link Pool} produced by this {@link PoolFactoryBean}.
* @param pool {@link Pool} to post process.
* @return the post processed {@link Pool}.
* @see org.apache.geode.cache.client.Pool
*/
protected Pool postProcess(Pool pool) {
return pool;
}
/**
* Returns the {@link Class type} of {@link Pool} produced by this {@link PoolFactoryBean}.
*
* @return the {@link Class type} of {@link Pool} produced by this {@link PoolFactoryBean}.
* @see org.springframework.beans.factory.FactoryBean#getObjectType()
*/
@Override
@SuppressWarnings("unchecked")
public Class<?> getObjectType() {
return Optional.ofNullable(this.pool).map(Pool::getClass).orElse((Class) Pool.class);
return this.pool != null ? this.pool.getClass() : Pool.class;
}
/* (non-Javadoc) */
public void addLocators(ConnectionEndpoint... locators) {
this.locators.add(locators);
}
/* (non-Javadoc) */
public void addLocators(Iterable<ConnectionEndpoint> locators) {
this.locators.add(locators);
}
/* (non-Javadoc) */
public void addServers(ConnectionEndpoint... servers) {
this.servers.add(servers);
}
/* (non-Javadoc) */
public void addServers(Iterable<ConnectionEndpoint> servers) {
this.servers.add(servers);
}
/* (non-Javadoc) */
/**
* Returns a reference to the Composite {@link PoolConfigurer} used to apply additional configuration
* to this {@link PoolFactoryBean} on Spring container initialization.
*
* @return the Composite {@link PoolConfigurer}.
* @see org.springframework.data.gemfire.config.annotation.PoolConfigurer
*/
protected PoolConfigurer getCompositePoolConfigurer() {
return this.compositePoolConfigurer;
}
public void setName(String name) {
this.name = name;
}
/* (non-Javadoc) */
protected String getName() {
return this.name;
}
/* (non-Javadoc) */
public void setPool(Pool pool) {
this.pool = pool;
}
/* (non-Javadoc) */
public Pool getPool() {
return Optional.ofNullable(this.pool).orElseGet(() -> new PoolAdapter() {
@Override
public boolean isDestroyed() {
Pool pool = PoolFactoryBean.this.pool;
return (pool != null && pool.isDestroyed());
return pool != null && pool.isDestroyed();
}
@Override
@@ -429,8 +454,10 @@ public class PoolFactoryBean extends AbstractFactoryBeanSupport<Pool> implements
@Override
public List<InetSocketAddress> getOnlineLocators() {
return Optional.ofNullable(PoolFactoryBean.this.pool).map(Pool::getOnlineLocators)
.orElseThrow(() -> new IllegalStateException("The Pool has not been initialized"));
return Optional.ofNullable(PoolFactoryBean.this.pool)
.map(Pool::getOnlineLocators)
.orElseThrow(() -> newIllegalStateException("Pool [%s] has not been initialized", getName()));
}
@Override
@@ -450,14 +477,18 @@ public class PoolFactoryBean extends AbstractFactoryBeanSupport<Pool> implements
@Override
public String getName() {
return Optional.ofNullable(PoolFactoryBean.this.getName()).filter(StringUtils::hasText)
return Optional.ofNullable(PoolFactoryBean.this.getName())
.filter(StringUtils::hasText)
.orElseGet(PoolFactoryBean.this::getBeanName);
}
@Override
public int getPendingEventCount() {
return Optional.ofNullable(PoolFactoryBean.this.pool).map(Pool::getPendingEventCount)
.orElseThrow(() -> new IllegalStateException("The Pool has not been initialized"));
return Optional.ofNullable(PoolFactoryBean.this.pool)
.map(Pool::getPendingEventCount)
.orElseThrow(() -> newIllegalStateException("Pool [%s] has not been initialized", getName()));
}
@Override
@@ -472,8 +503,10 @@ public class PoolFactoryBean extends AbstractFactoryBeanSupport<Pool> implements
@Override
public QueryService getQueryService() {
return Optional.ofNullable(PoolFactoryBean.this.pool).map(Pool::getQueryService)
.orElseThrow(() -> new IllegalStateException("The Pool has not been initialized"));
return Optional.ofNullable(PoolFactoryBean.this.pool)
.map(Pool::getQueryService)
.orElseThrow(() -> newIllegalStateException("Pool [%s] has not been initialized", getName()));
}
@Override
@@ -543,6 +576,7 @@ public class PoolFactoryBean extends AbstractFactoryBeanSupport<Pool> implements
@Override
public void destroy(boolean keepAlive) {
try {
PoolFactoryBean.this.destroy();
}
@@ -553,70 +587,58 @@ public class PoolFactoryBean extends AbstractFactoryBeanSupport<Pool> implements
@Override
public void releaseThreadLocalConnection() {
Pool pool = PoolFactoryBean.this.pool;
if (pool != null) {
pool.releaseThreadLocalConnection();
}
else {
throw new IllegalStateException("The Pool has not been initialized");
}
Optional.ofNullable(PoolFactoryBean.this.pool)
.map(it -> {
it.releaseThreadLocalConnection();
return it;
})
.orElseThrow(() -> newIllegalStateException("Pool [%s] has not been initialized", getName()));
}
});
}
/* (non-Javadoc) */
public void setFreeConnectionTimeout(int freeConnectionTimeout) {
this.freeConnectionTimeout = freeConnectionTimeout;
}
/* (non-Javadoc) */
public void setIdleTimeout(long idleTimeout) {
this.idleTimeout = idleTimeout;
}
/* (non-Javadoc) */
public void setKeepAlive(boolean keepAlive) {
this.keepAlive = keepAlive;
}
/* (non-Javadoc) */
public void setLoadConditioningInterval(int loadConditioningInterval) {
this.loadConditioningInterval = loadConditioningInterval;
}
/* (non-Javadoc) */
public void setLocators(ConnectionEndpoint[] connectionEndpoints) {
setLocators(ConnectionEndpointList.from(connectionEndpoints));
}
/* (non-Javadoc) */
public void setLocators(Iterable<ConnectionEndpoint> connectionEndpoints) {
getLocators().clear();
getLocators().add(connectionEndpoints);
}
/* (non-Javadoc) */
ConnectionEndpointList getLocators() {
return locators;
}
/* (non-Javadoc) */
public void setMaxConnections(int maxConnections) {
this.maxConnections = maxConnections;
}
/* (non-Javadoc) */
public void setMinConnections(int minConnections) {
this.minConnections = minConnections;
}
/* (non-Javadoc) */
public void setMultiUserAuthentication(boolean multiUserAuthentication) {
this.multiUserAuthentication = multiUserAuthentication;
}
/* (non-Javadoc) */
public void setPingInterval(long pingInterval) {
this.pingInterval = pingInterval;
}
@@ -658,78 +680,63 @@ public class PoolFactoryBean extends AbstractFactoryBeanSupport<Pool> implements
this.poolFactoryInitializer = poolFactoryInitializer;
}
/* (non-Javadoc) */
public void setPrSingleHopEnabled(boolean prSingleHopEnabled) {
this.prSingleHopEnabled = prSingleHopEnabled;
}
/* (non-Javadoc) */
public void setReadTimeout(int readTimeout) {
this.readTimeout = readTimeout;
}
/* (non-Javadoc) */
public void setRetryAttempts(int retryAttempts) {
this.retryAttempts = retryAttempts;
}
/* (non-Javadoc) */
public void setServerGroup(String serverGroup) {
this.serverGroup = serverGroup;
}
/* (non-Javadoc) */
public void setServers(ConnectionEndpoint[] connectionEndpoints) {
setServers(ConnectionEndpointList.from(connectionEndpoints));
}
/* (non-Javadoc) */
public void setServers(Iterable<ConnectionEndpoint> connectionEndpoints) {
getServers().clear();
getServers().add(connectionEndpoints);
}
/* (non-Javadoc) */
ConnectionEndpointList getServers() {
return servers;
}
/* (non-Javadoc) */
public void setSocketBufferSize(int socketBufferSize) {
this.socketBufferSize = socketBufferSize;
}
/* (non-Javadoc) */
public void setSocketConnectTimeout(int socketConnectTimeout) {
this.socketConnectTimeout = socketConnectTimeout;
}
/* (non-Javadoc) */
public void setStatisticInterval(int statisticInterval) {
this.statisticInterval = statisticInterval;
}
/* (non-Javadoc) */
public void setSubscriptionAckInterval(int subscriptionAckInterval) {
this.subscriptionAckInterval = subscriptionAckInterval;
}
/* (non-Javadoc) */
public void setSubscriptionEnabled(boolean subscriptionEnabled) {
this.subscriptionEnabled = subscriptionEnabled;
}
/* (non-Javadoc) */
public void setSubscriptionMessageTrackingTimeout(int subscriptionMessageTrackingTimeout) {
this.subscriptionMessageTrackingTimeout = subscriptionMessageTrackingTimeout;
}
/* (non-Javadoc) */
public void setSubscriptionRedundancy(int subscriptionRedundancy) {
this.subscriptionRedundancy = subscriptionRedundancy;
}
/* (non-Javadoc) */
public void setThreadLocalConnections(boolean threadLocalConnections) {
this.threadLocalConnections = threadLocalConnections;
}

View File

@@ -20,15 +20,18 @@ package org.springframework.data.gemfire.client.support;
import java.net.InetSocketAddress;
import java.util.Collection;
import java.util.List;
import java.util.function.Supplier;
import org.apache.geode.cache.client.Pool;
import org.apache.geode.cache.query.QueryService;
import org.apache.shiro.util.CollectionUtils;
import org.springframework.data.gemfire.util.SpringUtils;
import org.springframework.util.Assert;
/**
* The DefaultableDelegatingPoolAdapter class is a wrapper class around Pool allowing default configuration property
* values to be providing in the case that the Pool's setting were null.
* The {@link DefaultableDelegatingPoolAdapter} class is a wrapper class around {@link Pool}
* allowing default configuration property values to be provided in the case that the {@link Pool Pool's}
* settings were {@literal null}.
*
* @author John Blum
* @see org.apache.geode.cache.client.Pool
@@ -41,221 +44,178 @@ public abstract class DefaultableDelegatingPoolAdapter {
private Preference preference = Preference.PREFER_POOL;
/* (non-Javadoc) */
public static DefaultableDelegatingPoolAdapter from(Pool delegate) {
return new DefaultableDelegatingPoolAdapter(delegate) { };
return new DefaultableDelegatingPoolAdapter(delegate) {};
}
/* (non-Javadoc) */
protected DefaultableDelegatingPoolAdapter(Pool delegate) {
Assert.notNull(delegate, "'delegate' must not be null");
Assert.notNull(delegate, "Pool delegate must not be null");
this.delegate = delegate;
}
/* (non-Javadoc) */
protected Pool getDelegate() {
return this.delegate;
}
/* (non-Javadoc) */
protected DefaultableDelegatingPoolAdapter setPreference(Preference preference) {
this.preference = preference;
return this;
}
/* (non-Javadoc) */
protected Preference getPreference() {
return this.preference;
}
/* (non-Javadoc) */
protected <T> T defaultIfNull(T defaultValue, ValueProvider<T> valueProvider) {
return (prefersPool() ? SpringUtils.defaultIfNull(valueProvider.getValue(), defaultValue) :
(defaultValue != null ? defaultValue : valueProvider.getValue()));
protected <T> T defaultIfNull(T defaultValue, Supplier<T> valueProvider) {
return prefersPool() ? SpringUtils.defaultIfNull(valueProvider.get(), defaultValue) :
(defaultValue != null ? defaultValue : valueProvider.get());
}
/* (non-Javadoc) */
protected <E, T extends Collection<E>> T defaultIfEmpty(T defaultValue, ValueProvider<T> valueProvider) {
protected <E, T extends Collection<E>> T defaultIfEmpty(T defaultValue, Supplier<T> valueProvider) {
if (prefersPool()) {
T value = valueProvider.getValue();
return (value == null || value.isEmpty() ? defaultValue : value);
T value = valueProvider.get();
return CollectionUtils.isEmpty(value) ? defaultValue : value;
}
else {
return (defaultValue == null || defaultValue.isEmpty() ? valueProvider.getValue() : defaultValue);
return CollectionUtils.isEmpty(defaultValue) ? valueProvider.get() : defaultValue;
}
}
/* (non-Javadoc) */
public DefaultableDelegatingPoolAdapter preferDefault() {
return setPreference(Preference.PREFER_DEFAULT);
}
/* (non-Javadoc) */
protected boolean prefersDefault() {
return Preference.PREFER_DEFAULT.equals(getPreference());
}
/* (non-Javadoc) */
public DefaultableDelegatingPoolAdapter preferPool() {
return setPreference(Preference.PREFER_POOL);
}
/* (non-Javadoc) */
protected boolean prefersPool() {
return Preference.PREFER_POOL.equals(getPreference());
}
/* (non-Javadoc) */
public boolean isDestroyed() {
return getDelegate().isDestroyed();
}
/* (non-Javadoc) */
public int getFreeConnectionTimeout(Integer defaultFreeConnectionTimeout) {
return defaultIfNull(defaultFreeConnectionTimeout, () -> getDelegate().getFreeConnectionTimeout());
}
/* (non-Javadoc) */
public long getIdleTimeout(Long defaultIdleTimeout) {
return defaultIfNull(defaultIdleTimeout, () -> getDelegate().getIdleTimeout());
}
/* (non-Javadoc) */
public int getLoadConditioningInterval(Integer defaultLoadConditioningInterval) {
return defaultIfNull(defaultLoadConditioningInterval, () -> getDelegate().getLoadConditioningInterval());
}
/* (non-Javadoc) */
public List<InetSocketAddress> getLocators(List<InetSocketAddress> defaultLocators) {
return defaultIfEmpty(defaultLocators, () -> getDelegate().getLocators());
}
/* (non-Javadoc) */
public int getMaxConnections(Integer defaultMaxConnections) {
return defaultIfNull(defaultMaxConnections, () -> getDelegate().getMaxConnections());
}
/* (non-Javadoc) */
public int getMinConnections(Integer defaultMinConnections) {
return defaultIfNull(defaultMinConnections, () -> getDelegate().getMinConnections());
}
/* (non-Javadoc) */
public boolean getMultiuserAuthentication(Boolean defaultMultiUserAuthentication) {
return defaultIfNull(defaultMultiUserAuthentication, () -> getDelegate().getMultiuserAuthentication());
}
/* (non-Javadoc) */
public String getName() {
return getDelegate().getName();
}
/* (non-Javadoc) */
public int getPendingEventCount() {
return getDelegate().getPendingEventCount();
}
/* (non-Javadoc) */
public long getPingInterval(Long defaultPingInterval) {
return defaultIfNull(defaultPingInterval, () -> getDelegate().getPingInterval());
}
/* (non-Javadoc) */
public boolean getPRSingleHopEnabled(Boolean defaultPrSingleHopEnabled) {
return defaultIfNull(defaultPrSingleHopEnabled, () -> getDelegate().getPRSingleHopEnabled());
}
/* (non-Javadoc) */
public QueryService getQueryService(QueryService defaultQueryService) {
return defaultIfNull(defaultQueryService, () -> getDelegate().getQueryService());
}
/* (non-Javadoc) */
public int getReadTimeout(Integer defaultReadTimeout) {
return defaultIfNull(defaultReadTimeout, () -> getDelegate().getReadTimeout());
}
/* (non-Javadoc) */
public int getRetryAttempts(Integer defaultRetryAttempts) {
return defaultIfNull(defaultRetryAttempts, () -> getDelegate().getRetryAttempts());
}
/* (non-Javadoc) */
public String getServerGroup(String defaultServerGroup) {
return defaultIfNull(defaultServerGroup, () -> getDelegate().getServerGroup());
}
/* (non-Javadoc) */
public List<InetSocketAddress> getServers(List<InetSocketAddress> defaultServers) {
return defaultIfEmpty(defaultServers, () -> getDelegate().getServers());
}
/* (non-Javadoc) */
public int getSocketBufferSize(Integer defaultSocketBufferSize) {
return defaultIfNull(defaultSocketBufferSize, () -> getDelegate().getSocketBufferSize());
}
/* (non-Javadoc) */
public int getSocketConnectTimeout(Integer defaultSocketConnectTimeout) {
return defaultIfNull(defaultSocketConnectTimeout, () -> getDelegate().getSocketConnectTimeout());
}
/* (non-Javadoc) */
public int getStatisticInterval(Integer defaultStatisticInterval) {
return defaultIfNull(defaultStatisticInterval, () -> getDelegate().getStatisticInterval());
}
/* (non-Javadoc) */
public int getSubscriptionAckInterval(Integer defaultSubscriptionAckInterval) {
return defaultIfNull(defaultSubscriptionAckInterval, () -> getDelegate().getSubscriptionAckInterval());
}
/* (non-Javadoc) */
public boolean getSubscriptionEnabled(Boolean defaultSubscriptionEnabled) {
return defaultIfNull(defaultSubscriptionEnabled, () -> getDelegate().getSubscriptionEnabled());
}
/* (non-Javadoc) */
public int getSubscriptionMessageTrackingTimeout(Integer defaultSubscriptionMessageTrackingTimeout) {
return defaultIfNull(defaultSubscriptionMessageTrackingTimeout,
() -> getDelegate().getSubscriptionMessageTrackingTimeout());
}
/* (non-Javadoc) */
public int getSubscriptionRedundancy(Integer defaultSubscriptionRedundancy) {
return defaultIfNull(defaultSubscriptionRedundancy, () -> getDelegate().getSubscriptionRedundancy());
}
/* (non-Javadoc) */
public boolean getThreadLocalConnections(Boolean defaultThreadLocalConnections) {
return defaultIfNull(defaultThreadLocalConnections, () -> getDelegate().getThreadLocalConnections());
}
/* (non-Javadoc) */
public void destroy() {
getDelegate().destroy();
}
/* (non-Javadoc) */
public void destroy(final boolean keepAlive) {
public void destroy(boolean keepAlive) {
getDelegate().destroy(keepAlive);
}
/* (non-Javadoc) */
public void releaseThreadLocalConnection() {
getDelegate().releaseThreadLocalConnection();
}
/* (non-Javadoc) */
enum Preference {
PREFER_DEFAULT,
PREFER_POOL
}
/* (non-Javadoc) */
interface ValueProvider<T> {
T getValue();
}
}

View File

@@ -25,7 +25,7 @@ import org.apache.geode.cache.client.Pool;
import org.apache.geode.cache.query.QueryService;
/**
* DelegatingPoolAdapter is an abstract implementation of GemFire's {@link Pool} interface and extension of
* {@link DelegatingPoolAdapter} is an abstract implementation of GemFire's {@link Pool} interface and extension of
* {@link FactoryDefaultsPoolAdapter} that delegates operations to the provided {@link Pool} instance.
*
* However, this implementation guards against a potentially <code>null</code> {@link Pool} reference by returning
@@ -33,8 +33,9 @@ import org.apache.geode.cache.query.QueryService;
* when the {@link Pool} reference is <code>null</code>.
*
* @author John Blum
* @see org.springframework.data.gemfire.client.support.FactoryDefaultsPoolAdapter
* @see org.apache.geode.cache.client.Pool
* @see org.apache.geode.cache.query.QueryService
* @see org.springframework.data.gemfire.client.support.FactoryDefaultsPoolAdapter
* @since 1.8.0
*/
@SuppressWarnings("unused")
@@ -42,9 +43,8 @@ public abstract class DelegatingPoolAdapter extends FactoryDefaultsPoolAdapter {
private final Pool delegate;
/* (non-Javadoc) */
public static DelegatingPoolAdapter from(Pool delegate) {
return new DelegatingPoolAdapter(delegate) { };
return new DelegatingPoolAdapter(delegate) {};
}
/**
@@ -57,191 +57,225 @@ public abstract class DelegatingPoolAdapter extends FactoryDefaultsPoolAdapter {
this.delegate = delegate;
}
/* (non-Javadoc) */
protected Pool getDelegate() {
return delegate;
return this.delegate;
}
/* (non-Javadoc) */
@Override
public boolean isDestroyed() {
return Optional.ofNullable(getDelegate()).map(Pool::isDestroyed).orElseGet(super::isDestroyed);
}
/* (non-Javadoc) */
@Override
public int getFreeConnectionTimeout() {
return Optional.ofNullable(getDelegate()).map(Pool::getFreeConnectionTimeout)
return Optional.ofNullable(getDelegate())
.map(Pool::getFreeConnectionTimeout)
.orElseGet(super::getFreeConnectionTimeout);
}
/* (non-Javadoc) */
@Override
public long getIdleTimeout() {
return Optional.ofNullable(getDelegate()).map(Pool::getIdleTimeout).orElseGet(super::getIdleTimeout);
return Optional.ofNullable(getDelegate())
.map(Pool::getIdleTimeout)
.orElseGet(super::getIdleTimeout);
}
/* (non-Javadoc) */
@Override
public int getLoadConditioningInterval() {
return Optional.ofNullable(getDelegate()).map(Pool::getLoadConditioningInterval)
return Optional.ofNullable(getDelegate())
.map(Pool::getLoadConditioningInterval)
.orElseGet(super::getLoadConditioningInterval);
}
/* (non-Javadoc) */
@Override
public List<InetSocketAddress> getLocators() {
return Optional.ofNullable(getDelegate()).map(Pool::getLocators).orElseGet(super::getLocators);
return Optional.ofNullable(getDelegate())
.map(Pool::getLocators)
.orElseGet(super::getLocators);
}
/* (non-Javadoc) */
@Override
public int getMaxConnections() {
return Optional.ofNullable(getDelegate()).map(Pool::getMaxConnections).orElseGet(super::getMaxConnections);
return Optional.ofNullable(getDelegate())
.map(Pool::getMaxConnections)
.orElseGet(super::getMaxConnections);
}
/* (non-Javadoc) */
@Override
public int getMinConnections() {
return Optional.ofNullable(getDelegate()).map(Pool::getMinConnections).orElseGet(super::getMinConnections);
return Optional.ofNullable(getDelegate())
.map(Pool::getMinConnections)
.orElseGet(super::getMinConnections);
}
/* (non-Javadoc) */
@Override
public boolean getMultiuserAuthentication() {
return Optional.ofNullable(getDelegate()).map(Pool::getMultiuserAuthentication)
return Optional.ofNullable(getDelegate())
.map(Pool::getMultiuserAuthentication)
.orElseGet(super::getMultiuserAuthentication);
}
/* (non-Javadoc) */
@Override
public String getName() {
return Optional.ofNullable(getDelegate()).map(Pool::getName).orElseGet(super::getName);
return Optional.ofNullable(getDelegate())
.map(Pool::getName)
.orElseGet(super::getName);
}
/* (non-Javadoc) */
@Override
public List<InetSocketAddress> getOnlineLocators() {
return Optional.ofNullable(getDelegate()).map(Pool::getOnlineLocators).orElseGet(super::getOnlineLocators);
return Optional.ofNullable(getDelegate())
.map(Pool::getOnlineLocators)
.orElseGet(super::getOnlineLocators);
}
/* (non-Javadoc) */
@Override
public int getPendingEventCount() {
return Optional.ofNullable(getDelegate()).map(Pool::getPendingEventCount).orElse(0);
return Optional.ofNullable(getDelegate())
.map(Pool::getPendingEventCount)
.orElse(0);
}
/* (non-Javadoc) */
@Override
public long getPingInterval() {
return Optional.ofNullable(getDelegate()).map(Pool::getPingInterval).orElseGet(super::getPingInterval);
return Optional.ofNullable(getDelegate())
.map(Pool::getPingInterval)
.orElseGet(super::getPingInterval);
}
/* (non-Javadoc) */
@Override
public boolean getPRSingleHopEnabled() {
return Optional.ofNullable(getDelegate()).map(Pool::getPRSingleHopEnabled)
return Optional.ofNullable(getDelegate())
.map(Pool::getPRSingleHopEnabled)
.orElseGet(super::getPRSingleHopEnabled);
}
/* (non-Javadoc) */
@Override
public QueryService getQueryService() {
return Optional.ofNullable(getDelegate()).map(Pool::getQueryService).orElseGet(super::getQueryService);
return Optional.ofNullable(getDelegate())
.map(Pool::getQueryService)
.orElseGet(super::getQueryService);
}
/* (non-Javadoc) */
@Override
public int getReadTimeout() {
return Optional.ofNullable(getDelegate()).map(Pool::getReadTimeout).orElseGet(super::getReadTimeout);
return Optional.ofNullable(getDelegate())
.map(Pool::getReadTimeout)
.orElseGet(super::getReadTimeout);
}
/* (non-Javadoc) */
@Override
public int getRetryAttempts() {
return Optional.ofNullable(getDelegate()).map(Pool::getRetryAttempts).orElseGet(super::getRetryAttempts);
return Optional.ofNullable(getDelegate())
.map(Pool::getRetryAttempts)
.orElseGet(super::getRetryAttempts);
}
/* (non-Javadoc) */
@Override
public String getServerGroup() {
return Optional.ofNullable(getDelegate()).map(Pool::getServerGroup).orElseGet(super::getServerGroup);
return Optional.ofNullable(getDelegate())
.map(Pool::getServerGroup)
.orElseGet(super::getServerGroup);
}
/* (non-Javadoc) */
@Override
public List<InetSocketAddress> getServers() {
return Optional.ofNullable(getDelegate()).map(Pool::getServers).orElseGet(super::getServers);
return Optional.ofNullable(getDelegate())
.map(Pool::getServers)
.orElseGet(super::getServers);
}
/* (non-Javadoc) */
@Override
public int getSocketBufferSize() {
return Optional.ofNullable(getDelegate()).map(Pool::getSocketBufferSize).orElseGet(super::getSocketBufferSize);
return Optional.ofNullable(getDelegate())
.map(Pool::getSocketBufferSize)
.orElseGet(super::getSocketBufferSize);
}
/* (non-Javadoc) */
@Override
public int getSocketConnectTimeout() {
return Optional.ofNullable(getDelegate()).map(Pool::getSocketConnectTimeout)
return Optional.ofNullable(getDelegate())
.map(Pool::getSocketConnectTimeout)
.orElseGet(super::getSocketConnectTimeout);
}
/* (non-Javadoc) */
@Override
public int getStatisticInterval() {
return Optional.ofNullable(getDelegate()).map(Pool::getStatisticInterval)
return Optional.ofNullable(getDelegate())
.map(Pool::getStatisticInterval)
.orElseGet(super::getStatisticInterval);
}
/* (non-Javadoc) */
@Override
public int getSubscriptionAckInterval() {
return Optional.ofNullable(getDelegate()).map(Pool::getSubscriptionAckInterval)
return Optional.ofNullable(getDelegate())
.map(Pool::getSubscriptionAckInterval)
.orElseGet(super::getSubscriptionAckInterval);
}
/* (non-Javadoc) */
@Override
public boolean getSubscriptionEnabled() {
return Optional.ofNullable(getDelegate()).map(Pool::getSubscriptionEnabled)
return Optional.ofNullable(getDelegate())
.map(Pool::getSubscriptionEnabled)
.orElseGet(super::getSubscriptionEnabled);
}
/* (non-Javadoc) */
@Override
public int getSubscriptionMessageTrackingTimeout() {
return Optional.ofNullable(getDelegate()).map(Pool::getSubscriptionMessageTrackingTimeout)
return Optional.ofNullable(getDelegate())
.map(Pool::getSubscriptionMessageTrackingTimeout)
.orElseGet(super::getSubscriptionMessageTrackingTimeout);
}
/* (non-Javadoc) */
@Override
public int getSubscriptionRedundancy() {
return Optional.ofNullable(getDelegate()).map(Pool::getSubscriptionRedundancy)
return Optional.ofNullable(getDelegate())
.map(Pool::getSubscriptionRedundancy)
.orElseGet(super::getSubscriptionRedundancy);
}
/* (non-Javadoc) */
@Override
public boolean getThreadLocalConnections() {
return Optional.ofNullable(getDelegate()).map(Pool::getThreadLocalConnections)
return Optional.ofNullable(getDelegate())
.map(Pool::getThreadLocalConnections)
.orElseGet(super::getThreadLocalConnections);
}
/* (non-Javadoc) */
@Override
public void destroy() {
Optional.ofNullable(getDelegate()).ifPresent(Pool::destroy);
}
/* (non-Javadoc) */
@Override
public void destroy(boolean keepAlive) {
Optional.ofNullable(getDelegate()).ifPresent(delegate -> delegate.destroy(keepAlive));
}
/* (non-Javadoc) */
@Override
public void releaseThreadLocalConnection() {
Optional.ofNullable(getDelegate()).ifPresent(Pool::releaseThreadLocalConnection);

View File

@@ -21,20 +21,21 @@ import java.net.InetSocketAddress;
import java.util.Collections;
import java.util.List;
import org.apache.geode.cache.client.Pool;
import org.apache.geode.cache.client.PoolFactory;
import org.apache.geode.cache.query.QueryService;
import org.springframework.data.gemfire.GemfireUtils;
import org.springframework.data.gemfire.client.PoolAdapter;
/**
* FactoryDefaultsPoolAdapter is an abstract implementation of GemFire's {@link org.apache.geode.cache.client.Pool}
* interface and extension of {@link PoolAdapter} providing default factory values for all configuration properties
* {@link FactoryDefaultsPoolAdapter} is an abstract implementation of the {@link Pool} interface and extension of
* {@link PoolAdapter} that provides default factory values for all configuration properties
* (e.g. freeConnectionTimeout, idleTimeout, etc).
*
* @author John Blum
* @see org.springframework.data.gemfire.client.PoolAdapter
* @see org.apache.geode.cache.client.PoolFactory
* @see org.apache.geode.cache.client.Pool
* @see org.apache.geode.cache.client.PoolFactory
* @see org.springframework.data.gemfire.client.PoolAdapter
* @since 1.8.0
*/
@SuppressWarnings("unused")
@@ -45,151 +46,126 @@ public abstract class FactoryDefaultsPoolAdapter extends PoolAdapter {
protected static final String DEFAULT_POOL_NAME = "DEFAULT";
protected static final String LOCALHOST = "localhost";
/* (non-Javadoc) */
@Override
public int getFreeConnectionTimeout() {
return PoolFactory.DEFAULT_FREE_CONNECTION_TIMEOUT;
}
/* (non-Javadoc) */
@Override
public long getIdleTimeout() {
return PoolFactory.DEFAULT_IDLE_TIMEOUT;
}
/* (non-Javadoc) */
@Override
public int getLoadConditioningInterval() {
return PoolFactory.DEFAULT_LOAD_CONDITIONING_INTERVAL;
}
/* (non-Javadoc) */
@Override
public List<InetSocketAddress> getLocators() {
return Collections.emptyList();
}
/* (non-Javadoc) */
@Override
public int getMaxConnections() {
return PoolFactory.DEFAULT_MAX_CONNECTIONS;
}
/* (non-Javadoc) */
@Override
public int getMinConnections() {
return PoolFactory.DEFAULT_MIN_CONNECTIONS;
}
/* (non-Javadoc) */
@Override
public boolean getMultiuserAuthentication() {
return PoolFactory.DEFAULT_MULTIUSER_AUTHENTICATION;
}
/* (non-Javadoc) */
@Override
public String getName() {
return DEFAULT_POOL_NAME;
}
/* (non-Javadoc) */
@Override
public List<InetSocketAddress> getOnlineLocators() {
return Collections.emptyList();
}
/* (non-Javadoc) */
@Override
public long getPingInterval() {
return PoolFactory.DEFAULT_PING_INTERVAL;
}
/* (non-Javadoc) */
@Override
public boolean getPRSingleHopEnabled() {
return PoolFactory.DEFAULT_PR_SINGLE_HOP_ENABLED;
}
/* (non-Javadoc) */
@Override
public QueryService getQueryService() {
return null;
}
/* (non-Javadoc) */
@Override
public int getReadTimeout() {
return PoolFactory.DEFAULT_READ_TIMEOUT;
}
/* (non-Javadoc) */
@Override
public int getRetryAttempts() {
return PoolFactory.DEFAULT_RETRY_ATTEMPTS;
}
/* (non-Javadoc) */
@Override
public String getServerGroup() {
return PoolFactory.DEFAULT_SERVER_GROUP;
}
/* (non-Javadoc) */
@Override
public List<InetSocketAddress> getServers() {
return Collections.singletonList(new InetSocketAddress(LOCALHOST, GemfireUtils.DEFAULT_CACHE_SERVER_PORT));
}
/* (non-Javadoc) */
@Override
public int getSocketBufferSize() {
return PoolFactory.DEFAULT_SOCKET_BUFFER_SIZE;
}
/* (non-Javadoc) */
@Override
public int getSocketConnectTimeout() {
return PoolFactory.DEFAULT_SOCKET_CONNECT_TIMEOUT;
}
/* (non-Javadoc) */
@Override
public int getStatisticInterval() {
return PoolFactory.DEFAULT_STATISTIC_INTERVAL;
}
/* (non-Javadoc) */
@Override
public int getSubscriptionAckInterval() {
return PoolFactory.DEFAULT_SUBSCRIPTION_ACK_INTERVAL;
}
/* (non-Javadoc) */
@Override
public boolean getSubscriptionEnabled() {
return PoolFactory.DEFAULT_SUBSCRIPTION_ENABLED;
}
/* (non-Javadoc) */
@Override
public int getSubscriptionMessageTrackingTimeout() {
return PoolFactory.DEFAULT_SUBSCRIPTION_MESSAGE_TRACKING_TIMEOUT;
}
/* (non-Javadoc) */
@Override
public int getSubscriptionRedundancy() {
return PoolFactory.DEFAULT_SUBSCRIPTION_REDUNDANCY;
}
/* (non-Javadoc) */
@Override
public boolean getThreadLocalConnections() {
return PoolFactory.DEFAULT_THREAD_LOCAL_CONNECTIONS;
}
/* (non-Javadoc) */
public void destroy() {
destroy(DEFAULT_KEEP_ALIVE);
}

View File

@@ -71,7 +71,7 @@ import org.springframework.util.StringUtils;
@SuppressWarnings("unused")
public class ClientCacheConfiguration extends AbstractCacheConfiguration {
private static final AtomicBoolean CLIENT_REGION_POOL_BEAN_FACTORY_POST_PROCESSOR_REGISTERED =
private static final AtomicBoolean INFRASTRUCTURE_COMPONENTS_REGISTERED =
new AtomicBoolean(false);
protected static final boolean DEFAULT_READY_FOR_EVENTS = false;
@@ -205,13 +205,18 @@ public class ClientCacheConfiguration extends AbstractCacheConfiguration {
super.configureInfrastructure(importMetadata);
registerClientRegionPoolBeanFactoryPostProcessor(importMetadata);
registerInfrastructureComponents(importMetadata);
}
/* (non-Javadoc) */
private void registerClientRegionPoolBeanFactoryPostProcessor(AnnotationMetadata importMetadata) {
private void registerInfrastructureComponents(AnnotationMetadata importMetadata) {
if (INFRASTRUCTURE_COMPONENTS_REGISTERED.compareAndSet(false, true)) {
/*
register(BeanDefinitionBuilder.rootBeanDefinition(ClientCachePoolBeanFactoryPostProcessor.class)
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE).getBeanDefinition());
*/
if (CLIENT_REGION_POOL_BEAN_FACTORY_POST_PROCESSOR_REGISTERED.compareAndSet(false, true)) {
register(BeanDefinitionBuilder.rootBeanDefinition(ClientRegionPoolBeanFactoryPostProcessor.class)
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE).getBeanDefinition());
}

View File

@@ -0,0 +1,65 @@
/*
* 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.support;
import java.util.Optional;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.data.gemfire.client.ClientCacheFactoryBean;
import org.springframework.data.gemfire.client.ClientRegionFactoryBean;
import org.springframework.data.gemfire.client.PoolFactoryBean;
import org.springframework.util.StringUtils;
/**
* The AbstractDependencyStructuringBeanFactoryPostProcessor class...
*
* @author John Blum
* @since 1.0.0
*/
@SuppressWarnings("unused")
public abstract class AbstractDependencyStructuringBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
protected boolean isBeanDefinitionOfType(BeanDefinition beanDefinition, Class<?> type) {
return Optional.of(beanDefinition)
.map(it -> beanDefinition.getBeanClassName())
.filter(StringUtils::hasText)
.map(beanClassName -> type.getName().equals(beanClassName))
.orElseGet(() ->
Optional.ofNullable(beanDefinition.getFactoryMethodName())
.filter(StringUtils::hasText)
.filter(it -> beanDefinition instanceof AnnotatedBeanDefinition)
.map(it -> ((AnnotatedBeanDefinition) beanDefinition).getFactoryMethodMetadata())
.map(methodMetadata -> type.getName().equals(methodMetadata.getReturnTypeName()))
.orElse(false)
);
}
protected boolean isClientCacheBean(BeanDefinition beanDefinition) {
return isBeanDefinitionOfType(beanDefinition, ClientCacheFactoryBean.class);
}
protected boolean isClientRegionBean(BeanDefinition beanDefinition) {
return isBeanDefinitionOfType(beanDefinition, ClientRegionFactoryBean.class);
}
protected boolean isPoolBean(BeanDefinition beanDefinition) {
return isBeanDefinitionOfType(beanDefinition, PoolFactoryBean.class);
}
}

View File

@@ -0,0 +1,47 @@
/*
* 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.support;
import java.util.Arrays;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.data.gemfire.config.xml.GemfireConstants;
import org.springframework.data.gemfire.util.SpringUtils;
/**
* The ClientCachePoolBeanFactoryPostProcessor class...
*
* @author John Blum
* @since 1.0.0
*/
public class ClientCachePoolBeanFactoryPostProcessor extends AbstractDependencyStructuringBeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
Arrays.stream(beanFactory.getBeanDefinitionNames()).forEach(beanName -> {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
if (isPoolBean(beanDefinition)) {
SpringUtils.addDependsOn(beanDefinition, GemfireConstants.DEFAULT_GEMFIRE_CACHE_NAME);
}
});
}
}

View File

@@ -24,14 +24,10 @@ import java.util.Set;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.data.gemfire.client.ClientRegionFactoryBean;
import org.springframework.data.gemfire.client.PoolFactoryBean;
import org.springframework.data.gemfire.util.SpringUtils;
import org.springframework.util.StringUtils;
/**
* {@link ClientRegionPoolBeanFactoryPostProcessor} is a Spring {@link BeanFactoryPostProcessor} implementation
@@ -44,7 +40,7 @@ import org.springframework.util.StringUtils;
* @see org.springframework.beans.factory.config.BeanFactoryPostProcessor
* @since 1.8.2
*/
public class ClientRegionPoolBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
public class ClientRegionPoolBeanFactoryPostProcessor extends AbstractDependencyStructuringBeanFactoryPostProcessor {
protected static final String POOL_NAME_PROPERTY = "poolName";
@@ -82,35 +78,11 @@ public class ClientRegionPoolBeanFactoryPostProcessor implements BeanFactoryPost
});
}
boolean isBeanDefinitionOfType(BeanDefinition beanDefinition, Class<?> type) {
return Optional.of(beanDefinition)
.map(it -> beanDefinition.getBeanClassName())
.filter(StringUtils::hasText)
.map(beanClassName -> type.getName().equals(beanClassName))
.orElseGet(() ->
Optional.ofNullable(beanDefinition.getFactoryMethodName())
.filter(StringUtils::hasText)
.filter(it -> beanDefinition instanceof AnnotatedBeanDefinition)
.map(it -> ((AnnotatedBeanDefinition) beanDefinition).getFactoryMethodMetadata())
.map(methodMetadata -> type.getName().equals(methodMetadata.getReturnTypeName()))
.orElse(false)
);
}
/* (non-Javadoc)*/
boolean isClientRegionBean(BeanDefinition beanDefinition) {
return isBeanDefinitionOfType(beanDefinition, ClientRegionFactoryBean.class);
}
/* (non-Javadoc)*/
boolean isPoolBean(BeanDefinition beanDefinition) {
return isBeanDefinitionOfType(beanDefinition, PoolFactoryBean.class);
}
/* (non-Javadoc) */
String getPoolName(BeanDefinition clientRegionBean) {
PropertyValue poolNameProperty = clientRegionBean.getPropertyValues().getPropertyValue(POOL_NAME_PROPERTY);
return (poolNameProperty != null ? String.valueOf(poolNameProperty.getValue()) : null);
return Optional.ofNullable(clientRegionBean.getPropertyValues().getPropertyValue(POOL_NAME_PROPERTY))
.map(PropertyValue::getValue)
.map(String::valueOf)
.orElse(null);
}
}

View File

@@ -19,6 +19,7 @@ package org.springframework.data.gemfire.config.xml;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -66,7 +67,7 @@ abstract class AbstractRegionParser extends AbstractSingleBeanDefinitionParser {
@Override
protected String getParentName(Element element) {
String regionTemplate = element.getAttribute("template");
return (StringUtils.hasText(regionTemplate) ? regionTemplate : super.getParentName(element));
return StringUtils.hasText(regionTemplate) ? regionTemplate : super.getParentName(element);
}
/* (non-Javadoc) */
@@ -167,14 +168,14 @@ abstract class AbstractRegionParser extends AbstractSingleBeanDefinitionParser {
BeanDefinition templateRegionAttributes = getRegionAttributesBeanDefinition(templateRegion);
if (templateRegionAttributes != null) {
// NOTE we only need to merge the parent RegionAttributes with this since the parent will have
// already merged it's parent's RegionAttributes and so on...
// NOTE we only need to merge the parent's RegionAttributes with this since the parent
// will have already merged its parent's RegionAttributes and so on...
regionAttributesBuilder.getRawBeanDefinition().overrideFrom(templateRegionAttributes);
}
}
else {
parserContext.getReaderContext().error(String.format(
"The Region template [%1$s] must be 'defined before' the Region [%2$s] referring to the template!",
"The Region template [%1$s] must be defined before the Region [%2$s] referring to the template",
regionTemplateName, resolveId(element, regionBuilder.getRawBeanDefinition(), parserContext)),
element);
}
@@ -188,11 +189,13 @@ abstract class AbstractRegionParser extends AbstractSingleBeanDefinitionParser {
Object regionAttributes = null;
if (region.getPropertyValues().contains("attributes")) {
PropertyValue attributesProperty = region.getPropertyValues().getPropertyValue("attributes");
regionAttributes = attributesProperty.getValue();
regionAttributes =
Optional.ofNullable(region.getPropertyValues().getPropertyValue("attributes"))
.map(PropertyValue::getValue)
.orElse(null);
}
return (regionAttributes instanceof BeanDefinition ? (BeanDefinition) regionAttributes : null);
return regionAttributes instanceof BeanDefinition ? (BeanDefinition) regionAttributes : null;
}
protected void parseCollectionOfCustomSubElements(Element element, ParserContext parserContext,

View File

@@ -17,6 +17,7 @@
package org.springframework.data.gemfire.config.xml;
import java.util.List;
import java.util.Optional;
import org.apache.geode.internal.datasource.ConfigProperty;
import org.springframework.beans.factory.BeanDefinitionStoreException;
@@ -30,6 +31,7 @@ import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.data.gemfire.CacheFactoryBean;
import org.springframework.data.gemfire.config.support.CustomEditorBeanFactoryPostProcessor;
import org.springframework.data.gemfire.config.support.GemfireFeature;
import org.springframework.data.gemfire.config.support.PdxDiskStoreAwareBeanFactoryPostProcessor;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
@@ -45,8 +47,13 @@ import org.w3c.dom.NamedNodeMap;
* @author Oliver Gierke
* @author David Turanski
* @author John Blum
* @see org.springframework.beans.factory.support.AbstractBeanDefinition
* @see org.springframework.beans.factory.support.BeanDefinitionBuilder
* @see org.springframework.beans.factory.support.BeanDefinitionRegistry
* @see org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser
* @see org.springframework.beans.factory.xml.ParserContext
* @see org.springframework.data.gemfire.CacheFactoryBean
* @see org.w3c.dom.Element
*/
class CacheParser extends AbstractSingleBeanDefinitionParser {
@@ -62,79 +69,79 @@ class CacheParser extends AbstractSingleBeanDefinitionParser {
* {@inheritDoc}
*/
@Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder cacheBuilder) {
super.doParse(element, builder);
super.doParse(element, cacheBuilder);
registerGemFireBeanFactoryPostProcessors(getRegistry(parserContext));
ParsingUtils.setPropertyValue(element, builder, "cache-xml-location", "cacheXml");
ParsingUtils.setPropertyReference(element, builder, "properties-ref", "properties");
ParsingUtils.setPropertyValue(element, builder, "use-bean-factory-locator");
ParsingUtils.setPropertyValue(element, builder, "close");
ParsingUtils.setPropertyValue(element, builder, "copy-on-read");
ParsingUtils.setPropertyValue(element, builder, "critical-heap-percentage");
ParsingUtils.setPropertyValue(element, builder, "critical-off-heap-percentage");
ParsingUtils.setPropertyValue(element, builder, "eviction-heap-percentage");
ParsingUtils.setPropertyValue(element, builder, "eviction-off-heap-percentage");
ParsingUtils.setPropertyValue(element, builder, "enable-auto-reconnect");
ParsingUtils.setPropertyValue(element, builder, "lock-lease");
ParsingUtils.setPropertyValue(element, builder, "lock-timeout");
ParsingUtils.setPropertyValue(element, builder, "message-sync-interval");
parsePdxDiskStore(element, parserContext, builder);
ParsingUtils.setPropertyValue(element, builder, "pdx-ignore-unread-fields");
ParsingUtils.setPropertyValue(element, builder, "pdx-read-serialized");
ParsingUtils.setPropertyValue(element, builder, "pdx-persistent");
ParsingUtils.setPropertyReference(element, builder, "pdx-serializer-ref", "pdxSerializer");
ParsingUtils.setPropertyValue(element, builder, "search-timeout");
ParsingUtils.setPropertyValue(element, builder, "use-cluster-configuration");
ParsingUtils.setPropertyValue(element, cacheBuilder, "cache-xml-location", "cacheXml");
ParsingUtils.setPropertyReference(element, cacheBuilder, "properties-ref", "properties");
ParsingUtils.setPropertyValue(element, cacheBuilder, "use-bean-factory-locator");
ParsingUtils.setPropertyValue(element, cacheBuilder, "close");
ParsingUtils.setPropertyValue(element, cacheBuilder, "copy-on-read");
ParsingUtils.setPropertyValue(element, cacheBuilder, "critical-heap-percentage");
ParsingUtils.setPropertyValue(element, cacheBuilder, "critical-off-heap-percentage");
ParsingUtils.setPropertyValue(element, cacheBuilder, "eviction-heap-percentage");
ParsingUtils.setPropertyValue(element, cacheBuilder, "eviction-off-heap-percentage");
ParsingUtils.setPropertyValue(element, cacheBuilder, "enable-auto-reconnect");
ParsingUtils.setPropertyValue(element, cacheBuilder, "lock-lease");
ParsingUtils.setPropertyValue(element, cacheBuilder, "lock-timeout");
ParsingUtils.setPropertyValue(element, cacheBuilder, "message-sync-interval");
parsePdxDiskStore(element, parserContext, cacheBuilder);
ParsingUtils.setPropertyValue(element, cacheBuilder, "pdx-ignore-unread-fields");
ParsingUtils.setPropertyValue(element, cacheBuilder, "pdx-read-serialized");
ParsingUtils.setPropertyValue(element, cacheBuilder, "pdx-persistent");
ParsingUtils.setPropertyReference(element, cacheBuilder, "pdx-serializer-ref", "pdxSerializer");
ParsingUtils.setPropertyValue(element, cacheBuilder, "search-timeout");
ParsingUtils.setPropertyValue(element, cacheBuilder, "use-cluster-configuration");
List<Element> txListeners = DomUtils.getChildElementsByTagName(element, "transaction-listener");
if (!CollectionUtils.isEmpty(txListeners)) {
ManagedList<Object> transactionListeners = new ManagedList<Object>();
ManagedList<Object> transactionListeners = new ManagedList<>();
for (Element txListener : txListeners) {
transactionListeners.add(ParsingUtils.parseRefOrNestedBeanDeclaration(
txListener, parserContext, builder));
txListener, parserContext, cacheBuilder));
}
builder.addPropertyValue("transactionListeners", transactionListeners);
cacheBuilder.addPropertyValue("transactionListeners", transactionListeners);
}
Element txWriter = DomUtils.getChildElementByTagName(element, "transaction-writer");
if (txWriter != null) {
builder.addPropertyValue("transactionWriter", ParsingUtils.parseRefOrNestedBeanDeclaration(
txWriter, parserContext, builder));
cacheBuilder.addPropertyValue("transactionWriter",
ParsingUtils.parseRefOrNestedBeanDeclaration(txWriter, parserContext, cacheBuilder));
}
Element gatewayConflictResolver = DomUtils.getChildElementByTagName(element, "gateway-conflict-resolver");
Element gatewayConflictResolver =
DomUtils.getChildElementByTagName(element, "gateway-conflict-resolver");
if (gatewayConflictResolver != null) {
ParsingUtils.throwExceptionIfNotGemfireV7(element.getLocalName(), "gateway-conflict-resolver", parserContext);
builder.addPropertyValue("gatewayConflictResolver", ParsingUtils.parseRefOrSingleNestedBeanDeclaration(
gatewayConflictResolver, parserContext, builder));
ParsingUtils.throwExceptionWhenGemFireFeatureUnavailable(GemfireFeature.WAN, element.getLocalName(),
"gateway-conflict-resolver", parserContext);
cacheBuilder.addPropertyValue("gatewayConflictResolver", ParsingUtils.parseRefOrSingleNestedBeanDeclaration(
gatewayConflictResolver, parserContext, cacheBuilder));
}
parseDynamicRegionFactory(element, builder);
parseJndiBindings(element, builder);
parseDynamicRegionFactory(element, cacheBuilder);
parseJndiBindings(element, cacheBuilder);
}
/* (non-Javadoc) */
protected BeanDefinitionRegistry getRegistry(ParserContext parserContext) {
return parserContext.getRegistry();
}
/* (non-Javadoc) */
void registerGemFireBeanFactoryPostProcessors(BeanDefinitionRegistry registry) {
private void registerGemFireBeanFactoryPostProcessors(BeanDefinitionRegistry registry) {
BeanDefinitionReaderUtils.registerWithGeneratedName(
BeanDefinitionBuilder.genericBeanDefinition(CustomEditorBeanFactoryPostProcessor.class)
.getBeanDefinition(), registry);
}
/* (non-Javadoc) */
private void parsePdxDiskStore(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
ParsingUtils.setPropertyValue(element, builder, "pdx-disk-store", "pdxDiskStoreName");
@@ -146,15 +153,15 @@ class CacheParser extends AbstractSingleBeanDefinitionParser {
}
}
/* (non-Javadoc) */
void registerPdxDiskStoreAwareBeanFactoryPostProcessor(BeanDefinitionRegistry registry, String pdxDiskStoreName) {
private void registerPdxDiskStoreAwareBeanFactoryPostProcessor(BeanDefinitionRegistry registry,
String pdxDiskStoreName) {
BeanDefinitionReaderUtils.registerWithGeneratedName(
createPdxDiskStoreAwareBeanFactoryPostProcessorBeanDefinition(pdxDiskStoreName), registry);
}
/* (non-Javadoc) */
private AbstractBeanDefinition createPdxDiskStoreAwareBeanFactoryPostProcessorBeanDefinition(String pdxDiskStoreName) {
private AbstractBeanDefinition createPdxDiskStoreAwareBeanFactoryPostProcessorBeanDefinition(
String pdxDiskStoreName) {
BeanDefinitionBuilder builder =
BeanDefinitionBuilder.genericBeanDefinition(PdxDiskStoreAwareBeanFactoryPostProcessor.class);
@@ -164,25 +171,26 @@ class CacheParser extends AbstractSingleBeanDefinitionParser {
return builder.getBeanDefinition();
}
/* (non-Javadoc) */
private void parseDynamicRegionFactory(Element element, BeanDefinitionBuilder builder) {
private void parseDynamicRegionFactory(Element element, BeanDefinitionBuilder cacheBuilder) {
Element dynamicRegionFactory = DomUtils.getChildElementByTagName(element, "dynamic-region-factory");
Element dynamicRegionFactory =
DomUtils.getChildElementByTagName(element, "dynamic-region-factory");
if (dynamicRegionFactory != null) {
BeanDefinitionBuilder dynamicRegionSupport = buildDynamicRegionSupport(dynamicRegionFactory);
postProcessDynamicRegionSupport(element, dynamicRegionSupport);
builder.addPropertyValue("dynamicRegionSupport", dynamicRegionSupport.getBeanDefinition());
cacheBuilder.addPropertyValue("dynamicRegionSupport", dynamicRegionSupport.getBeanDefinition());
}
}
/* (non-Javadoc) */
private BeanDefinitionBuilder buildDynamicRegionSupport(Element dynamicRegionFactory) {
if (dynamicRegionFactory != null) {
BeanDefinitionBuilder dynamicRegionSupport = BeanDefinitionBuilder.genericBeanDefinition(
CacheFactoryBean.DynamicRegionSupport.class);
BeanDefinitionBuilder dynamicRegionSupport =
BeanDefinitionBuilder.genericBeanDefinition(CacheFactoryBean.DynamicRegionSupport.class);
String diskDirectory = dynamicRegionFactory.getAttribute("disk-dir");
@@ -211,17 +219,15 @@ class CacheParser extends AbstractSingleBeanDefinitionParser {
/**
* @param dynamicRegionSupport {@link BeanDefinitionBuilder} for &lt;gfe:dynamic-region-factory&gt; element.
*/
protected void postProcessDynamicRegionSupport(Element element, BeanDefinitionBuilder dynamicRegionSupport) {
}
protected void postProcessDynamicRegionSupport(Element element, BeanDefinitionBuilder dynamicRegionSupport) { }
/* (non-Javadoc) */
private void parseJndiBindings(Element element, BeanDefinitionBuilder builder) {
private void parseJndiBindings(Element element, BeanDefinitionBuilder cacheBuilder) {
List<Element> jndiBindings = DomUtils.getChildElementsByTagName(element, "jndi-binding");
if (!CollectionUtils.isEmpty(jndiBindings)) {
ManagedList<Object> jndiDataSources = new ManagedList<Object>(jndiBindings.size());
ManagedList<Object> jndiDataSources = new ManagedList<>(jndiBindings.size());
for (Element jndiBinding : jndiBindings) {
@@ -231,7 +237,7 @@ class CacheParser extends AbstractSingleBeanDefinitionParser {
// NOTE 'jndi-name' and 'type' are required by the XSD so we should have at least 2 attributes.
NamedNodeMap attributes = jndiBinding.getAttributes();
ManagedMap<String, String> jndiAttributes = new ManagedMap<String, String>(attributes.getLength());
ManagedMap<String, String> jndiAttributes = new ManagedMap<>(attributes.getLength());
for (int index = 0, length = attributes.getLength(); index < length; index++) {
Attr attribute = (Attr) attributes.item(index);
@@ -243,9 +249,11 @@ class CacheParser extends AbstractSingleBeanDefinitionParser {
List<Element> jndiProps = DomUtils.getChildElementsByTagName(jndiBinding, "jndi-prop");
if (!CollectionUtils.isEmpty(jndiProps)) {
ManagedList<Object> props = new ManagedList<Object>(jndiProps.size());
ManagedList<Object> props = new ManagedList<>(jndiProps.size());
for (Element jndiProp : jndiProps) {
String key = jndiProp.getAttribute("key");
String type = jndiProp.getAttribute("type");
String value = jndiProp.getTextContent();
@@ -265,7 +273,7 @@ class CacheParser extends AbstractSingleBeanDefinitionParser {
jndiDataSources.add(jndiDataSource.getBeanDefinition());
}
builder.addPropertyValue("jndiDataSources", jndiDataSources);
cacheBuilder.addPropertyValue("jndiDataSources", jndiDataSources);
}
}
@@ -276,11 +284,12 @@ class CacheParser extends AbstractSingleBeanDefinitionParser {
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext)
throws BeanDefinitionStoreException {
String name = super.resolveId(element, definition, parserContext);
String name = Optional.of(super.resolveId(element, definition, parserContext))
.filter(StringUtils::hasText)
.map(StringUtils::trimWhitespace)
.orElse(GemfireConstants.DEFAULT_GEMFIRE_CACHE_NAME);
if (!StringUtils.hasText(name)) {
name = GemfireConstants.DEFAULT_GEMFIRE_CACHE_NAME;
// Set Cache bean alias for backwards compatibility...
if (!"gemfire-cache".equals(name)) {
parserContext.getRegistry().registerAlias(name, "gemfire-cache");
}

View File

@@ -45,14 +45,15 @@ class ClientCacheParser extends CacheParser {
* {@inheritDoc}
*/
@Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
super.doParse(element, parserContext, builder);
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder clientCacheBuilder) {
ParsingUtils.setPropertyValue(element, builder, "durable-client-id");
ParsingUtils.setPropertyValue(element, builder, "durable-client-timeout");
ParsingUtils.setPropertyValue(element, builder, "keep-alive");
ParsingUtils.setPropertyValue(element, builder, "pool-name");
ParsingUtils.setPropertyValue(element, builder, "ready-for-events");
super.doParse(element, parserContext, clientCacheBuilder);
ParsingUtils.setPropertyValue(element, clientCacheBuilder, "durable-client-id");
ParsingUtils.setPropertyValue(element, clientCacheBuilder, "durable-client-timeout");
ParsingUtils.setPropertyValue(element, clientCacheBuilder, "keep-alive");
ParsingUtils.setPropertyValue(element, clientCacheBuilder, "pool-name");
ParsingUtils.setPropertyValue(element, clientCacheBuilder, "ready-for-events");
}
/**

View File

@@ -1,5 +1,9 @@
/*
<<<<<<< Updated upstream
* Copyright 2010-2018 the original author or authors.
=======
* Copyright 2018 the original author or authors.
>>>>>>> Stashed changes
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -78,9 +82,9 @@ class ClientRegionParser extends AbstractRegionParser {
parseDiskStoreAttribute(element, regionBuilder);
// Client RegionAttributes for overflow/eviction, expiration and statistics
BeanDefinitionBuilder regionAttributesBuilder = BeanDefinitionBuilder.genericBeanDefinition(
RegionAttributesFactoryBean.class);
// Client RegionAttributes for Compression, Eviction, Expiration and Statistics
BeanDefinitionBuilder regionAttributesBuilder =
BeanDefinitionBuilder.genericBeanDefinition(RegionAttributesFactoryBean.class);
mergeRegionTemplateAttributes(element, parserContext, regionBuilder, regionAttributesBuilder);
@@ -94,9 +98,10 @@ class ClientRegionParser extends AbstractRegionParser {
List<Element> subElements = DomUtils.getChildElements(element);
ManagedList<Object> interests = new ManagedList<Object>();
ManagedList<Object> interests = new ManagedList<>();
for (Element subElement : subElements) {
String subElementLocalName = subElement.getLocalName();
if ("cache-listener".equals(subElementLocalName)) {
@@ -128,8 +133,8 @@ class ClientRegionParser extends AbstractRegionParser {
}
}
/* (non-Javadoc) */
private void parseDiskStoreAttribute(Element element, BeanDefinitionBuilder builder) {
String diskStoreRefAttribute = element.getAttribute("disk-store-ref");
if (StringUtils.hasText(diskStoreRefAttribute)) {
@@ -138,28 +143,28 @@ class ClientRegionParser extends AbstractRegionParser {
}
}
/* (non-Javadoc) */
private void parseCommonInterestAttributes(Element element, BeanDefinitionBuilder builder) {
ParsingUtils.setPropertyValue(element, builder, "durable", "durable");
ParsingUtils.setPropertyValue(element, builder, "receive-values", "receiveValues");
ParsingUtils.setPropertyValue(element, builder, "result-policy", "policy");
}
/* (non-Javadoc) */
private Object parseKeyInterest(Element keyInterestElement, ParserContext parserContext) {
BeanDefinitionBuilder keyInterestBuilder = BeanDefinitionBuilder.genericBeanDefinition(KeyInterest.class);
keyInterestBuilder.addConstructorArgValue(ParsingUtils.parseRefOrNestedBeanDeclaration(keyInterestElement,
parserContext,
keyInterestBuilder, "key-ref"));
keyInterestBuilder.addConstructorArgValue(
ParsingUtils.parseRefOrNestedBeanDeclaration(keyInterestElement, parserContext, keyInterestBuilder,
"key-ref"));
parseCommonInterestAttributes(keyInterestElement, keyInterestBuilder);
return keyInterestBuilder.getBeanDefinition();
}
/* (non-Javadoc) */
private Object parseRegexInterest(Element regexInterestElement) {
BeanDefinitionBuilder regexInterestBuilder = BeanDefinitionBuilder.genericBeanDefinition(RegexInterest.class);
regexInterestBuilder.addConstructorArgValue(regexInterestElement.getAttribute("pattern"));

View File

@@ -39,7 +39,9 @@ class GemfireDataNamespaceHandler extends NamespaceHandlerSupport {
*/
@Override
public void init() {
RepositoryConfigurationExtension extension = new GemfireRepositoryConfigurationExtension();
registerBeanDefinitionParser("datasource", new GemfireDataSourceParser());
registerBeanDefinitionParser("function-executions", new FunctionExecutionBeanDefinitionParser());
registerBeanDefinitionParser("json-region-autoproxy", new GemfireRegionAutoProxyParser());

View File

@@ -13,8 +13,8 @@
package org.springframework.data.gemfire.config.xml;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
@@ -40,17 +40,35 @@ class GemfireDataSourceParser extends AbstractBeanDefinitionParser {
static final String SUBSCRIPTION_ENABLED_ATTRIBUTE_NAME = "subscription-enabled";
static final String SUBSCRIPTION_ENABLED_PROPERTY_NAME = "subscriptionEnabled";
protected final Log log = LogFactory.getLog(getClass());
protected final Logger logger = LoggerFactory.getLogger(getClass());
/**
* {@inheritDoc}
*/
@Override
protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
parseAndRegisterClientCache(element, parserContext);
parseAndRegisterPool(element, parserContext);
registerGemFireDataSourcePostProcessor(parserContext);
return null;
}
private void parseAndRegisterClientCache(Element element, ParserContext parserContext) {
BeanDefinition clientCacheDefinition = new ClientCacheParser().parse(element, parserContext);
parserContext.getRegistry().registerBeanDefinition(GemfireConstants.DEFAULT_GEMFIRE_CACHE_NAME,
clientCacheDefinition);
parserContext.getRegistry()
.registerBeanDefinition(GemfireConstants.DEFAULT_GEMFIRE_CACHE_NAME, clientCacheDefinition);
if (logger.isDebugEnabled()) {
logger.debug(String.format("Registered GemFire ClientCache bean [%1$s] of type [%2$s]%n",
GemfireConstants.DEFAULT_GEMFIRE_CACHE_NAME, clientCacheDefinition.getBeanClassName()));
}
}
private void parseAndRegisterPool(Element element, ParserContext parserContext) {
BeanDefinition poolDefinition = new PoolParser().parse(element, parserContext);
@@ -61,19 +79,15 @@ class GemfireDataSourceParser extends AbstractBeanDefinitionParser {
}
parserContext.getRegistry().registerBeanDefinition(GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME, poolDefinition);
}
if (log.isDebugEnabled()) {
log.debug(String.format("Registered GemFire ClientCache bean [%1$s] of type [%2$s]%n",
GemfireConstants.DEFAULT_GEMFIRE_CACHE_NAME, clientCacheDefinition.getBeanClassName()));
}
private void registerGemFireDataSourcePostProcessor(ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(
GemfireDataSourcePostProcessor.class);
BeanDefinitionBuilder builder =
BeanDefinitionBuilder.genericBeanDefinition(GemfireDataSourcePostProcessor.class);
builder.addConstructorArgReference(GemfireConstants.DEFAULT_GEMFIRE_CACHE_NAME);
BeanDefinitionReaderUtils.registerWithGeneratedName(builder.getBeanDefinition(), parserContext.getRegistry());
return null;
}
}

View File

@@ -18,8 +18,6 @@ package org.springframework.data.gemfire.config.xml;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.geode.cache.LossAction;
import org.apache.geode.cache.MembershipAttributes;
import org.apache.geode.cache.ResumptionAction;
@@ -32,6 +30,7 @@ import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.core.Conventions;
import org.springframework.data.gemfire.GemfireUtils;
import org.springframework.data.gemfire.SubscriptionAttributesFactoryBean;
import org.springframework.data.gemfire.config.support.GemfireFeature;
import org.springframework.data.gemfire.eviction.EvictionAttributesFactoryBean;
import org.springframework.data.gemfire.expiration.ExpirationAttributesFactoryBean;
import org.springframework.data.gemfire.util.SpringUtils;
@@ -58,15 +57,13 @@ import org.w3c.dom.Element;
*/
abstract class ParsingUtils {
private static final Log log = LogFactory.getLog(ParsingUtils.class);
protected static final String CACHE_PROPERTY_NAME = "cache";
protected static final String REGION_PROPERTY_NAME = "region";
protected static final String CACHE_REF_ATTRIBUTE_NAME = "cache-ref";
protected static final String REGION_REF_ATTRIBUTE_NAME = "region-ref";
static void setPropertyReference(Element element, BeanDefinitionBuilder builder, String attributeName,
String propertyName) {
String propertyName) {
String attributeValue = element.getAttribute(attributeName);
@@ -81,7 +78,7 @@ abstract class ParsingUtils {
}
static void setPropertyValue(Element element, BeanDefinitionBuilder builder, String attributeName,
String propertyName, Object defaultValue) {
String propertyName, Object defaultValue) {
String attributeValue = element.getAttribute(attributeName);
@@ -94,7 +91,8 @@ abstract class ParsingUtils {
}
static void setPropertyValue(Element element, BeanDefinitionBuilder builder, String attributeName,
String propertyName) {
String propertyName) {
setPropertyValue(element, builder, attributeName, propertyName, null);
}
@@ -103,7 +101,7 @@ abstract class ParsingUtils {
}
static void setPropertyValue(BeanDefinitionBuilder builder, BeanDefinition source, String propertyName,
boolean withDependsOn) {
boolean withDependsOn) {
PropertyValue propertyValue = source.getPropertyValues().getPropertyValue(propertyName);
@@ -129,7 +127,7 @@ abstract class ParsingUtils {
if (!DomUtils.getChildElements(element).isEmpty()) {
parserContext.getReaderContext().error(String.format(
"Use either the '%1$s' attribute or a nested bean declaration for '%2$s' element, but not both.",
refAttributeName, element.getLocalName()), element);
refAttributeName, element.getLocalName()), element);
}
returnValue = new RuntimeBeanReference(refAttributeValue);
@@ -139,7 +137,7 @@ abstract class ParsingUtils {
}
static Object parseRefOrNestedCustomElement(Element element, ParserContext parserContext,
BeanDefinitionBuilder builder) {
BeanDefinitionBuilder builder) {
Object beanRef = ParsingUtils.getBeanReference(element, parserContext, "bean");
@@ -166,31 +164,31 @@ abstract class ParsingUtils {
* @return Bean reference or nested Bean definition.
*/
static Object parseRefOrNestedBeanDeclaration(Element element, ParserContext parserContext,
BeanDefinitionBuilder builder) {
BeanDefinitionBuilder builder) {
return parseRefOrNestedBeanDeclaration(element, parserContext, builder, "ref", false);
}
static Object parseRefOrNestedBeanDeclaration(Element element, ParserContext parserContext,
BeanDefinitionBuilder builder, String refAttributeName) {
BeanDefinitionBuilder builder, String refAttributeName) {
return parseRefOrNestedBeanDeclaration(element, parserContext, builder, refAttributeName, false);
}
static Object parseRefOrSingleNestedBeanDeclaration(Element element, ParserContext parserContext,
BeanDefinitionBuilder builder) {
BeanDefinitionBuilder builder) {
return parseRefOrNestedBeanDeclaration(element, parserContext, builder, "ref", true);
}
static Object parseRefOrSingleNestedBeanDeclaration(Element element, ParserContext parserContext,
BeanDefinitionBuilder builder, String refAttributeName) {
BeanDefinitionBuilder builder, String refAttributeName) {
return parseRefOrNestedBeanDeclaration(element, parserContext, builder, refAttributeName, true);
}
static Object parseRefOrNestedBeanDeclaration(Element element, ParserContext parserContext,
BeanDefinitionBuilder builder, String refAttributeName, boolean single) {
BeanDefinitionBuilder builder, String refAttributeName, boolean single) {
Object beanReference = getBeanReference(element, parserContext, refAttributeName);
@@ -211,7 +209,7 @@ abstract class ParsingUtils {
if (single) {
parserContext.getReaderContext().error(String.format(
"The element '%1$s' does not support multiple nested bean definitions.",
element.getLocalName()), element);
element.getLocalName()), element);
}
}
@@ -233,7 +231,7 @@ abstract class ParsingUtils {
* @return true if parsing actually occurred, false otherwise.
*/
static boolean parseEviction(Element element, ParserContext parserContext,
BeanDefinitionBuilder regionAttributesBuilder) {
BeanDefinitionBuilder regionAttributesBuilder) {
Element evictionElement = DomUtils.getChildElementByTagName(element, "eviction");
@@ -259,7 +257,7 @@ abstract class ParsingUtils {
return true;
}
return false;
return false;
}
/**
@@ -336,7 +334,7 @@ abstract class ParsingUtils {
@SuppressWarnings("unused")
static void parseOptionalRegionAttributes(Element element, ParserContext parserContext,
BeanDefinitionBuilder regionAttributesBuilder) {
BeanDefinitionBuilder regionAttributesBuilder) {
setPropertyValue(element, regionAttributesBuilder, "cloning-enabled");
setPropertyValue(element, regionAttributesBuilder, "concurrency-level");
@@ -357,18 +355,13 @@ abstract class ParsingUtils {
String concurrencyChecksEnabled = element.getAttribute("concurrency-checks-enabled");
if (StringUtils.hasText(concurrencyChecksEnabled)) {
if (GemfireUtils.isGemfireVersion7OrAbove()) {
ParsingUtils.setPropertyValue(element, regionAttributesBuilder, "concurrency-checks-enabled");
}
else {
log.warn("Setting 'concurrency-checks-enabled' is only available in Gemfire 7.0 or above!");
}
ParsingUtils.setPropertyValue(element, regionAttributesBuilder, "concurrency-checks-enabled");
}
}
@SuppressWarnings({ "deprecation", "unused" })
static void parseMembershipAttributes(Element element, ParserContext parserContext,
BeanDefinitionBuilder regionAttributesBuilder) {
BeanDefinitionBuilder regionAttributesBuilder) {
Element membershipAttributes = DomUtils.getChildElementByTagName(element, "membership-attributes");
@@ -393,17 +386,6 @@ abstract class ParsingUtils {
}
}
static void throwExceptionIfNotGemfireV7(String elementName, String attributeName, ParserContext parserContext) {
if (!GemfireUtils.isGemfireVersion7OrAbove()) {
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.",
messagePrefix, GemfireUtils.GEMFIRE_VERSION), null);
}
}
static void parseScope(Element element, BeanDefinitionBuilder builder) {
String scopeAttributeValue = element.getAttribute("scope");
@@ -413,7 +395,7 @@ abstract class ParsingUtils {
}
private static boolean parseExpiration(Element rootElement, String elementName, String propertyName,
BeanDefinitionBuilder regionAttributesBuilder) {
BeanDefinitionBuilder regionAttributesBuilder) {
Element expirationElement = DomUtils.getChildElementByTagName(rootElement, elementName);
@@ -432,7 +414,7 @@ abstract class ParsingUtils {
}
private static boolean parseCustomExpiration(Element rootElement, ParserContext parserContext, String elementName,
String propertyName, BeanDefinitionBuilder regionAttributesBuilder) {
String propertyName, BeanDefinitionBuilder regionAttributesBuilder) {
Element expirationElement = DomUtils.getChildElementByTagName(rootElement, elementName);
@@ -449,7 +431,7 @@ abstract class ParsingUtils {
}
static void parseCompressor(Element element, ParserContext parserContext,
BeanDefinitionBuilder regionAttributesBuilder) {
BeanDefinitionBuilder regionAttributesBuilder) {
Element compressorElement = DomUtils.getChildElementByTagName(element, "compressor");
@@ -459,6 +441,14 @@ 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);
}
}
static void setCacheReference(Element element, BeanDefinitionBuilder builder) {
builder.addPropertyReference(CACHE_PROPERTY_NAME, resolveCacheReference(element));
}
@@ -478,4 +468,17 @@ abstract class ParsingUtils {
static String resolveRegionReference(Element element) {
return element.getAttribute(REGION_REF_ATTRIBUTE_NAME);
}
static void throwExceptionWhenGemFireFeatureUnavailable(GemfireFeature feature,
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.",
messagePrefix, GemfireUtils.GEMFIRE_VERSION), null);
}
}
}

View File

@@ -66,17 +66,22 @@ class PoolParser extends AbstractSingleBeanDefinitionParser {
static final String SERVER_ELEMENT_NAME = "server";
static final String SERVERS_ATTRIBUTE_NAME = "servers";
/* (non-Javadoc) */
private static void registerInfrastructureComponents(ParserContext parserContext) {
if (INFRASTRUCTURE_COMPONENTS_REGISTERED.compareAndSet(false, true)) {
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder
.rootBeanDefinition(ClientRegionPoolBeanFactoryPostProcessor.class)
// Be careful to not to register this infrastructure component (just yet; requires more thought)
/*
BeanDefinitionReaderUtils.registerWithGeneratedName(
BeanDefinitionBuilder.rootBeanDefinition(ClientCachePoolBeanFactoryPostProcessor.class)
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE)
.getBeanDefinition();
.getBeanDefinition(), parserContext.getRegistry());
*/
BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, parserContext.getRegistry());
BeanDefinitionReaderUtils.registerWithGeneratedName(
BeanDefinitionBuilder.rootBeanDefinition(ClientRegionPoolBeanFactoryPostProcessor.class)
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE)
.getBeanDefinition(), parserContext.getRegistry());
}
}
@@ -92,30 +97,33 @@ class PoolParser extends AbstractSingleBeanDefinitionParser {
* {@inheritDoc}
*/
@Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder poolBuilder) {
registerInfrastructureComponents(parserContext);
ParsingUtils.setPropertyValue(element, builder, "free-connection-timeout");
ParsingUtils.setPropertyValue(element, builder, "idle-timeout");
ParsingUtils.setPropertyValue(element, builder, "keep-alive");
ParsingUtils.setPropertyValue(element, builder, "load-conditioning-interval");
ParsingUtils.setPropertyValue(element, builder, "max-connections");
ParsingUtils.setPropertyValue(element, builder, "min-connections");
ParsingUtils.setPropertyValue(element, builder, "multi-user-authentication");
ParsingUtils.setPropertyValue(element, builder, "ping-interval");
ParsingUtils.setPropertyValue(element, builder, "pr-single-hop-enabled");
ParsingUtils.setPropertyValue(element, builder, "read-timeout");
ParsingUtils.setPropertyValue(element, builder, "retry-attempts");
ParsingUtils.setPropertyValue(element, builder, "server-group");
ParsingUtils.setPropertyValue(element, builder, "socket-buffer-size");
ParsingUtils.setPropertyValue(element, builder, "socket-connect-timeout");
ParsingUtils.setPropertyValue(element, builder, "statistic-interval");
ParsingUtils.setPropertyValue(element, builder, "subscription-ack-interval");
ParsingUtils.setPropertyValue(element, builder, "subscription-enabled");
ParsingUtils.setPropertyValue(element, builder, "subscription-message-tracking-timeout");
ParsingUtils.setPropertyValue(element, builder, "subscription-redundancy");
ParsingUtils.setPropertyValue(element, builder, "thread-local-connections");
// Be careful not to enable this dependency
//poolBuilder.addDependsOn(GemfireConstants.DEFAULT_GEMFIRE_CACHE_NAME);
ParsingUtils.setPropertyValue(element, poolBuilder, "free-connection-timeout");
ParsingUtils.setPropertyValue(element, poolBuilder, "idle-timeout");
ParsingUtils.setPropertyValue(element, poolBuilder, "keep-alive");
ParsingUtils.setPropertyValue(element, poolBuilder, "load-conditioning-interval");
ParsingUtils.setPropertyValue(element, poolBuilder, "max-connections");
ParsingUtils.setPropertyValue(element, poolBuilder, "min-connections");
ParsingUtils.setPropertyValue(element, poolBuilder, "multi-user-authentication");
ParsingUtils.setPropertyValue(element, poolBuilder, "ping-interval");
ParsingUtils.setPropertyValue(element, poolBuilder, "pr-single-hop-enabled");
ParsingUtils.setPropertyValue(element, poolBuilder, "read-timeout");
ParsingUtils.setPropertyValue(element, poolBuilder, "retry-attempts");
ParsingUtils.setPropertyValue(element, poolBuilder, "server-group");
ParsingUtils.setPropertyValue(element, poolBuilder, "socket-buffer-size");
ParsingUtils.setPropertyValue(element, poolBuilder, "socket-connect-timeout");
ParsingUtils.setPropertyValue(element, poolBuilder, "statistic-interval");
ParsingUtils.setPropertyValue(element, poolBuilder, "subscription-ack-interval");
ParsingUtils.setPropertyValue(element, poolBuilder, "subscription-enabled");
ParsingUtils.setPropertyValue(element, poolBuilder, "subscription-message-tracking-timeout");
ParsingUtils.setPropertyValue(element, poolBuilder, "subscription-redundancy");
ParsingUtils.setPropertyValue(element, poolBuilder, "thread-local-connections");
List<Element> childElements = DomUtils.getChildElements(element);
@@ -137,8 +145,8 @@ class PoolParser extends AbstractSingleBeanDefinitionParser {
BeanDefinitionRegistry registry = resolveRegistry(parserContext);
boolean locatorsSet = parseLocators(element, builder, registry);
boolean serversSet = parseServers(element, builder, registry);
boolean locatorsSet = parseLocators(element, poolBuilder, registry);
boolean serversSet = parseServers(element, poolBuilder, registry);
// If neither Locators nor Servers were explicitly configured, then setup a connection to a CacheServer
// running on localhost, listening on the default CacheServer port, 40404
@@ -147,20 +155,18 @@ class PoolParser extends AbstractSingleBeanDefinitionParser {
}
if (!locators.isEmpty()) {
builder.addPropertyValue("locators", locators);
poolBuilder.addPropertyValue("locators", locators);
}
if (!servers.isEmpty()) {
builder.addPropertyValue("servers", servers);
poolBuilder.addPropertyValue("servers", servers);
}
}
/* (non-Javadoc) */
BeanDefinitionRegistry resolveRegistry(ParserContext parserContext) {
return parserContext.getRegistry();
}
/* (non-Javadoc) */
BeanDefinition buildConnection(String host, String port, boolean server) {
BeanDefinitionBuilder connectionEndpointBuilder =
@@ -172,7 +178,6 @@ class PoolParser extends AbstractSingleBeanDefinitionParser {
return connectionEndpointBuilder.getBeanDefinition();
}
/* (non-Javadoc) */
BeanDefinition buildConnections(String expression, boolean server) {
BeanDefinitionBuilder connectionEndpointListBuilder =
@@ -185,27 +190,23 @@ class PoolParser extends AbstractSingleBeanDefinitionParser {
return connectionEndpointListBuilder.getBeanDefinition();
}
/* (non-Javadoc) */
String defaultHost(String host) {
return (StringUtils.hasText(host) ? host : DEFAULT_HOST);
}
/* (non-Javadoc) */
String defaultPort(String port, boolean server) {
return (StringUtils.hasText(port) ? port
: (server ? String.valueOf(DEFAULT_SERVER_PORT) : String.valueOf(DEFAULT_LOCATOR_PORT)));
}
/* (non-Javadoc) */
BeanDefinition parseLocator(Element element) {
return buildConnection(element.getAttribute(HOST_ATTRIBUTE_NAME),
element.getAttribute(PORT_ATTRIBUTE_NAME), false);
}
/* (non-Javadoc) */
boolean parseLocators(Element element, BeanDefinitionBuilder poolBuilder, BeanDefinitionRegistry registry) {
String locatorsAttributeValue = element.getAttribute(LOCATORS_ATTRIBUTE_NAME);
@@ -232,14 +233,12 @@ class PoolParser extends AbstractSingleBeanDefinitionParser {
return false;
}
/* (non-Javadoc) */
BeanDefinition parseServer(Element element) {
return buildConnection(element.getAttribute(HOST_ATTRIBUTE_NAME),
element.getAttribute(PORT_ATTRIBUTE_NAME), true);
}
/* (non-Javadoc) */
boolean parseServers(Element element, BeanDefinitionBuilder poolBuilder, BeanDefinitionRegistry registry) {
String serversAttributeValue = element.getAttribute(SERVERS_ATTRIBUTE_NAME);
@@ -266,19 +265,16 @@ class PoolParser extends AbstractSingleBeanDefinitionParser {
return false;
}
/* (non-Javadoc) */
String resolveId(Element element) {
return Optional.ofNullable(element.getAttribute(ID_ATTRIBUTE)).filter(StringUtils::hasText)
.orElse(GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME);
}
/* (non-Javadoc) */
String resolveDereferencedId(Element element) {
return SpringUtils.dereferenceBean(resolveId(element));
}
/* (non-Javadoc) */
@Override
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext)
throws BeanDefinitionStoreException {

View File

@@ -1,5 +1,9 @@
/*
<<<<<<< Updated upstream
* Copyright 2002-2018 the original author or authors.
=======
* Copyright 2002-2013 the original author or authors.
>>>>>>> Stashed changes
*
* 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
@@ -34,37 +38,32 @@ abstract class AbstractFunctionExecutionBeanDefinitionBuilder {
protected final Log log = LogFactory.getLog(getClass());
/**
*
* @param configuration the configuration values
*/
AbstractFunctionExecutionBeanDefinitionBuilder(FunctionExecutionConfiguration configuration) {
Assert.notNull(configuration);
Assert.notNull(configuration, "FunctionExecutionConfiguration must not be null");
this.configuration = configuration;
}
/**
* Build the bean definition
* @param registry
* @return
*/
BeanDefinition build(BeanDefinitionRegistry registry) {
BeanDefinitionBuilder functionProxyFactoryBeanBuilder = BeanDefinitionBuilder.rootBeanDefinition(
getFunctionProxyFactoryBeanClass());
functionProxyFactoryBeanBuilder.addConstructorArgValue(configuration.getFunctionExecutionInterface());
functionProxyFactoryBeanBuilder.addConstructorArgReference(BeanDefinitionReaderUtils.registerWithGeneratedName(
buildGemfireFunctionOperations(registry), registry));
BeanDefinitionBuilder functionProxyFactoryBeanBuilder =
BeanDefinitionBuilder.rootBeanDefinition(getFunctionProxyFactoryBeanClass());
functionProxyFactoryBeanBuilder.addConstructorArgValue(this.configuration.getFunctionExecutionInterface());
functionProxyFactoryBeanBuilder.addConstructorArgReference(BeanDefinitionReaderUtils
.registerWithGeneratedName(buildGemfireFunctionOperations(registry), registry));
return functionProxyFactoryBeanBuilder.getBeanDefinition();
}
protected AbstractBeanDefinition buildGemfireFunctionOperations(BeanDefinitionRegistry registry) {
BeanDefinitionBuilder functionTemplateBuilder = getGemfireFunctionOperationsBeanDefinitionBuilder(registry);
functionTemplateBuilder.setLazyInit(true);
String resultCollectorReference = (String) configuration.getAttribute("resultCollector");
String resultCollectorReference = (String) this.configuration.getAttribute("resultCollector");
if (StringUtils.hasText(resultCollectorReference)){
functionTemplateBuilder.addPropertyReference("resultCollector", resultCollectorReference);
@@ -73,10 +72,8 @@ abstract class AbstractFunctionExecutionBeanDefinitionBuilder {
return functionTemplateBuilder.getBeanDefinition();
}
/* Subclasses implement to specify the types to uses. */
protected abstract Class<?> getFunctionProxyFactoryBeanClass();
protected abstract BeanDefinitionBuilder getGemfireFunctionOperationsBeanDefinitionBuilder(
BeanDefinitionRegistry registry);
protected abstract BeanDefinitionBuilder getGemfireFunctionOperationsBeanDefinitionBuilder(BeanDefinitionRegistry registry);
}

View File

@@ -1,5 +1,9 @@
/*
<<<<<<< Updated upstream
* Copyright 2002-2018 the original author or authors.
=======
* Copyright 2002-2013 the original author or authors.
>>>>>>> Stashed changes
*
* 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
@@ -12,19 +16,21 @@
*/
package org.springframework.data.gemfire.function.config;
import static org.springframework.data.gemfire.util.CollectionUtils.nullSafeIterable;
import java.lang.annotation.Annotation;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.data.gemfire.function.annotation.OnMember;
import org.springframework.data.gemfire.function.annotation.OnMembers;
import org.springframework.data.gemfire.function.annotation.OnRegion;
@@ -32,68 +38,68 @@ import org.springframework.data.gemfire.function.annotation.OnServer;
import org.springframework.data.gemfire.function.annotation.OnServers;
/**
<<<<<<< Updated upstream
* Annotation based configuration source for function executions
*
* @author David Turanski
=======
* Abstract base class and configuration source for Function Executions.
>>>>>>> Stashed changes
*
* @author David Turanski
* @author John Blum
* @see org.springframework.data.gemfire.function.config.FunctionExecutionConfiguration
*/
abstract class AbstractFunctionExecutionConfigurationSource implements FunctionExecutionConfigurationSource {
private static Set<Class<? extends Annotation>> functionExecutionAnnotationTypes;
static {
Set<Class<? extends Annotation>> annotationTypes = new HashSet<Class<? extends Annotation>>(5);
Set<Class<? extends Annotation>> annotationTypes = new HashSet<>(5);
annotationTypes.add(OnMember.class);
annotationTypes.add(OnMembers.class);
annotationTypes.add(OnRegion.class);
annotationTypes.add(OnServer.class);
annotationTypes.add(OnServers.class);
annotationTypes.add(OnMember.class);
annotationTypes.add(OnMembers.class);
functionExecutionAnnotationTypes = Collections.unmodifiableSet(annotationTypes);
}
protected Log logger = LogFactory.getLog(getClass());
static Set<Class<? extends Annotation>> getFunctionExecutionAnnotationTypes() {
return functionExecutionAnnotationTypes;
}
static Set<String> getFunctionExecutionAnnotationTypeNames() {
Set<String> functionExecutionTypeNames = new HashSet<String>(getFunctionExecutionAnnotationTypes().size());
for (Class<? extends Annotation> annotationType : getFunctionExecutionAnnotationTypes()) {
functionExecutionTypeNames.add(annotationType.getName());
}
return functionExecutionTypeNames;
return getFunctionExecutionAnnotationTypes().stream().map(Class::getName).collect(Collectors.toSet());
}
protected Log logger = LogFactory.getLog(getClass());
public Collection<ScannedGenericBeanDefinition> getCandidates(ResourceLoader loader) {
ClassPathScanningCandidateComponentProvider scanner = new FunctionExecutionComponentProvider(
getIncludeFilters(), getFunctionExecutionAnnotationTypes());
ClassPathScanningCandidateComponentProvider scanner =
new FunctionExecutionComponentProvider(getIncludeFilters(), getFunctionExecutionAnnotationTypes());
scanner.setResourceLoader(loader);
for (TypeFilter filter : getExcludeFilters()) {
scanner.addExcludeFilter(filter);
}
StreamSupport.stream(nullSafeIterable(getExcludeFilters()).spliterator(), false)
.forEach(scanner::addExcludeFilter);
Set<ScannedGenericBeanDefinition> result = new HashSet<ScannedGenericBeanDefinition>();
Set<ScannedGenericBeanDefinition> result = new HashSet<>();
for (String basePackage : getBasePackages()) {
if (logger.isDebugEnabled()) {
logger.debug("scanning package " + basePackage);
}
Collection<BeanDefinition> candidateComponents = scanner.findCandidateComponents(basePackage);
for (BeanDefinition beanDefinition : candidateComponents) {
result.add((ScannedGenericBeanDefinition) beanDefinition);
}
scanner.findCandidateComponents(basePackage).stream()
.map(beanDefinition -> (ScannedGenericBeanDefinition) beanDefinition)
.forEach(result::add);
}
return result;
}
}

View File

@@ -1,5 +1,9 @@
/*
<<<<<<< Updated upstream
* Copyright 2002-2018 the original author or authors.
=======
* Copyright 2002-2013 the original author or authors.
>>>>>>> Stashed changes
*
* 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
@@ -37,6 +41,7 @@ import org.springframework.data.gemfire.function.annotation.OnServers;
abstract class FunctionExecutionBeanDefinitionBuilderFactory {
static AbstractFunctionExecutionBeanDefinitionBuilder newInstance(FunctionExecutionConfiguration configuration) {
String functionExecutionAnnotation = configuration.getAnnotationType();
if (OnMember.class.getName().equals(functionExecutionAnnotation)) {
@@ -57,5 +62,4 @@ abstract class FunctionExecutionBeanDefinitionBuilderFactory {
return null;
}
}

View File

@@ -1,5 +1,9 @@
/*
<<<<<<< Updated upstream
* Copyright 2002-2018 the original author or authors.
=======
* Copyright 2002-2013 the original author or authors.
>>>>>>> Stashed changes
*
* 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
@@ -18,28 +22,24 @@ import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;
/**
* Parse for &lt;function-executions&gt; definitions.
* Parser for a &lt;function-executions&gt; bean definition.
*
* @author David Turanski
* @author John Blum
* @see org.springframework.beans.factory.config.BeanDefinition
* @see org.springframework.beans.factory.xml.BeanDefinitionParser
* @see org.springframework.beans.factory.xml.ParserContext
* @see org.w3c.dom.Element
*/
public class FunctionExecutionBeanDefinitionParser implements BeanDefinitionParser {
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.xml.BeanDefinitionParser#parse(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext)
*/
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
AbstractFunctionExecutionConfigurationSource configurationSource = new XmlFunctionExecutionConfigurationSource(
element, parserContext);
new FunctionExecutionBeanDefinitionRegistrar().registerBeanDefinitions(configurationSource, parserContext.getRegistry());
new FunctionExecutionBeanDefinitionRegistrar().registerBeanDefinitions(element, parserContext);
return null;
}
}

View File

@@ -1,5 +1,9 @@
/*
<<<<<<< Updated upstream
* Copyright 2002-2018 the original author or authors.
=======
* Copyright 2002-2013 the original author or authors.
>>>>>>> Stashed changes
*
* 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
@@ -10,59 +14,81 @@
* 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.function.config;
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalStateException;
import java.util.Optional;
import java.util.Set;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
/**
* {@link ImportBeanDefinitionRegistrar} for {code} @EnableGemfireFunctionExecutions {code}
* Scans for interfaces annotated with one of {code} @OnRegion, @OnServer, @OnServers, @OnMember, @OnMembers {code}
* @author David Turanski
*
* @author David Turanski
* @author John Blum
*/
class FunctionExecutionBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
/* (non-Javadoc)
* @see org.springframework.context.annotation.ImportBeanDefinitionRegistrar#registerBeanDefinitions(org.springframework.core.type.AnnotationMetadata, org.springframework.beans.factory.support.BeanDefinitionRegistry)
/*
* (non-Javadoc)
* @see org.springframework.context.annotation.ImportBeanDefinitionRegistrar
* #registerBeanDefinitions(org.springframework.core.type.AnnotationMetadata, org.springframework.beans.factory.support.BeanDefinitionRegistry)
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry registry) {
AbstractFunctionExecutionConfigurationSource configurationSource = new AnnotationFunctionExecutionConfigurationSource(
annotationMetadata);
AbstractFunctionExecutionConfigurationSource configurationSource =
new AnnotationFunctionExecutionConfigurationSource(annotationMetadata);
registerBeanDefinitions(configurationSource, registry);
}
/*
* This registers bean definitions from any function execution configuration source
void registerBeanDefinitions(Element element, ParserContext parserContext) {
AbstractFunctionExecutionConfigurationSource configurationSource =
new XmlFunctionExecutionConfigurationSource(element, parserContext);
registerBeanDefinitions(configurationSource, parserContext.getRegistry());
}
/**
* Registers bean definitions from any {@link FunctionExecutionConfigurationSource}.
*/
void registerBeanDefinitions(AbstractFunctionExecutionConfigurationSource functionExecutionConfigurationSource,
BeanDefinitionRegistry registry) {
for (ScannedGenericBeanDefinition beanDefinition : functionExecutionConfigurationSource.getCandidates(
new DefaultResourceLoader())) {
Set<String> functionExecutionAnnotationTypeNames =
AbstractFunctionExecutionConfigurationSource.getFunctionExecutionAnnotationTypeNames();
String functionExecutionAnnotation = getFunctionExecutionAnnotation(beanDefinition,
AnnotationFunctionExecutionConfigurationSource.getFunctionExecutionAnnotationTypeNames());
for (ScannedGenericBeanDefinition beanDefinition : functionExecutionConfigurationSource
.getCandidates(new DefaultResourceLoader())) {
Assert.notNull(functionExecutionAnnotation);
String functionExecutionAnnotation =
Optional.ofNullable(getFunctionExecutionAnnotation(beanDefinition, functionExecutionAnnotationTypeNames))
.orElseThrow(() -> newIllegalStateException(String.format("No Function Execution Annotation [%1$s] found for type [%2$s]",
functionExecutionAnnotationTypeNames, beanDefinition.getBeanClassName())));
String beanName = (String) beanDefinition.getMetadata().getAnnotationAttributes(
functionExecutionAnnotation).get("id");
if (!StringUtils.hasText(beanName)) {
beanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, registry);
}
String beanName = Optional.of(beanDefinition.getMetadata())
.map(annotationMetadata -> annotationMetadata.getAnnotationAttributes(functionExecutionAnnotation))
.map(AnnotationAttributes::fromMap)
.map(annotationAttributes -> annotationAttributes.getString("id"))
.filter(StringUtils::hasText)
.orElseGet(() -> BeanDefinitionReaderUtils.generateBeanName(beanDefinition, registry));
AbstractFunctionExecutionBeanDefinitionBuilder builder = FunctionExecutionBeanDefinitionBuilderFactory
.newInstance(new FunctionExecutionConfiguration(beanDefinition, functionExecutionAnnotation));
@@ -74,20 +100,19 @@ class FunctionExecutionBeanDefinitionRegistrar implements ImportBeanDefinitionRe
private String getFunctionExecutionAnnotation(ScannedGenericBeanDefinition beanDefinition,
Set<String> functionExecutionAnnotationTypeNames) {
Set<String> annotationTypes = beanDefinition.getMetadata().getAnnotationTypes();
String existingFunctionExecutionAnnotation = null;
String functionExecutionAnnotation = null;
for (String annotationType : annotationTypes) {
for (String annotationType : beanDefinition.getMetadata().getAnnotationTypes()) {
if (functionExecutionAnnotationTypeNames.contains(annotationType)) {
Assert.isNull(functionExecutionAnnotation, String.format(
"interface %1$s contains multiple Function Execution Annotations: %2$s, %3$s",
beanDefinition.getBeanClassName(), functionExecutionAnnotation, annotationType));
functionExecutionAnnotation = annotationType;
Assert.isNull(existingFunctionExecutionAnnotation,
String.format("interface [%1$s] contains multiple Function Execution Annotations: %2$s, %3$s",
beanDefinition.getBeanClassName(), existingFunctionExecutionAnnotation, annotationType));
existingFunctionExecutionAnnotation = annotationType;
}
}
return functionExecutionAnnotation;
return existingFunctionExecutionAnnotation;
}
}

View File

@@ -1,5 +1,9 @@
/*
<<<<<<< Updated upstream
* Copyright 2002-2018 the original author or authors.
=======
* Copyright 2002-2013 the original author or authors.
>>>>>>> Stashed changes
*
* 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
@@ -15,6 +19,7 @@ package org.springframework.data.gemfire.function.config;
import java.util.Map;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.data.gemfire.util.SpringUtils;
import org.springframework.util.Assert;
/**
@@ -27,29 +32,29 @@ class FunctionExecutionConfiguration {
private Class<?> functionExecutionInterface;
private final Map<String,Object> attributes;
private final Map<String, Object> annotationAttributes;
private final String annotationType;
/* constructor for testing purposes only! */
FunctionExecutionConfiguration() {
this.annotationType = null;
this.attributes = null;
this.annotationAttributes = null;
}
FunctionExecutionConfiguration(ScannedGenericBeanDefinition beanDefinition, String annotationType) {
try {
this.annotationType = annotationType;
this.attributes = beanDefinition.getMetadata().getAnnotationAttributes(annotationType, true);
this.annotationAttributes = beanDefinition.getMetadata().getAnnotationAttributes(annotationType, true);
this.functionExecutionInterface = beanDefinition.resolveBeanClass(beanDefinition.getClass().getClassLoader());
Assert.isTrue(functionExecutionInterface.isInterface(),
String.format("The annotation %1$s only applies to an interface. It is not valid for the type %2$s",
annotationType, functionExecutionInterface.getName()));
Assert.isTrue(this.functionExecutionInterface != null && this.functionExecutionInterface.isInterface(),
String.format("The annotation %1$s only applies to an interface. It is not valid for type %2$s",
annotationType, SpringUtils.nullSafeName(this.functionExecutionInterface)));
}
catch (ClassNotFoundException e) {
throw new RuntimeException(e);
catch (ClassNotFoundException cause) {
throw new RuntimeException(cause);
}
}
@@ -58,15 +63,14 @@ class FunctionExecutionConfiguration {
}
Object getAttribute(String name) {
return attributes.get(name);
return this.annotationAttributes.get(name);
}
Map<String, Object> getAttributes() {
return this.attributes;
return this.annotationAttributes;
}
Class<?> getFunctionExecutionInterface() {
return this.functionExecutionInterface;
}
}

View File

@@ -1,5 +1,9 @@
/*
<<<<<<< Updated upstream
* Copyright 2002-2018 the original author or authors.
=======
* Copyright 2002-2013 the original author or authors.
>>>>>>> Stashed changes
*
* 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
@@ -12,23 +16,25 @@
*/
package org.springframework.data.gemfire.function.config;
import java.lang.annotation.Annotation;
import org.springframework.core.type.filter.TypeFilter;
/**
<<<<<<< Updated upstream
* Interface for function execution configuration sources (e.g., annotation or XML configuration) to configure
* classpath scanning of annotated interfaces to implement proxies that invoke Gemfire functions
*
* @author David Turanski
=======
* Interface for Function Execution configuration sources (e.g. {@link Annotation} or XML configuration)
* to configure classpath scanning of annotated interfaces to implement proxies that invoke Functions.
>>>>>>> Stashed changes
*
* @author David Turanski
* @author John Blum
*/
interface FunctionExecutionConfigurationSource {
/**
* Returns the actual source object that the configuration originated from. Will be used by the tooling to give visual
* feedback on where the repository instances actually come from.
*
* @return must not be {@literal null}.
*/
Object getSource();
/**
* Returns the base packages the repository interfaces shall be found under.
@@ -37,7 +43,6 @@ interface FunctionExecutionConfigurationSource {
*/
Iterable<String> getBasePackages();
/**
* Returns configured {@link TypeFilter}s
* @return include filters
@@ -50,4 +55,12 @@ interface FunctionExecutionConfigurationSource {
*/
Iterable<TypeFilter> getExcludeFilters();
/**
* Returns the actual source object that the configuration originated from. Will be used by the tooling to give visual
* feedback on where the repository instances actually come from.
*
* @return must not be {@literal null}.
*/
Object getSource();
}

View File

@@ -1,5 +1,9 @@
/*
<<<<<<< Updated upstream
* Copyright 2002-2018 the original author or authors.
=======
* Copyright 2002-2013 the original author or authors.
>>>>>>> Stashed changes
*
* 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
@@ -19,36 +23,36 @@ import org.springframework.data.gemfire.function.execution.OnRegionFunctionProxy
/**
* @author David Turanski
*
* @author John Blum
*/
class OnRegionExecutionBeanDefinitionBuilder extends AbstractFunctionExecutionBeanDefinitionBuilder {
/**
* @param configuration
*/
OnRegionExecutionBeanDefinitionBuilder(FunctionExecutionConfiguration configuration) {
super(configuration);
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.gemfire.function.config.AbstractFunctionExecutionBeanDefinitionBuilder#getGemfireFunctionOperationsBeanDefinitionBuilder(org.springframework.beans.factory.support.BeanDefinitionRegistry)
*/
@Override
protected BeanDefinitionBuilder getGemfireFunctionOperationsBeanDefinitionBuilder(BeanDefinitionRegistry registry) {
BeanDefinitionBuilder functionTemplateBuilder = BeanDefinitionBuilder.genericBeanDefinition(GemfireOnRegionFunctionTemplate.class);
functionTemplateBuilder.addConstructorArgReference((String)configuration.getAttribute("region"));
BeanDefinitionBuilder functionTemplateBuilder =
BeanDefinitionBuilder.genericBeanDefinition(GemfireOnRegionFunctionTemplate.class);
functionTemplateBuilder.addConstructorArgReference((String) this.configuration.getAttribute("region"));
return functionTemplateBuilder;
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.gemfire.function.config.AbstractFunctionExecutionBeanDefinitionBuilder#getFunctionProxyFactoryBeanClass()
*/
@Override
protected Class<?> getFunctionProxyFactoryBeanClass() {
return OnRegionFunctionProxyFactoryBean.class;
}
}

View File

@@ -15,9 +15,12 @@
*/
package org.springframework.data.gemfire.function.config;
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalArgumentException;
import java.lang.annotation.Annotation;
import java.util.Collection;
import java.util.HashSet;
import java.util.Optional;
import java.util.regex.Pattern;
import org.springframework.beans.BeanUtils;
@@ -25,6 +28,7 @@ import org.springframework.beans.FatalBeanException;
import org.springframework.beans.factory.parsing.ReaderContext;
import org.springframework.beans.factory.xml.XmlReaderContext;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.core.type.filter.AspectJTypeFilter;
import org.springframework.core.type.filter.AssignableTypeFilter;
@@ -36,26 +40,37 @@ import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
<<<<<<< Updated upstream
* Parser to populate the given {@link ClassPathScanningCandidateComponentProvider} with {@link TypeFilter}s parsed from
* the given {@link Element}'s children.
=======
* Parser to populate the given {@link ClassPathScanningCandidateComponentProvider} with {@link TypeFilter}s
* parsed from the given {@link Element}'s children.
>>>>>>> Stashed changes
*
* @author Oliver Gierke
*/
class TypeFilterParser {
private static final String FILTER_TYPE_ATTRIBUTE = "type";
private static final String FILTER_EXPRESSION_ATTRIBUTE = "expression";
private static final String FILTER_TYPE_ATTRIBUTE = "type";
private final ClassLoader classLoader;
private final ReaderContext readerContext;
private final ClassLoader classLoader;
/**
* Creates a new {@link TypeFilterParser} with the given {@link ReaderContext}.
*
* @param readerContext must not be {@literal null}.
* @see org.springframework.beans.factory.xml.XmlReaderContext
*/
public TypeFilterParser(XmlReaderContext readerContext) {
this(readerContext, readerContext.getResourceLoader().getClassLoader());
this(readerContext, Optional.ofNullable(readerContext)
.map(XmlReaderContext::getResourceLoader)
.map(ResourceLoader::getClassLoader)
.orElseGet(() -> Thread.currentThread().getContextClassLoader()));
}
/**
@@ -76,20 +91,21 @@ class TypeFilterParser {
public Iterable<TypeFilter> parseTypeFilters(Element element, Type type) {
Collection<TypeFilter> filters = new HashSet<>();
NodeList nodeList = element.getChildNodes();
Collection<TypeFilter> filters = new HashSet<TypeFilter>();
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
Element childElement = type.getElement(node);
Element childElement = type.getElement(nodeList.item(i));
if (childElement != null) {
try {
filters.add(createTypeFilter(childElement, classLoader));
} catch (RuntimeException e) {
readerContext.error(e.getMessage(), readerContext.extractSource(element), e.getCause());
filters.add(createTypeFilter(childElement, this.classLoader));
}
catch (RuntimeException cause) {
this.readerContext.error(cause.getMessage(), this.readerContext.extractSource(element),
cause.getCause());
}
}
}
@@ -99,16 +115,17 @@ class TypeFilterParser {
protected TypeFilter createTypeFilter(Element element, ClassLoader classLoader) {
String filterType = element.getAttribute(FILTER_TYPE_ATTRIBUTE);
String expression = element.getAttribute(FILTER_EXPRESSION_ATTRIBUTE);
String filterType = element.getAttribute(FILTER_TYPE_ATTRIBUTE);
try {
FilterType filter = FilterType.fromString(filterType);
return filter.getFilter(expression, classLoader);
} catch (ClassNotFoundException ex) {
throw new FatalBeanException("Type filter class not found: " + expression, ex);
} catch (ClassNotFoundException cause) {
throw new FatalBeanException("TypeFilter class not found: " + expression, cause);
}
}
@@ -119,109 +136,105 @@ class TypeFilterParser {
* @author Oliver Gierke
* @see #getFilter(String, ClassLoader)
*/
private static enum FilterType {
private enum FilterType {
ANNOTATION {
@Override
@SuppressWarnings("unchecked")
public TypeFilter getFilter(String expression, ClassLoader classLoader) throws ClassNotFoundException {
return new AnnotationTypeFilter((Class<Annotation>) classLoader.loadClass(expression));
}
},
ASSIGNABLE {
@Override
public TypeFilter getFilter(String expression, ClassLoader classLoader) throws ClassNotFoundException {
return new AssignableTypeFilter(classLoader.loadClass(expression));
}
},
ASPECTJ {
@Override
public TypeFilter getFilter(String expression, ClassLoader classLoader) {
return new AspectJTypeFilter(expression, classLoader);
}
},
REGEX {
@Override
public TypeFilter getFilter(String expression, ClassLoader classLoader) {
return new RegexPatternTypeFilter(Pattern.compile(expression));
}
},
CUSTOM {
@Override
public TypeFilter getFilter(String expression, ClassLoader classLoader) throws ClassNotFoundException {
Class<?> filterClass = classLoader.loadClass(expression);
if (!TypeFilter.class.isAssignableFrom(filterClass)) {
throw new IllegalArgumentException("Class is not assignable to [" + TypeFilter.class.getName() + "]: "
+ expression);
throw newIllegalArgumentException("Class is not assignable to [%s]: %s",
TypeFilter.class.getName(), expression);
}
return (TypeFilter) BeanUtils.instantiateClass(filterClass);
}
};
/**
* Returns the {@link TypeFilter} for the given expression and {@link ClassLoader}.
*
* @param expression
* @param classLoader
* @return
* @throws ClassNotFoundException
*/
abstract TypeFilter getFilter(String expression, ClassLoader classLoader) throws ClassNotFoundException;
/**
* Returns the {@link FilterType} for the given type as {@link String}.
*
* @param typeString
* @return
* @param type {@link String} containing the name of the type.
* @return {@link FilterType} for the given {@link String type name}.
* @throws IllegalArgumentException if no {@link FilterType} could be found for the given argument.
*/
static FilterType fromString(String typeString) {
static FilterType fromString(String type) {
for (FilterType filter : FilterType.values()) {
if (filter.name().equalsIgnoreCase(typeString)) {
if (filter.name().equalsIgnoreCase(type)) {
return filter;
}
}
throw new IllegalArgumentException("Unsupported filter type: " + typeString);
throw new IllegalArgumentException("Unsupported filter type: " + type);
}
}
static enum Type {
enum Type {
INCLUDE("include-filter"), EXCLUDE("exclude-filter");
INCLUDE("include-filter"),
EXCLUDE("exclude-filter");
private String elementName;
private Type(String elementName) {
private final String elementName;
Type(String elementName) {
this.elementName = elementName;
}
/**
* Returns the {@link Element} if the given {@link Node} is an {@link Element} and it's name equals the one of the
* type.
*
* @param node
* @return
* Returns the {@link Element} if the given {@link Node} is an {@link Element} and it's name equals
* the one of the type.
*/
Element getElement(Node node) {
if (node.getNodeType() == Node.ELEMENT_NODE) {
String localName = node.getLocalName();
if (elementName.equals(localName)) {
if (this.elementName.equals(localName)) {
return (Element) node;
}
}

View File

@@ -1,5 +1,9 @@
/*
<<<<<<< Updated upstream
* Copyright 2002-2018 the original author or authors.
=======
* Copyright 2002-2013 the original author or authors.
>>>>>>> Stashed changes
*
* 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
@@ -26,20 +30,26 @@ import org.w3c.dom.Element;
*
*/
class XmlFunctionExecutionConfigurationSource extends AbstractFunctionExecutionConfigurationSource {
private static final String BASE_PACKAGE = "base-package";
private Element element;
private ParserContext context;
private Iterable<TypeFilter> includeFilters;
private Iterable<TypeFilter> excludeFilters;
XmlFunctionExecutionConfigurationSource(Element element, ParserContext context) {
Assert.notNull(element);
Assert.notNull(context);
private static final String BASE_PACKAGE = "base-package";
private final Element element;
private final Iterable<TypeFilter> includeFilters;
private final Iterable<TypeFilter> excludeFilters;
private final ParserContext parserContext;
XmlFunctionExecutionConfigurationSource(Element element, ParserContext parserContext) {
Assert.notNull(element, "Element must not be null");
Assert.notNull(parserContext, "ParserContext must not be null");
this.element = element;
this.context = context;
this.parserContext = parserContext;
TypeFilterParser parser = new TypeFilterParser(parserContext.getReaderContext());
TypeFilterParser parser = new TypeFilterParser(context.getReaderContext());
this.includeFilters = parser.parseTypeFilters(element, Type.INCLUDE);
this.excludeFilters = parser.parseTypeFilters(element, Type.EXCLUDE);
}
@@ -49,7 +59,7 @@ class XmlFunctionExecutionConfigurationSource extends AbstractFunctionExecutionC
*/
@Override
public Object getSource() {
return context.extractSource(element);
return this.parserContext.extractSource(this.element);
}
/* (non-Javadoc)
@@ -57,7 +67,9 @@ class XmlFunctionExecutionConfigurationSource extends AbstractFunctionExecutionC
*/
@Override
public Iterable<String> getBasePackages() {
String attribute = element.getAttribute(BASE_PACKAGE);
String attribute = this.element.getAttribute(BASE_PACKAGE);
return Arrays.asList(StringUtils.delimitedListToStringArray(attribute, ",", " "));
}
@@ -67,7 +79,7 @@ class XmlFunctionExecutionConfigurationSource extends AbstractFunctionExecutionC
*/
@Override
public Iterable<TypeFilter> getIncludeFilters() {
return includeFilters;
return this.includeFilters;
}
/* (non-Javadoc)
@@ -75,7 +87,6 @@ class XmlFunctionExecutionConfigurationSource extends AbstractFunctionExecutionC
*/
@Override
public Iterable<TypeFilter> getExcludeFilters() {
return excludeFilters;
return this.excludeFilters;
}
}

View File

@@ -12,7 +12,7 @@
*/
package org.springframework.data.gemfire.function.execution;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@@ -25,7 +25,6 @@ import org.apache.geode.cache.execute.FunctionException;
import org.apache.geode.cache.execute.FunctionService;
import org.apache.geode.cache.execute.ResultCollector;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* Base class for * Creating a GemFire {@link Execution} using {@link FunctionService}. Protected setters support
@@ -51,14 +50,18 @@ abstract class AbstractFunctionExecution {
private String functionId;
public AbstractFunctionExecution(Function function, Object... args) {
Assert.notNull(function, "function cannot be null");
Assert.notNull(function, "Function cannot be null");
this.function = function;
this.functionId = function.getId();
this.args = args;
}
public AbstractFunctionExecution(String functionId, Object... args) {
Assert.isTrue(StringUtils.hasLength(functionId), "functionId cannot be null or empty");
Assert.hasText(functionId, "FunctionId cannot be null or empty");
this.functionId = functionId;
this.args = args;
}
@@ -67,23 +70,23 @@ abstract class AbstractFunctionExecution {
}
Object[] getArgs() {
return args;
return this.args;
}
ResultCollector<?, ?> getCollector() {
return resultCollector;
return this.resultCollector;
}
Function getFunction() {
return function;
return this.function;
}
String getFunctionId() {
return functionId;
return this.functionId;
}
long getTimeout() {
return timeout;
return this.timeout;
}
<T> Iterable<T> execute() {
@@ -92,21 +95,22 @@ abstract class AbstractFunctionExecution {
@SuppressWarnings("unchecked")
<T> Iterable<T> execute(Boolean returnResult) {
Execution execution = getExecution();
execution = execution.withArgs(getArgs());
execution = (getCollector() == null ? execution : execution.withCollector(getCollector()));
execution = (getKeys() == null ? execution : execution.withFilter(getKeys()));
execution = execution.setArguments(getArgs());
execution = getCollector() != null ? execution.withCollector(getCollector()) : execution;
execution = getKeys() != null ? execution.withFilter(getKeys()) : execution;
ResultCollector<?, ?> resultCollector;
if (isRegisteredFunction()) {
resultCollector = execution.execute(functionId);
resultCollector = execution.execute(this.functionId);
}
else {
resultCollector = execution.execute(function);
resultCollector = execution.execute(this.function);
if (!function.hasResult()) {
if (!this.function.hasResult()) {
return null;
}
}
@@ -116,7 +120,7 @@ abstract class AbstractFunctionExecution {
}
if (logger.isDebugEnabled()) {
logger.debug("using ResultsCollector " + resultCollector.getClass().getName());
logger.debug("Using ResultsCollector " + resultCollector.getClass().getName());
}
Iterable<T> results = null;
@@ -126,11 +130,8 @@ abstract class AbstractFunctionExecution {
try {
results = (Iterable<T>) resultCollector.getResult(this.timeout, TimeUnit.MILLISECONDS);
}
catch (FunctionException e) {
throw new RuntimeException(e);
}
catch (InterruptedException e) {
throw new RuntimeException(e);
catch (FunctionException | InterruptedException cause) {
throw new RuntimeException(cause);
}
}
else {
@@ -139,10 +140,10 @@ abstract class AbstractFunctionExecution {
return replaceSingletonNullCollectionWithEmptyList(results);
}
catch (FunctionException e) {
//TODO Come up with a better way to determine that the function should not return a result;
if (!e.getMessage().equals(NO_RESULT_MESSAGE)) {
throw e;
catch (FunctionException cause) {
// TODO Come up with a better way to determine that the function should not return a result;
if (!cause.getMessage().equals(NO_RESULT_MESSAGE)) {
throw cause;
}
}
@@ -151,6 +152,7 @@ abstract class AbstractFunctionExecution {
@SuppressWarnings("unchecked")
<T> T executeAndExtract() {
Iterable<T> results = execute();
if (results == null || !results.iterator().hasNext()) {
@@ -160,9 +162,9 @@ abstract class AbstractFunctionExecution {
Object result = results.iterator().next();
if (result instanceof Throwable) {
throw new FunctionException(String.format("Execution of Function %1$s failed",
(function != null ? function.getClass().getName() : String.format("with ID '%1$s'", functionId))),
(Throwable) result);
throw new FunctionException(String.format("Execution of Function %s failed",
(this.function != null ? this.function.getClass().getName()
: String.format("with ID [%s]", this.functionId))), (Throwable) result);
}
return (T) result;
@@ -200,11 +202,13 @@ abstract class AbstractFunctionExecution {
}
private boolean isRegisteredFunction() {
return function == null;
return this.function == null;
}
private <T> Iterable<T> replaceSingletonNullCollectionWithEmptyList(Iterable<T> results) {
if (results != null) {
Iterator<T> it = results.iterator();
if (!it.hasNext()) {
@@ -212,11 +216,10 @@ abstract class AbstractFunctionExecution {
}
if (it.next() == null && !it.hasNext()) {
return new ArrayList<T>();
return Collections.emptyList();
}
}
return results;
}
}

View File

@@ -1,5 +1,9 @@
/*
<<<<<<< Updated upstream
* Copyright 2002-2018 the original author or authors.
=======
* Copyright 2002-2013 the original author or authors.
>>>>>>> Stashed changes
*
* 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
@@ -35,7 +39,7 @@ import org.springframework.util.ClassUtils;
* @see org.springframework.beans.factory.BeanClassLoaderAware
* @see org.springframework.beans.factory.FactoryBean
*/
public class GemfireFunctionProxyFactoryBean implements FactoryBean<Object>, MethodInterceptor, BeanClassLoaderAware {
public class GemfireFunctionProxyFactoryBean implements BeanClassLoaderAware, FactoryBean<Object>, MethodInterceptor {
private volatile ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
@@ -56,6 +60,7 @@ public class GemfireFunctionProxyFactoryBean implements FactoryBean<Object>, Met
* @param gemfireFunctionOperations an interface used to delegate the function invocation (typically a GemFire function template)
*/
public GemfireFunctionProxyFactoryBean(Class<?> functionExecutionInterface, GemfireFunctionOperations gemfireFunctionOperations) {
Assert.notNull(functionExecutionInterface, "'functionExecutionInterface' must not be null");
Assert.isTrue(functionExecutionInterface.isInterface(), "'functionExecutionInterface' must be an interface");
@@ -65,16 +70,17 @@ public class GemfireFunctionProxyFactoryBean implements FactoryBean<Object>, Met
}
protected GemfireFunctionOperations getGemfireFunctionOperations() {
return gemfireFunctionOperations;
return this.gemfireFunctionOperations;
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
beanClassLoader = classLoader;
this.beanClassLoader = classLoader;
}
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
if (AopUtils.isToStringMethod(invocation.getMethod())) {
return "GemFire Function Proxy for service interface [" + this.functionExecutionInterface + "]";
}
@@ -88,17 +94,18 @@ public class GemfireFunctionProxyFactoryBean implements FactoryBean<Object>, Met
protected Object invokeFunction(Method method, Object[] args) {
return this.gemfireFunctionOperations.executeAndExtract(
methodMetadata.getMethodMetadata(method).getFunctionId(), args);
this.methodMetadata.getMethodMetadata(method).getFunctionId(), args);
}
@Override
public Object getObject() throws Exception {
if (functionExecutionProxy == null) {
if (this.functionExecutionProxy == null) {
onInit();
Assert.notNull(functionExecutionProxy, "failed to initialize proxy");
Assert.notNull(this.functionExecutionProxy, "failed to initialize proxy");
}
return functionExecutionProxy;
return this.functionExecutionProxy;
}
@Override
@@ -112,11 +119,13 @@ public class GemfireFunctionProxyFactoryBean implements FactoryBean<Object>, Met
}
protected void onInit() {
if (!initialized) {
ProxyFactory proxyFactory = new ProxyFactory(functionExecutionInterface, this);
functionExecutionProxy = proxyFactory.getProxy(beanClassLoader);
initialized = true;
if (!this.initialized) {
ProxyFactory proxyFactory = new ProxyFactory(this.functionExecutionInterface, this);
this.functionExecutionProxy = proxyFactory.getProxy(this.beanClassLoader);
this.initialized = true;
}
}
}

View File

@@ -20,11 +20,11 @@ import org.springframework.util.Assert;
/**
* @author David Turanski
*
* @author John Blum
*/
public class GemfireOnRegionFunctionTemplate extends AbstractFunctionTemplate implements GemfireOnRegionOperations {
private Region<?, ?> region;
private final Region<?, ?> region;
/**
* Constructs an instance of the GemFireOnRegionFunctionTemplate with the given GemFire Cache Region.
@@ -33,37 +33,52 @@ public class GemfireOnRegionFunctionTemplate extends AbstractFunctionTemplate im
* @see org.apache.geode.cache.Region
*/
public GemfireOnRegionFunctionTemplate(Region<?, ?> region) {
Assert.notNull(region, "Region cannot be null");
Assert.notNull(region, "Region must not be null");
this.region = region;
}
@Override
public <T> Iterable<T> execute(Function function, Set<?> keys, Object... args) {
return execute(new RegionFunctionExecution(region).setKeys(keys).setFunction(function).setTimeout(timeout)
.setArgs(args));
}
@Override
public <T> Iterable<T> execute(String functionId, Set<?> keys, Object... args) {
return execute(new RegionFunctionExecution(region).setKeys(keys).setFunctionId(functionId).setTimeout(timeout)
.setArgs(args));
}
@Override
public <T> T executeAndextract(String functionId, Set<?> keys, Object... args) {
return this.<T> executeAndExtract(new RegionFunctionExecution(region).setKeys(keys).setFunctionId(functionId)
.setTimeout(timeout).setArgs(args));
}
@Override
protected AbstractFunctionExecution getFunctionExecution() {
protected RegionFunctionExecution getFunctionExecution() {
return new RegionFunctionExecution(this.region);
}
@Override
public void executeWithNoResult(String functionId, Set<?> keys, Object... args) {
execute(new RegionFunctionExecution(region).setKeys(keys).setFunctionId(functionId).setTimeout(timeout)
.setArgs(args), false);
public <T> Iterable<T> execute(Function function, Set<?> keys, Object... args) {
return execute(getFunctionExecution()
.setKeys(keys)
.setFunction(function)
.setTimeout(this.timeout)
.setArgs(args));
}
@Override
public <T> Iterable<T> execute(String functionId, Set<?> keys, Object... args) {
return execute(getFunctionExecution()
.setKeys(keys).setFunctionId(functionId)
.setTimeout(this.timeout)
.setArgs(args));
}
@Override
public <T> T executeAndextract(String functionId, Set<?> keys, Object... args) {
return executeAndExtract(getFunctionExecution()
.setKeys(keys)
.setFunctionId(functionId)
.setTimeout(this.timeout).setArgs(args));
}
@Override
public void executeWithNoResult(String functionId, Set<?> keys, Object... args) {
execute(getFunctionExecution()
.setKeys(keys)
.setFunctionId(functionId)
.setTimeout(this.timeout)
.setArgs(args), false);
}
}

View File

@@ -1,5 +1,9 @@
/*
<<<<<<< Updated upstream
* Copyright 2002-2018 the original author or authors.
=======
* Copyright 2002-2013 the original author or authors.
>>>>>>> Stashed changes
*
* 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
@@ -23,38 +27,41 @@ import org.springframework.data.gemfire.util.ArrayUtils;
*/
public class OnRegionFunctionProxyFactoryBean extends GemfireFunctionProxyFactoryBean {
private OnRegionExecutionMethodMetadata methodMetadata;
private final OnRegionExecutionMethodMetadata methodMetadata;
/**
* @param serviceInterface the Service class interface specifying the operations to proxy.
* @param gemfireOnRegionOperations an {@link GemfireOnRegionOperations} instance
*/
public OnRegionFunctionProxyFactoryBean(Class<?> serviceInterface, GemfireOnRegionOperations gemfireOnRegionOperations) {
public OnRegionFunctionProxyFactoryBean(Class<?> serviceInterface,
GemfireOnRegionOperations gemfireOnRegionOperations) {
super(serviceInterface, gemfireOnRegionOperations);
methodMetadata = new OnRegionExecutionMethodMetadata(serviceInterface);
this.methodMetadata = new OnRegionExecutionMethodMetadata(serviceInterface);
}
@Override
protected Iterable<?> invokeFunction(Method method, Object[] args) {
GemfireOnRegionOperations gemfireOnRegionOperations = (GemfireOnRegionOperations) getGemfireFunctionOperations();
OnRegionMethodMetadata onRegionMethodMetadata = methodMetadata.getMethodMetadata(method);
GemfireOnRegionOperations gemfireOnRegionOperations =
(GemfireOnRegionOperations) getGemfireFunctionOperations();
OnRegionMethodMetadata onRegionMethodMetadata = this.methodMetadata.getMethodMetadata(method);
int filterArgPosition = onRegionMethodMetadata.getFilterArgPosition();
String functionId = onRegionMethodMetadata.getFunctionId();
Set<?> filter = null;
/*
* extract filter from args if necessary
*/
// extract filter from args if necessary
if (filterArgPosition >= 0) {
filter = (Set<?>) args[filterArgPosition];
args = ArrayUtils.remove(args, filterArgPosition);
}
return (filter == null ? gemfireOnRegionOperations.execute(functionId, args)
: gemfireOnRegionOperations.execute(functionId, filter, args));
return filter != null ? gemfireOnRegionOperations.execute(functionId, filter, args)
: gemfireOnRegionOperations.execute(functionId, args);
}
}

View File

@@ -26,12 +26,11 @@ import org.springframework.util.CollectionUtils;
*/
class RegionFunctionExecution extends AbstractFunctionExecution {
private final Region<?, ?> region;
private volatile Set<?> keys;
public RegionFunctionExecution(Region<?, ?> region) {
super();
this.region = region;
}
@@ -48,11 +47,17 @@ class RegionFunctionExecution extends AbstractFunctionExecution {
* @see org.springframework.data.gemfire.function.FunctionExecution#getExecution()
*/
@Override
@SuppressWarnings("unchecked")
protected Execution getExecution() {
Execution execution = FunctionService.onRegion(region);
if (!CollectionUtils.isEmpty(this.keys) ) {
Execution execution = FunctionService.onRegion(this.region);
Set<?> keys = getKeys();
if (!CollectionUtils.isEmpty(keys) ) {
execution = execution.withFilter(keys);
}
return execution;
}
}

View File

@@ -25,6 +25,7 @@ import org.apache.geode.cache.CacheFactory;
import org.apache.geode.cache.GemFireCache;
import org.apache.geode.cache.client.ClientCache;
import org.apache.geode.cache.client.ClientCacheFactory;
import org.apache.geode.cache.client.Pool;
import org.apache.geode.distributed.DistributedSystem;
import org.apache.geode.internal.cache.GemFireCacheImpl;
import org.springframework.util.StringUtils;
@@ -50,7 +51,6 @@ public abstract class CacheUtils extends DistributedSystemUtils {
public static final String DEFAULT_POOL_NAME = "DEFAULT";
/* (non-Javadoc) */
@SuppressWarnings("all")
public static boolean isClient(GemFireCache cache) {
@@ -63,10 +63,25 @@ public abstract class CacheUtils extends DistributedSystemUtils {
return client;
}
/* (non-Javadoc) */
public static boolean isDefaultPool(Pool pool) {
return Optional.ofNullable(pool).map(Pool::getName).filter(CacheUtils::isDefaultPool).isPresent();
}
public static boolean isNotDefaultPool(Pool pool) {
return !isDefaultPool(pool);
}
public static boolean isDefaultPool(String poolName) {
return DEFAULT_POOL_NAME.equals(poolName);
}
public static boolean isNotDefaultPool(String poolName) {
return !isDefaultPool(poolName);
}
public static boolean isDurable(ClientCache clientCache) {
// NOTE technically the following code snippet would be more useful/valuable but is not "testable"!
// NOTE: Technically, the following code snippet would be more useful/valuable but is not "testable"!
//((InternalDistributedSystem) distributedSystem).getConfig().getDurableClientId();
return Optional.ofNullable(clientCache)
@@ -78,7 +93,6 @@ public abstract class CacheUtils extends DistributedSystemUtils {
.isPresent();
}
/* (non-Javadoc) */
@SuppressWarnings("all")
public static boolean isPeer(GemFireCache cache) {
@@ -91,17 +105,14 @@ public abstract class CacheUtils extends DistributedSystemUtils {
return peer;
}
/* (non-Javadoc) */
public static boolean close() {
return close(resolveGemFireCache());
}
/* (non-Javadoc) */
public static boolean close(GemFireCache gemfireCache) {
return close(gemfireCache, () -> {});
}
/* (non-Javadoc) */
public static boolean close(GemFireCache gemfireCache, Runnable shutdownHook) {
try {
@@ -116,7 +127,6 @@ public abstract class CacheUtils extends DistributedSystemUtils {
}
}
/* (non-Javadoc) */
public static boolean closeCache() {
try {
@@ -128,7 +138,6 @@ public abstract class CacheUtils extends DistributedSystemUtils {
}
}
/* (non-Javadoc) */
public static boolean closeClientCache() {
try {
@@ -140,7 +149,6 @@ public abstract class CacheUtils extends DistributedSystemUtils {
}
}
/* (non-Javadoc) */
public static Cache getCache() {
try {
@@ -151,7 +159,6 @@ public abstract class CacheUtils extends DistributedSystemUtils {
}
}
/* (non-Javadoc) */
public static ClientCache getClientCache() {
try {
@@ -162,7 +169,6 @@ public abstract class CacheUtils extends DistributedSystemUtils {
}
}
/* (non-Javadoc) */
public static GemFireCache resolveGemFireCache() {
return Optional.<GemFireCache>ofNullable(getClientCache()).orElseGet(CacheUtils::getCache);
}

View File

@@ -18,10 +18,14 @@ package org.springframework.data.gemfire.util;
import java.util.Optional;
import org.apache.geode.cache.DataPolicy;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.RegionAttributes;
import org.apache.geode.cache.client.ClientRegionShortcut;
import org.springframework.data.gemfire.client.ClientRegionShortcutWrapper;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
@@ -35,6 +39,53 @@ import org.springframework.util.StringUtils;
@SuppressWarnings("unused")
public abstract class RegionUtils extends CacheUtils {
/**
* Assert that the configuration settings for {@link ClientRegionShortcut} and the {@literal persistent} attribute
* in &lt;gfe:*-region&gt; elements are compatible.
*
* @param resolvedShortcut {@link ClientRegionShortcut} resolved from the SDG XML namespace.
* @param persistent boolean indicating the value of the {@literal persistent} configuration attribute.
* @see org.springframework.data.gemfire.client.ClientRegionShortcutWrapper
* @see org.apache.geode.cache.client.ClientRegionShortcut
*/
public static void assertClientRegionShortcutAndPersistentAttributeAreCompatible(
ClientRegionShortcut resolvedShortcut, Boolean persistent) {
boolean persistentUnspecified = persistent == null;
if (ClientRegionShortcutWrapper.valueOf(resolvedShortcut).isPersistent()) {
Assert.isTrue(persistentUnspecified || Boolean.TRUE.equals(persistent),
String.format("Client Region Shortcut [%s] is not valid when persistent is false", resolvedShortcut));
}
else {
Assert.isTrue(persistentUnspecified || Boolean.FALSE.equals(persistent),
String.format("Client Region Shortcut [%s] is not valid when persistent is true", resolvedShortcut));
}
}
/**
* Assert that the configuration settings for {@link DataPolicy} and the {@literal persistent} attribute
* in &lt;gfe:*-region&gt; elements are compatible.
*
* @param resolvedDataPolicy {@link DataPolicy} resolved from the SDG XML namespace.
* @param persistent boolean indicating the value of the {@literal persistent} configuration attribute.
* @see org.apache.geode.cache.DataPolicy
*/
public static void assertDataPolicyAndPersistentAttributeAreCompatible(
DataPolicy resolvedDataPolicy, Boolean persistent) {
boolean persistentUnspecified = persistent == null;
if (resolvedDataPolicy.withPersistence()) {
Assert.isTrue(persistentUnspecified || Boolean.TRUE.equals(persistent),
String.format("Data Policy [%s] is not valid when persistent is false", resolvedDataPolicy));
}
else {
Assert.isTrue(persistentUnspecified || Boolean.FALSE.equals(persistent),
String.format("Data Policy [%s] is not valid when persistent is true", resolvedDataPolicy));
}
}
public static boolean isClient(Region region) {
return Optional.ofNullable(region)
@@ -44,13 +95,11 @@ public abstract class RegionUtils extends CacheUtils {
.isPresent();
}
/* (non-Javadoc) */
@Nullable
public static String toRegionName(@Nullable Region<?, ?> region) {
return Optional.ofNullable(region).map(Region::getName).orElse(null);
}
/* (non-Javadoc) */
@Nullable
public static String toRegionName(String regionPath) {
@@ -63,13 +112,11 @@ public abstract class RegionUtils extends CacheUtils {
.orElse(regionPath);
}
/* (non-Javadoc) */
@Nullable
public static String toRegionPath(@Nullable Region<?, ?> region) {
return Optional.ofNullable(region).map(Region::getFullPath).orElse(null);
}
/* (non-Javadoc) */
@NonNull
public static String toRegionPath(String regionName) {
return String.format("%1$s%2$s", Region.SEPARATOR, regionName);

View File

@@ -23,7 +23,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Supplier;
@@ -39,10 +38,8 @@ import org.springframework.util.StringUtils;
* @since 1.8.0
*/
@SuppressWarnings("unused")
// TODO rename this utility class using a more descriptive, intuitive and meaningful name
public abstract class SpringUtils {
/* (non-Javadoc) */
public static BeanDefinition addDependsOn(BeanDefinition bean, String... beanNames) {
List<String> dependsOnList = new ArrayList<>();
@@ -54,7 +51,6 @@ public abstract class SpringUtils {
return bean;
}
/* (non-Javadoc) */
public static BeanDefinition setPropertyReference(BeanDefinition beanDefinition,
String propertyName, String beanName) {
@@ -63,7 +59,6 @@ public abstract class SpringUtils {
return beanDefinition;
}
/* (non-Javadoc) */
public static BeanDefinition setPropertyValue(BeanDefinition beanDefinition,
String propertyName, Object propertyValue) {
@@ -72,58 +67,60 @@ public abstract class SpringUtils {
return beanDefinition;
}
/* (non-Javadoc) */
public static String defaultIfEmpty(String value, String defaultValue) {
return (StringUtils.hasText(value) ? value : defaultValue);
return defaultIfEmpty(value, () -> defaultValue);
}
public static String defaultIfEmpty(String value, Supplier<String> supplier) {
return StringUtils.hasText(value) ? value : supplier.get();
}
/* (non-Javadoc) */
public static <T> T defaultIfNull(T value, T defaultValue) {
return Optional.ofNullable(value).orElse(defaultValue);
return defaultIfNull(value, () -> defaultValue);
}
/* (non-Javadoc) */
public static <T> T defaultIfNull(T value, Supplier<T> supplier) {
return Optional.ofNullable(value).orElseGet(supplier);
return value != null ? value : supplier.get();
}
/* (non-Javadoc) */
public static String dereferenceBean(String beanName) {
return String.format("%1$s%2$s", BeanFactory.FACTORY_BEAN_PREFIX, beanName);
}
/* (non-Javadoc) */
public static boolean equalsIgnoreNull(Object obj1, Object obj2) {
return (obj1 == null ? obj2 == null : obj1.equals(obj2));
return obj1 == null ? obj2 == null : obj1.equals(obj2);
}
/* (non-Javadoc) */
public static boolean nullOrEquals(Object obj1, Object obj2) {
return (obj1 == null || obj1.equals(obj2));
return obj1 == null || obj1.equals(obj2);
}
/* (non-Javadoc) */
public static boolean nullSafeEquals(Object obj1, Object obj2) {
return (obj1 != null && obj1.equals(obj2));
return obj1 != null && obj1.equals(obj2);
}
public static String nullSafeName(Class<?> type) {
return type != null ? type.getName() : null;
}
public static String nullSafeSimpleName(Class<?> type) {
return type != null ? type.getSimpleName() : null;
}
/* (non-Javadoc) */
public static <T> T safeGetValue(Supplier<T> valueSupplier) {
return safeGetValue(valueSupplier, (T) null);
}
/* (non-Javadoc) */
public static <T> T safeGetValue(Supplier<T> valueSupplier, T defaultValue) {
return safeGetValue(valueSupplier, (Supplier<T>) () -> defaultValue);
}
/* (non-Javadoc) */
public static <T> T safeGetValue(Supplier<T> valueSupplier, Supplier<T> defaultValueSupplier) {
return safeGetValue(valueSupplier, (Function<Throwable, T>) exception -> defaultValueSupplier.get());
}
/* (non-Javadoc) */
public static <T> T safeGetValue(Supplier<T> valueSupplier, Function<Throwable, T> exceptionHandler) {
try {
return valueSupplier.get();
}