SGF-604 - Add Configurers to enable dynamic configuration in the new SDG Annotation configuration model.
Related JIRA: https://jira.spring.io/browse/SGF-586 Related JIRA: https://jira.spring.io/browse/DATAGEODE-12
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -16,30 +16,44 @@
|
||||
|
||||
package org.springframework.data.gemfire;
|
||||
|
||||
import static java.util.stream.StreamSupport.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.newIllegalStateException;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.geode.cache.DiskStore;
|
||||
import org.apache.geode.cache.DiskStoreFactory;
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.data.gemfire.config.annotation.DiskStoreConfigurer;
|
||||
import org.springframework.data.gemfire.support.AbstractFactoryBeanSupport;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* FactoryBean for creating a GemFire DiskStore.
|
||||
* Spring {@link FactoryBean} used to create {@link DiskStore}.
|
||||
*
|
||||
* @author David Turanski
|
||||
* @author John Blum
|
||||
* @see org.springframework.beans.factory.BeanNameAware
|
||||
* @see org.apache.geode.cache.DiskStore
|
||||
* @see org.apache.geode.cache.DiskStoreFactory
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.springframework.beans.factory.FactoryBean
|
||||
* @see org.springframework.beans.factory.InitializingBean
|
||||
* @see org.springframework.data.gemfire.config.annotation.DiskStoreConfigurer
|
||||
* @see org.springframework.data.gemfire.support.AbstractFactoryBeanSupport
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class DiskStoreFactoryBean implements BeanNameAware , FactoryBean<DiskStore>, InitializingBean {
|
||||
public class DiskStoreFactoryBean extends AbstractFactoryBeanSupport<DiskStore> implements InitializingBean {
|
||||
|
||||
private Boolean allowForceCompaction;
|
||||
private Boolean autoCompact;
|
||||
@@ -57,78 +71,184 @@ public class DiskStoreFactoryBean implements BeanNameAware , FactoryBean<DiskSto
|
||||
private Float diskUsageCriticalPercentage;
|
||||
private Float diskUsageWarningPercentage;
|
||||
|
||||
private List<DiskStoreConfigurer> diskStoreConfigurers = Collections.emptyList();
|
||||
|
||||
private DiskStoreConfigurer compositeDiskStoreConfigurer = (beanName, bean) ->
|
||||
nullSafeCollection(diskStoreConfigurers).forEach(diskStoreConfigurer ->
|
||||
diskStoreConfigurer.configure(beanName, bean));
|
||||
|
||||
private List<DiskDir> diskDirs;
|
||||
|
||||
private String name;
|
||||
|
||||
@Override
|
||||
public DiskStore getObject() throws Exception {
|
||||
return diskStore;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return (diskStore != null ? diskStore.getClass() : DiskStore.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.state(cache != null, String.format("A reference to the GemFire Cache must be set for Disk Store '%1$s'.",
|
||||
getName()));
|
||||
|
||||
DiskStoreFactory diskStoreFactory = cache.createDiskStoreFactory();
|
||||
String diskStoreName = resolveDiskStoreName();
|
||||
|
||||
if (allowForceCompaction != null) {
|
||||
diskStoreFactory.setAllowForceCompaction(allowForceCompaction);
|
||||
}
|
||||
if (autoCompact != null) {
|
||||
diskStoreFactory.setAutoCompact(autoCompact);
|
||||
}
|
||||
if (compactionThreshold != null) {
|
||||
diskStoreFactory.setCompactionThreshold(compactionThreshold);
|
||||
}
|
||||
if (diskUsageCriticalPercentage != null) {
|
||||
diskStoreFactory.setDiskUsageCriticalPercentage(diskUsageCriticalPercentage);
|
||||
}
|
||||
if (diskUsageWarningPercentage != null) {
|
||||
diskStoreFactory.setDiskUsageWarningPercentage(diskUsageWarningPercentage);
|
||||
}
|
||||
if (maxOplogSize != null) {
|
||||
diskStoreFactory.setMaxOplogSize(maxOplogSize);
|
||||
}
|
||||
if (queueSize != null) {
|
||||
diskStoreFactory.setQueueSize(queueSize);
|
||||
}
|
||||
if (timeInterval != null) {
|
||||
diskStoreFactory.setTimeInterval(timeInterval);
|
||||
}
|
||||
if (writeBufferSize != null) {
|
||||
diskStoreFactory.setWriteBufferSize(writeBufferSize);
|
||||
}
|
||||
applyDiskStoreConfigurers(diskStoreName);
|
||||
|
||||
if (!CollectionUtils.isEmpty(diskDirs)) {
|
||||
File[] diskDirFiles = new File[diskDirs.size()];
|
||||
int[] diskDirSizes = new int[diskDirs.size()];
|
||||
GemFireCache cache = resolveCache(diskStoreName);
|
||||
|
||||
for (int index = 0; index < diskDirs.size(); index++) {
|
||||
DiskDir diskDir = diskDirs.get(index);
|
||||
diskDirFiles[index] = new File(diskDir.location);
|
||||
diskDirSizes[index] = (diskDir.maxSize != null ? diskDir.maxSize
|
||||
: DiskStoreFactory.DEFAULT_DISK_DIR_SIZE);
|
||||
}
|
||||
DiskStoreFactory diskStoreFactory = postProcess(configure(createDiskStoreFactory(cache)));
|
||||
|
||||
diskStoreFactory.setDiskDirsAndSizes(diskDirFiles, diskDirSizes);
|
||||
}
|
||||
this.diskStore = postProcess(newDiskStore(diskStoreFactory, diskStoreName));
|
||||
}
|
||||
|
||||
diskStore = diskStoreFactory.create(getName());
|
||||
/* (non-Javadoc) */
|
||||
private void applyDiskStoreConfigurers(String diskStoreName) {
|
||||
applyDiskStoreConfigurers(diskStoreName, getCompositeDiskStoreConfigurer());
|
||||
}
|
||||
|
||||
Assert.notNull(diskStore, String.format("DiskStore with name '%1$s' failed to be created successfully.",
|
||||
diskStore.getName()));
|
||||
/**
|
||||
* Null-safe operation to apply the given array of {@link DiskStoreConfigurer DiskStoreConfigurers}
|
||||
* to this {@link DiskStoreFactoryBean}.
|
||||
*
|
||||
* @param diskStoreName {@link String} containing the name of the {@link DiskStore}.
|
||||
* @param diskStoreConfigurers array of {@link DiskStoreConfigurer DiskStoreConfigurers} applied
|
||||
* to this {@link DiskStoreFactoryBean}.
|
||||
* @see org.springframework.data.gemfire.config.annotation.DiskStoreConfigurer
|
||||
* @see #applyDiskStoreConfigurers(String, Iterable)
|
||||
*/
|
||||
protected void applyDiskStoreConfigurers(String diskStoreName, DiskStoreConfigurer... diskStoreConfigurers) {
|
||||
applyDiskStoreConfigurers(diskStoreName,
|
||||
Arrays.asList(nullSafeArray(diskStoreConfigurers, DiskStoreConfigurer.class)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe operation to apply the given {@link Iterable} of {@link DiskStoreConfigurer DiskStoreConfigurers}
|
||||
* to this {@link DiskStoreFactoryBean}.
|
||||
*
|
||||
* @param diskStoreName {@link String} containing the name of the {@link DiskStore}.
|
||||
* @param diskStoreConfigurers {@link Iterable} of {@link DiskStoreConfigurer DiskStoreConfigurers} applied
|
||||
* to this {@link DiskStoreFactoryBean}.
|
||||
* @see org.springframework.data.gemfire.config.annotation.DiskStoreConfigurer
|
||||
*/
|
||||
protected void applyDiskStoreConfigurers(String diskStoreName, Iterable<DiskStoreConfigurer> diskStoreConfigurers) {
|
||||
stream(nullSafeIterable(diskStoreConfigurers).spliterator(), false)
|
||||
.forEach(diskStoreConfigurer -> diskStoreConfigurer.configure(diskStoreName, this));
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private GemFireCache resolveCache(String diskStoreName) {
|
||||
return Optional.ofNullable(this.cache)
|
||||
.orElseThrow(() -> newIllegalStateException("Cache is required to create DiskStore [%s]", diskStoreName));
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
final String resolveDiskStoreName() {
|
||||
return Optional.ofNullable(getBeanName()).filter(StringUtils::hasText)
|
||||
.orElse(DiskStoreFactory.DEFAULT_DISK_STORE_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of {@link DiskStoreFactory} using the given {@link GemFireCache} in order to
|
||||
* construct, configure and initialize a new {@link DiskStore}.
|
||||
*
|
||||
* @param cache reference to the {@link GemFireCache} used to create the {@link DiskStoreFactory}.
|
||||
* @return a new instance of {@link DiskStoreFactory}.
|
||||
* @see org.apache.geode.cache.GemFireCache#createDiskStoreFactory()
|
||||
* @see org.apache.geode.cache.DiskStoreFactory
|
||||
*/
|
||||
protected DiskStoreFactory createDiskStoreFactory(GemFireCache cache) {
|
||||
return cache.createDiskStoreFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the given {@link DiskStoreFactory} with the configuration settings present
|
||||
* on this {@link DiskStoreFactoryBean}
|
||||
*
|
||||
* @param diskStoreFactory {@link DiskStoreFactory} to configure.
|
||||
* @return the given {@link DiskStoreFactory}
|
||||
* @see org.apache.geode.cache.DiskStoreFactory
|
||||
*/
|
||||
protected DiskStoreFactory configure(DiskStoreFactory diskStoreFactory) {
|
||||
|
||||
Optional.ofNullable(this.allowForceCompaction).ifPresent(diskStoreFactory::setAllowForceCompaction);
|
||||
Optional.ofNullable(this.autoCompact).ifPresent(diskStoreFactory::setAutoCompact);
|
||||
Optional.ofNullable(this.compactionThreshold).ifPresent(diskStoreFactory::setCompactionThreshold);
|
||||
Optional.ofNullable(this.diskUsageCriticalPercentage).ifPresent(diskStoreFactory::setDiskUsageCriticalPercentage);
|
||||
Optional.ofNullable(this.diskUsageWarningPercentage).ifPresent(diskStoreFactory::setDiskUsageWarningPercentage);
|
||||
Optional.ofNullable(this.maxOplogSize).ifPresent(diskStoreFactory::setMaxOplogSize);
|
||||
Optional.ofNullable(this.queueSize).ifPresent(diskStoreFactory::setQueueSize);
|
||||
Optional.ofNullable(this.timeInterval).ifPresent(diskStoreFactory::setTimeInterval);
|
||||
Optional.ofNullable(this.writeBufferSize).ifPresent(diskStoreFactory::setWriteBufferSize);
|
||||
|
||||
Optional.ofNullable(this.diskDirs).filter(diskDirs -> !CollectionUtils.isEmpty(diskDirs))
|
||||
.ifPresent(diskDirs -> {
|
||||
|
||||
File[] diskDirFiles = new File[diskDirs.size()];
|
||||
int[] diskDirSizes = new int[diskDirs.size()];
|
||||
|
||||
for (int index = 0; index < diskDirs.size(); index++) {
|
||||
DiskDir diskDir = diskDirs.get(index);
|
||||
diskDirFiles[index] = new File(diskDir.location);
|
||||
diskDirSizes[index] = Optional.ofNullable(diskDir.maxSize)
|
||||
.orElse(DiskStoreFactory.DEFAULT_DISK_DIR_SIZE);
|
||||
}
|
||||
|
||||
diskStoreFactory.setDiskDirsAndSizes(diskDirFiles, diskDirSizes);
|
||||
});
|
||||
|
||||
return diskStoreFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new instance of {@link DiskStore} with the given {@link String name}
|
||||
* using the provided {@link DiskStoreFactory}
|
||||
*
|
||||
* @param diskStoreFactory {@link DiskStoreFactory} used to create the {@link DiskStore}.
|
||||
* @param diskStoreName {@link String} containing the name of the new {@link DiskStore}.
|
||||
* @return a new instance of {@link DiskStore} with the given {@link String name}.
|
||||
* @see org.apache.geode.cache.DiskStoreFactory
|
||||
* @see org.apache.geode.cache.DiskStore
|
||||
*/
|
||||
protected DiskStore newDiskStore(DiskStoreFactory diskStoreFactory, String diskStoreName) {
|
||||
return diskStoreFactory.create(diskStoreName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Post-process the {@link DiskStoreFactory} with any custom {@link DiskStoreFactory} or {@link DiskStore}
|
||||
* configuration settings as required by the application.
|
||||
*
|
||||
* @param diskStoreFactory {@link DiskStoreFactory} to process.
|
||||
* @return the given {@link DiskStoreFactory}.
|
||||
* @see org.apache.geode.cache.DiskStoreFactory
|
||||
*/
|
||||
protected DiskStoreFactory postProcess(DiskStoreFactory diskStoreFactory) {
|
||||
return diskStoreFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Post-process the provided {@link DiskStore} constructed, configured and initialized
|
||||
* by this {@link DiskStoreFactoryBean}.
|
||||
*
|
||||
* @param diskStore {@link DiskStore} to process.
|
||||
* @return the given {@link DiskStore}.
|
||||
* @see org.apache.geode.cache.DiskStore
|
||||
*/
|
||||
protected DiskStore postProcess(DiskStore diskStore) {
|
||||
return diskStore;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the Composite {@link DiskStoreConfigurer} used to apply additional configuration
|
||||
* to this {@link DiskStoreFactoryBean} on Spring container initialization.
|
||||
*
|
||||
* @return the Composite {@link DiskStoreConfigurer}.
|
||||
* @see org.springframework.data.gemfire.config.annotation.DiskStoreConfigurer
|
||||
*/
|
||||
protected DiskStoreConfigurer getCompositeDiskStoreConfigurer() {
|
||||
return this.compositeDiskStoreConfigurer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DiskStore getObject() throws Exception {
|
||||
return this.diskStore;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Class<?> getObjectType() {
|
||||
return Optional.ofNullable(this.diskStore).map(DiskStore::getClass).orElse((Class) DiskStore.class);
|
||||
}
|
||||
|
||||
public void setCache(GemFireCache cache) {
|
||||
@@ -143,26 +263,47 @@ public class DiskStoreFactoryBean implements BeanNameAware , FactoryBean<DiskSto
|
||||
this.autoCompact = autoCompact;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setCompactionThreshold(Integer compactionThreshold) {
|
||||
validateCompactionThreshold(compactionThreshold);
|
||||
this.compactionThreshold = compactionThreshold;
|
||||
}
|
||||
|
||||
protected void validateCompactionThreshold(final Integer compactionThreshold) {
|
||||
protected void validateCompactionThreshold(Integer compactionThreshold) {
|
||||
Assert.isTrue(compactionThreshold == null || (compactionThreshold >= 0 && compactionThreshold <= 100),
|
||||
String.format("The DiskStore's (%1$s) compaction threshold (%2$d) must be an integer value between 0 and 100 inclusive.",
|
||||
this.name, compactionThreshold));
|
||||
resolveDiskStoreName(), compactionThreshold));
|
||||
}
|
||||
|
||||
public void setDiskDirs(List<DiskDir> diskDirs) {
|
||||
this.diskDirs = diskDirs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe operation to set an array of {@link DiskStoreConfigurer DiskStoreConfigurers} used to
|
||||
* apply additional configuration to this {@link DiskStoreFactoryBean} when using Annotation-based configuration.
|
||||
*
|
||||
* @param diskStoreConfigurers array of {@link DiskStoreConfigurer DiskStoreConfigurers} used to apply
|
||||
* additional configuration to this {@link DiskStoreFactoryBean}.
|
||||
* @see org.springframework.data.gemfire.config.annotation.DiskStoreConfigurer
|
||||
* @see #setDiskStoreConfigurers(List)
|
||||
*/
|
||||
public void setDiskStoreConfigurers(DiskStoreConfigurer... diskStoreConfigurers) {
|
||||
setDiskStoreConfigurers(Arrays.asList(nullSafeArray(diskStoreConfigurers, DiskStoreConfigurer.class)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe operation to set an {@link Iterable} of {@link DiskStoreConfigurer DiskStoreConfigurers}
|
||||
* used to apply additional configuration to this {@link DiskStoreFactoryBean}
|
||||
* when using Annotation-based configuration.
|
||||
*
|
||||
* @param diskStoreConfigurers {@link Iterable } of {@link DiskStoreConfigurer DiskStoreConfigurers} used to
|
||||
* apply additional configuration to this {@link DiskStoreFactoryBean}.
|
||||
* @see org.springframework.data.gemfire.config.annotation.DiskStoreConfigurer
|
||||
*/
|
||||
public void setDiskStoreConfigurers(List<DiskStoreConfigurer> diskStoreConfigurers) {
|
||||
this.diskStoreConfigurers = Optional.ofNullable(diskStoreConfigurers).orElseGet(Collections::emptyList);
|
||||
}
|
||||
|
||||
public void setDiskUsageCriticalPercentage(Float diskUsageCriticalPercentage) {
|
||||
this.diskUsageCriticalPercentage = diskUsageCriticalPercentage;
|
||||
}
|
||||
@@ -187,11 +328,8 @@ public class DiskStoreFactoryBean implements BeanNameAware , FactoryBean<DiskSto
|
||||
this.writeBufferSize = writeBufferSize;
|
||||
}
|
||||
|
||||
/* package-private */ final String getName() {
|
||||
return (StringUtils.hasText(name) ? name : DiskStoreFactory.DEFAULT_DISK_STORE_NAME);
|
||||
}
|
||||
|
||||
public static class DiskDir {
|
||||
|
||||
final Integer maxSize;
|
||||
final String location;
|
||||
|
||||
@@ -199,10 +337,10 @@ public class DiskStoreFactoryBean implements BeanNameAware , FactoryBean<DiskSto
|
||||
this.location = location;
|
||||
this.maxSize = null;
|
||||
}
|
||||
|
||||
public DiskDir(String location, int maxSize) {
|
||||
this.location = location;
|
||||
this.maxSize = maxSize;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ 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.util.CacheUtils;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
@@ -36,7 +37,30 @@ import org.springframework.util.ClassUtils;
|
||||
@SuppressWarnings("unused")
|
||||
public abstract class GemfireUtils extends CacheUtils {
|
||||
|
||||
public final static String GEMFIRE_VERSION = CacheFactory.getVersion();
|
||||
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";
|
||||
|
||||
/* (non-Javadoc) */
|
||||
public static String apacheGeodeProductName() {
|
||||
try {
|
||||
return GemFireVersion.getProductName();
|
||||
}
|
||||
catch (Throwable ignore) {
|
||||
return APACHE_GEODE_NAME;
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
public static String apacheGeodeVersion() {
|
||||
try {
|
||||
return CacheFactory.getVersion();
|
||||
}
|
||||
catch (Throwable ignore) {
|
||||
return UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
public static boolean isGemfireVersionGreaterThanEqualTo(double expectedVersion) {
|
||||
@@ -87,5 +111,4 @@ public abstract class GemfireUtils extends CacheUtils {
|
||||
//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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,7 +16,16 @@
|
||||
|
||||
package org.springframework.data.gemfire;
|
||||
|
||||
import static java.util.stream.StreamSupport.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 java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.apache.geode.cache.RegionService;
|
||||
@@ -27,51 +36,59 @@ import org.apache.geode.cache.query.IndexInvalidException;
|
||||
import org.apache.geode.cache.query.IndexNameConflictException;
|
||||
import org.apache.geode.cache.query.IndexStatistics;
|
||||
import org.apache.geode.cache.query.QueryService;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.data.gemfire.config.annotation.IndexConfigurer;
|
||||
import org.springframework.data.gemfire.config.xml.GemfireConstants;
|
||||
import org.springframework.data.gemfire.support.AbstractFactoryBeanSupport;
|
||||
import org.springframework.data.gemfire.util.CollectionUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Spring FactoryBean for easy declarative creation of GemFire Indexes.
|
||||
* Spring {@link FactoryBean} used to construct, configure and initialize {@link Index Indexes}
|
||||
* using a declarative approach.
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @author David Turanski
|
||||
* @author John Blum
|
||||
* @see org.springframework.beans.factory.BeanFactoryAware
|
||||
* @see org.springframework.beans.factory.BeanNameAware
|
||||
* @see org.springframework.beans.factory.FactoryBean
|
||||
* @see org.springframework.beans.factory.InitializingBean
|
||||
* @see org.springframework.data.gemfire.IndexFactoryBean.IndexWrapper
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.apache.geode.cache.RegionService
|
||||
* @see org.apache.geode.cache.query.Index
|
||||
* @see org.apache.geode.cache.query.QueryService
|
||||
* @see org.springframework.beans.factory.FactoryBean
|
||||
* @see org.springframework.beans.factory.InitializingBean
|
||||
* @see org.springframework.data.gemfire.IndexFactoryBean.IndexWrapper
|
||||
* @see org.springframework.data.gemfire.config.annotation.IndexConfigurer
|
||||
* @see org.springframework.data.gemfire.support.AbstractFactoryBeanSupport
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class IndexFactoryBean implements InitializingBean, FactoryBean<Index>, BeanNameAware, BeanFactoryAware {
|
||||
public class IndexFactoryBean extends AbstractFactoryBeanSupport<Index> implements InitializingBean {
|
||||
|
||||
private boolean define = false;
|
||||
private boolean override = true;
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
private Index index;
|
||||
|
||||
private IndexType indexType;
|
||||
|
||||
//@Autowired(required = false)
|
||||
private List<IndexConfigurer> indexConfigurers = Collections.emptyList();
|
||||
|
||||
private IndexConfigurer compositeIndexConfigurer = new IndexConfigurer() {
|
||||
|
||||
@Override
|
||||
public void configure(String beanName, IndexFactoryBean bean) {
|
||||
nullSafeCollection(indexConfigurers).forEach(indexConfigurer -> indexConfigurer.configure(beanName, bean));
|
||||
}
|
||||
};
|
||||
|
||||
private QueryService queryService;
|
||||
|
||||
private RegionService cache;
|
||||
|
||||
private String beanName;
|
||||
private String expression;
|
||||
private String from;
|
||||
private String imports;
|
||||
@@ -83,29 +100,66 @@ public class IndexFactoryBean implements InitializingBean, FactoryBean<Index>, B
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(cache, "The GemFire Cache reference must not be null!");
|
||||
|
||||
queryService = lookupQueryService();
|
||||
this.indexName = Optional.ofNullable(this.name).filter(StringUtils::hasText).orElse(getBeanName());
|
||||
|
||||
Assert.hasText(this.indexName, "Index name is required");
|
||||
|
||||
applyIndexConfigurers(this.indexName);
|
||||
|
||||
Assert.notNull(cache, "Cache is required");
|
||||
|
||||
this.queryService = lookupQueryService();
|
||||
|
||||
Assert.notNull(queryService, "QueryService is required to create an Index");
|
||||
Assert.hasText(expression, "Index 'expression' is required");
|
||||
Assert.hasText(from, "Index 'from clause' is required");
|
||||
Assert.hasText(expression, "Index expression is required");
|
||||
Assert.hasText(from, "Index from clause is required");
|
||||
|
||||
if (IndexType.isKey(indexType)) {
|
||||
Assert.isNull(imports, "'imports' are not supported with a KEY Index");
|
||||
Assert.isNull(imports, "imports are not supported with a KEY Index");
|
||||
}
|
||||
|
||||
indexName = (StringUtils.hasText(name) ? name : beanName);
|
||||
this.index = createIndex(queryService, indexName);
|
||||
}
|
||||
|
||||
Assert.hasText(indexName, "Index 'name' is required");
|
||||
/* (non-Javadoc) */
|
||||
private void applyIndexConfigurers(String indexName) {
|
||||
applyIndexConfigurers(indexName, getCompositeRegionConfigurer());
|
||||
}
|
||||
|
||||
index = createIndex(queryService, indexName);
|
||||
/**
|
||||
* Null-safe operation to apply the given array of {@link IndexConfigurer IndexConfigurers}
|
||||
* to this {@link IndexFactoryBean}.
|
||||
*
|
||||
* @param indexName {@link String} containing the name of the {@link Index}.
|
||||
* @param indexConfigurers array of {@link IndexConfigurer IndexConfigurers} applied
|
||||
* to this {@link IndexFactoryBean}.
|
||||
* @see org.springframework.data.gemfire.config.annotation.RegionConfigurer
|
||||
* @see #applyIndexConfigurers(String, Iterable)
|
||||
*/
|
||||
protected void applyIndexConfigurers(String indexName, IndexConfigurer... indexConfigurers) {
|
||||
applyIndexConfigurers(indexName, Arrays.asList(nullSafeArray(indexConfigurers, IndexConfigurer.class)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe operation to apply the given {@link Iterable} of {@link IndexConfigurer IndexConfigurers}
|
||||
* to this {@link IndexFactoryBean}.
|
||||
*
|
||||
* @param indexName {@link String} containing the name of the {@link Index}.
|
||||
* @param indexConfigurers {@link Iterable} of {@link IndexConfigurer IndexConfigurers} applied
|
||||
* to this {@link IndexFactoryBean}.
|
||||
* @see org.springframework.data.gemfire.config.annotation.RegionConfigurer
|
||||
*/
|
||||
protected void applyIndexConfigurers(String indexName, Iterable<IndexConfigurer> indexConfigurers) {
|
||||
stream(nullSafeIterable(indexConfigurers).spliterator(), false)
|
||||
.forEach(indexConfigurer -> indexConfigurer.configure(indexName, this));
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
QueryService doLookupQueryService() {
|
||||
return (queryService != null ? queryService
|
||||
: (cache instanceof ClientCache ? ((ClientCache) cache).getLocalQueryService() : cache.getQueryService()));
|
||||
return Optional.ofNullable(this.queryService).orElseGet(() ->
|
||||
(this.cache instanceof ClientCache ? ((ClientCache) this.cache).getLocalQueryService()
|
||||
: this.cache.getQueryService()));
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@@ -131,6 +185,7 @@ public class IndexFactoryBean implements InitializingBean, FactoryBean<Index>, B
|
||||
|
||||
/* (non-Javadoc) */
|
||||
Index createIndex(QueryService queryService, String indexName) throws Exception {
|
||||
|
||||
Index existingIndex = getExistingIndex(queryService, indexName);
|
||||
|
||||
if (existingIndex != null) {
|
||||
@@ -183,6 +238,7 @@ public class IndexFactoryBean implements InitializingBean, FactoryBean<Index>, B
|
||||
|
||||
/* (non-Javadoc) */
|
||||
Index createKeyIndex(QueryService queryService, String indexName, String expression, String from) throws Exception {
|
||||
|
||||
if (isDefine()) {
|
||||
queryService.defineKeyIndex(indexName, expression, from);
|
||||
return new IndexWrapper(queryService, indexName);
|
||||
@@ -194,7 +250,7 @@ public class IndexFactoryBean implements InitializingBean, FactoryBean<Index>, B
|
||||
|
||||
/* (non-Javadoc) */
|
||||
Index createHashIndex(QueryService queryService, String indexName, String expression, String from,
|
||||
String imports) throws Exception {
|
||||
String imports) throws Exception {
|
||||
|
||||
boolean hasImports = StringUtils.hasText(imports);
|
||||
|
||||
@@ -246,7 +302,8 @@ public class IndexFactoryBean implements InitializingBean, FactoryBean<Index>, B
|
||||
|
||||
/* (non-Javadoc) */
|
||||
Index getExistingIndex(QueryService queryService, String indexName) {
|
||||
for (Index index : CollectionUtils.nullSafeCollection(queryService.getIndexes())) {
|
||||
|
||||
for (Index index : nullSafeCollection(queryService.getIndexes())) {
|
||||
if (index.getName().equalsIgnoreCase(indexName)) {
|
||||
return index;
|
||||
}
|
||||
@@ -255,29 +312,33 @@ public class IndexFactoryBean implements InitializingBean, FactoryBean<Index>, B
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the Composite {@link IndexConfigurer} used to apply additional configuration
|
||||
* to this {@link IndexFactoryBean} on Spring container initialization.
|
||||
*
|
||||
* @return the Composite {@link IndexConfigurer}.
|
||||
* @see org.springframework.data.gemfire.config.annotation.IndexConfigurer
|
||||
*/
|
||||
protected IndexConfigurer getCompositeRegionConfigurer() {
|
||||
return this.compositeIndexConfigurer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public Index getObject() {
|
||||
index = (index != null ? index : getExistingIndex(queryService, indexName));
|
||||
return index;
|
||||
return Optional.ofNullable(this.index)
|
||||
.orElseGet(() -> this.index = getExistingIndex(queryService, indexName));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Class<?> getObjectType() {
|
||||
return (index != null ? index.getClass() : Index.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
return Optional.ofNullable(this.index).map(Index::getClass).orElse((Class) Index.class);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -298,24 +359,6 @@ public class IndexFactoryBean implements InitializingBean, FactoryBean<Index>, B
|
||||
this.queryService = service;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected BeanFactory getBeanFactory() {
|
||||
Assert.state(beanFactory != null, "'beanFactory' was not properly initialized");
|
||||
return beanFactory;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@Override
|
||||
public void setBeanName(String name) {
|
||||
this.beanName = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name the name to set
|
||||
*/
|
||||
@@ -363,6 +406,31 @@ public class IndexFactoryBean implements InitializingBean, FactoryBean<Index>, B
|
||||
this.imports = imports;
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe operation to set an array of {@link IndexConfigurer IndexConfigurers} used to apply
|
||||
* additional configuration to this {@link IndexFactoryBean} when using Annotation-based configuration.
|
||||
*
|
||||
* @param indexConfigurers array of {@link IndexConfigurer IndexConfigurers} used to apply
|
||||
* additional configuration to this {@link IndexFactoryBean}.
|
||||
* @see org.springframework.data.gemfire.config.annotation.IndexConfigurer
|
||||
* @see #setIndexConfigurers(List)
|
||||
*/
|
||||
public void setIndexConfigurers(IndexConfigurer... indexConfigurers) {
|
||||
setIndexConfigurers(Arrays.asList(nullSafeArray(indexConfigurers, IndexConfigurer.class)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe operation to set an {@link Iterable} of {@link IndexConfigurer IndexConfigurers} used to apply
|
||||
* additional configuration to this {@link IndexFactoryBean} when using Annotation-based configuration.
|
||||
*
|
||||
* @param indexConfigurers {@link Iterable } of {@link IndexConfigurer IndexConfigurers} used to apply
|
||||
* additional configuration to this {@link IndexFactoryBean}.
|
||||
* @see org.springframework.data.gemfire.config.annotation.IndexConfigurer
|
||||
*/
|
||||
public void setIndexConfigurers(List<IndexConfigurer> indexConfigurers) {
|
||||
this.indexConfigurers = Optional.ofNullable(indexConfigurers).orElseGet(Collections::emptyList);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param override the override to set
|
||||
*/
|
||||
|
||||
@@ -16,7 +16,19 @@
|
||||
|
||||
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.lang.reflect.Field;
|
||||
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;
|
||||
@@ -43,20 +55,52 @@ import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.context.SmartLifecycle;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.data.gemfire.util.ArrayUtils;
|
||||
import org.springframework.data.gemfire.client.ClientRegionFactoryBean;
|
||||
import org.springframework.data.gemfire.config.annotation.RegionConfigurer;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
<<<<<<< HEAD
|
||||
* Abstract base class and Spring {@link FactoryBean} for constructing and initializing a GemFire {@link Region}.
|
||||
=======
|
||||
* Abstract Spring {@link FactoryBean} base class extended by other SDG {@link FactoryBean FactoryBeans} used to
|
||||
* construct, configure and initialize peer {@link Region Regions}.
|
||||
*
|
||||
* This {@link FactoryBean} allows for very easy and flexible creation of peer {@link Region}.
|
||||
* For client {@link Region Regions}, however, see the {@link ClientRegionFactoryBean}.
|
||||
>>>>>>> c22ebe6... DATAGEODE-12 - Introduce Spring Configurers to flexibly alter Spring Data GemFire configuration when using Annotation config.
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @author David Turanski
|
||||
* @author John Blum
|
||||
<<<<<<< HEAD
|
||||
* @see org.springframework.beans.factory.DisposableBean
|
||||
* @see org.springframework.context.SmartLifecycle
|
||||
* @see org.springframework.data.gemfire.RegionLookupFactoryBean
|
||||
=======
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see org.apache.geode.cache.CacheListener
|
||||
* @see org.apache.geode.cache.CacheLoader
|
||||
* @see org.apache.geode.cache.CacheWriter
|
||||
* @see org.apache.geode.cache.DataPolicy
|
||||
* @see org.apache.geode.cache.EvictionAttributes
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.PartitionAttributes
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.apache.geode.cache.RegionAttributes
|
||||
* @see org.apache.geode.cache.RegionFactory
|
||||
* @see org.apache.geode.cache.RegionShortcut
|
||||
* @see org.apache.geode.cache.Scope
|
||||
* @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 org.springframework.data.gemfire.client.ClientRegionFactoryBean
|
||||
* @see org.springframework.data.gemfire.config.annotation.RegionConfigurer
|
||||
>>>>>>> c22ebe6... DATAGEODE-12 - Introduce Spring Configurers to flexibly alter Spring Data GemFire configuration when using Annotation config.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
|
||||
@@ -68,6 +112,7 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
|
||||
private boolean destroy = false;
|
||||
private boolean running;
|
||||
|
||||
private Boolean offHeap;
|
||||
private Boolean persistent;
|
||||
|
||||
private AsyncEventQueue[] asyncEventQueues;
|
||||
@@ -87,8 +132,19 @@ 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;
|
||||
@@ -98,128 +154,215 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
|
||||
private String diskStoreName;
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* Creates a new {@link Region} with the given {@link String name}.
|
||||
*
|
||||
* @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 org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.Region
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
super.afterPropertiesSet();
|
||||
postProcess(getRegion());
|
||||
protected Region<K, V> createRegion(GemFireCache gemfireCache, String regionName) throws Exception {
|
||||
|
||||
applyRegionConfigurers(regionName);
|
||||
|
||||
verifyLockGrantorEligibility(getAttributes(), getScope());
|
||||
|
||||
Cache cache = resolveCache(gemfireCache);
|
||||
|
||||
RegionFactory<K, V> regionFactory = postProcess(configure(createRegionFactory(cache)));
|
||||
|
||||
Region<K, V> region = newRegion(regionFactory, getParent(), regionName);
|
||||
|
||||
return enableAsLockGrantor(region);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private void applyRegionConfigurers(String regionName) {
|
||||
applyRegionConfigurers(regionName, getCompositeRegionConfigurer());
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* 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)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
protected Region<K, V> lookupRegion(GemFireCache gemfireCache, String regionName) throws Exception {
|
||||
Assert.isTrue(gemfireCache instanceof Cache, String.format("Unable to create Regions from '%1$s'.",
|
||||
gemfireCache));
|
||||
protected void applyRegionConfigurers(String regionName, RegionConfigurer... regionConfigurers) {
|
||||
applyRegionConfigurers(regionName, Arrays.asList(nullSafeArray(regionConfigurers, RegionConfigurer.class)));
|
||||
}
|
||||
|
||||
Cache cache = (Cache) gemfireCache;
|
||||
/**
|
||||
* 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));
|
||||
}
|
||||
|
||||
RegionFactory<K, V> regionFactory = createRegionFactory(cache);
|
||||
/* (non-Javadoc) */
|
||||
private Region<K, V> enableAsLockGrantor(Region<K, V> region) {
|
||||
|
||||
for (AsyncEventQueue asyncEventQueue : ArrayUtils.nullSafeArray(asyncEventQueues, AsyncEventQueue.class)) {
|
||||
regionFactory.addAsyncEventQueueId(asyncEventQueue.getId());
|
||||
}
|
||||
|
||||
for (CacheListener<K, V> listener : ArrayUtils.nullSafeArray(cacheListeners, CacheListener.class)) {
|
||||
regionFactory.addCacheListener(listener);
|
||||
}
|
||||
|
||||
if (cacheLoader != null) {
|
||||
regionFactory.setCacheLoader(cacheLoader);
|
||||
}
|
||||
|
||||
if (cacheWriter != null) {
|
||||
regionFactory.setCacheWriter(cacheWriter);
|
||||
}
|
||||
|
||||
for (GatewaySender gatewaySender : ArrayUtils.nullSafeArray(gatewaySenders, GatewaySender.class)) {
|
||||
regionFactory.addGatewaySenderId(gatewaySender.getId());
|
||||
}
|
||||
|
||||
resolveDataPolicy(regionFactory, persistent, dataPolicy);
|
||||
|
||||
if (isDiskStoreConfigurationAllowed()) {
|
||||
regionFactory.setDiskStoreName(diskStoreName);
|
||||
}
|
||||
|
||||
if (evictionAttributes != null) {
|
||||
regionFactory.setEvictionAttributes(evictionAttributes);
|
||||
}
|
||||
|
||||
if (keyConstraint != null) {
|
||||
regionFactory.setKeyConstraint(keyConstraint);
|
||||
}
|
||||
|
||||
if (scope != null) {
|
||||
regionFactory.setScope(scope);
|
||||
}
|
||||
|
||||
if (valueConstraint != null) {
|
||||
regionFactory.setValueConstraint(valueConstraint);
|
||||
}
|
||||
|
||||
if (attributes != null) {
|
||||
Assert.state(!attributes.isLockGrantor() || (scope == null) || scope.isGlobal(),
|
||||
"Lock Grantor only applies to a 'GLOBAL' scoped Region.");
|
||||
}
|
||||
|
||||
postProcess(regionFactory);
|
||||
|
||||
Region<K, V> region = (getParent() != null ? regionFactory.createSubregion(getParent(), regionName)
|
||||
: regionFactory.create(regionName));
|
||||
|
||||
if (log.isInfoEnabled()) {
|
||||
if (getParent() != null) {
|
||||
log.info(String.format("Created new Cache sub-Region [%1$s] under parent Region [%2$s].",
|
||||
regionName, getParent().getName()));
|
||||
}
|
||||
else {
|
||||
log.info(String.format("Created new Cache Region [%1$s].", regionName));
|
||||
}
|
||||
}
|
||||
|
||||
if (snapshot != null) {
|
||||
region.loadSnapshot(snapshot.getInputStream());
|
||||
}
|
||||
|
||||
if (attributes != null && attributes.isLockGrantor()) {
|
||||
region.becomeLockGrantor();
|
||||
}
|
||||
Optional.ofNullable(region)
|
||||
.filter(it -> it.getAttributes().isLockGrantor())
|
||||
.ifPresent(Region::becomeLockGrantor);
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private Region<K, V> newRegion(RegionFactory<K, V> regionFactory, Region<?, ?> parentRegion, String regionName) {
|
||||
|
||||
return Optional.ofNullable(parentRegion)
|
||||
.map(parent -> {
|
||||
logInfo("Creating Subregion [%1$s] with parent Region [%2$s]",
|
||||
regionName, parent.getName());
|
||||
|
||||
return regionFactory.<K, V>createSubregion(parent, regionName);
|
||||
})
|
||||
.orElseGet(() -> {
|
||||
logInfo("Created Region [%1$s]", regionName);
|
||||
|
||||
return regionFactory.create(regionName);
|
||||
});
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private Cache resolveCache(GemFireCache gemfireCache) {
|
||||
|
||||
return Optional.ofNullable(gemfireCache)
|
||||
.filter(cache -> cache instanceof Cache)
|
||||
.map(cache -> (Cache) cache)
|
||||
.orElseThrow(() -> newIllegalArgumentException("Peer Cache is required"));
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private RegionAttributes<K, V> verifyLockGrantorEligibility(RegionAttributes<K, V> regionAttributes, Scope scope) {
|
||||
|
||||
Optional.ofNullable(regionAttributes).ifPresent(attributes ->
|
||||
Assert.state(!attributes.isLockGrantor() || verifyScope(scope),
|
||||
"Lock Grantor only applies to GLOBAL Scoped Regions"));
|
||||
|
||||
return regionAttributes;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private boolean verifyScope(Scope scope) {
|
||||
return (scope == null || Scope.GLOBAL.equals(scope));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of RegionFactory using the given Cache instance used to configure and construct the Region
|
||||
* created by this FactoryBean.
|
||||
* Creates an instance of {@link RegionFactory} with the given {@link Cache} which is then used to construct,
|
||||
* configure and initialize the {@link Region} specified by this {@link RegionFactoryBean}.
|
||||
*
|
||||
* @param cache the GemFire Cache instance.
|
||||
* @return a RegionFactory used to configure and construct the Region created by this FactoryBean.
|
||||
* @see org.apache.geode.cache.Cache#createRegionFactory()
|
||||
* @see org.apache.geode.cache.Cache#createRegionFactory(org.apache.geode.cache.RegionAttributes)
|
||||
* @param cache reference to the {@link Cache}.
|
||||
* @return a {@link RegionFactory} used to construct, configure and initialized the {@link Region} specified by
|
||||
* this {@link RegionFactoryBean}.
|
||||
* @see org.apache.geode.cache.Cache#createRegionFactory(org.apache.geode.cache.RegionShortcut)
|
||||
* @see org.apache.geode.cache.Cache#createRegionFactory(org.apache.geode.cache.RegionAttributes)
|
||||
* @see org.apache.geode.cache.Cache#createRegionFactory()
|
||||
* @see org.apache.geode.cache.RegionFactory
|
||||
*/
|
||||
protected RegionFactory<K, V> createRegionFactory(Cache cache) {
|
||||
if (shortcut != null) {
|
||||
RegionFactory<K, V> regionFactory = mergeRegionAttributes(cache.createRegionFactory(shortcut), attributes);
|
||||
|
||||
if (this.shortcut != null) {
|
||||
RegionFactory<K, V> regionFactory =
|
||||
mergeRegionAttributes(cache.createRegionFactory(this.shortcut), this.attributes);
|
||||
|
||||
setDataPolicy(getDataPolicy(regionFactory));
|
||||
|
||||
return regionFactory;
|
||||
}
|
||||
else if (attributes != null) {
|
||||
return cache.createRegionFactory(attributes);
|
||||
else if (this.attributes != null) {
|
||||
return cache.createRegionFactory(this.attributes);
|
||||
}
|
||||
else {
|
||||
return cache.createRegionFactory();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the {@link RegionFactory} based on the configuration settings of this {@link RegionFactoryBean}.
|
||||
*
|
||||
* @param regionFactory {@link RegionFactory} to configure
|
||||
* @return the given {@link RegionFactory}.
|
||||
* @see org.apache.geode.cache.RegionFactory
|
||||
*/
|
||||
protected RegionFactory<K, V> configure(RegionFactory<K, V> regionFactory) {
|
||||
|
||||
stream(nullSafeArray(this.asyncEventQueues, AsyncEventQueue.class))
|
||||
.forEach(asyncEventQueue -> regionFactory.addAsyncEventQueueId(asyncEventQueue.getId()));
|
||||
|
||||
stream(nullSafeArray(this.cacheListeners, CacheListener.class)).forEach(regionFactory::addCacheListener);
|
||||
|
||||
Optional.ofNullable(this.cacheLoader).ifPresent(regionFactory::setCacheLoader);
|
||||
|
||||
Optional.ofNullable(this.cacheWriter).ifPresent(regionFactory::setCacheWriter);
|
||||
|
||||
resolveDataPolicy(regionFactory, persistent, dataPolicy);
|
||||
|
||||
Optional.ofNullable(this.diskStoreName)
|
||||
.filter(name -> isDiskStoreConfigurationAllowed())
|
||||
.ifPresent(regionFactory::setDiskStoreName);
|
||||
|
||||
Optional.ofNullable(this.evictionAttributes).ifPresent(regionFactory::setEvictionAttributes);
|
||||
|
||||
stream(nullSafeArray(this.gatewaySenders, GatewaySender.class))
|
||||
.forEach(gatewaySender -> regionFactory.addGatewaySenderId(((GatewaySender) gatewaySender).getId()));
|
||||
|
||||
Optional.ofNullable(this.keyConstraint).ifPresent(regionFactory::setKeyConstraint);
|
||||
|
||||
Optional.ofNullable(this.scope).ifPresent(regionFactory::setScope);
|
||||
|
||||
Optional.ofNullable(this.valueConstraint).ifPresent(regionFactory::setValueConstraint);
|
||||
|
||||
return regionFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Post-process the {@link RegionFactory} used to create the {@link Region} specified by
|
||||
* this {@link RegionFactoryBean} during initialization.
|
||||
*
|
||||
* The {@link RegionFactory} has been already constructed, configured and initialized by
|
||||
* this {@link RegionFactoryBean} before this method gets invoked.
|
||||
*
|
||||
* @param regionFactory {@link RegionFactory} used to create the {@link Region}.
|
||||
* @return the given {@link RegionFactory}.
|
||||
* @see org.apache.geode.cache.RegionFactory
|
||||
*/
|
||||
protected RegionFactory<K, V> postProcess(RegionFactory<K, V> regionFactory) {
|
||||
|
||||
regionFactory.setOffHeap(Boolean.TRUE.equals(this.offHeap));
|
||||
|
||||
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 should not be considered part of the RegionFactoryBean API
|
||||
* and is strictly for testing purposes!
|
||||
* (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(..)
|
||||
* since the "regionAttributes" field is naively declared as a instance of the implementation class type
|
||||
@@ -233,8 +376,8 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
|
||||
*/
|
||||
@SuppressWarnings({ "deprecation", "unchecked" })
|
||||
DataPolicy getDataPolicy(RegionFactory regionFactory) {
|
||||
return ((RegionAttributes) getFieldValue(getFieldValue(regionFactory, "attrsFactory", AttributesFactory.class),
|
||||
"regionAttributes", null)).getDataPolicy();
|
||||
return ((RegionAttributes) getFieldValue(getFieldValue(regionFactory, "attrsFactory",
|
||||
AttributesFactory.class), "regionAttributes", null)).getDataPolicy();
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@@ -298,7 +441,10 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
|
||||
regionFactory.setLockGrantor(regionAttributes.isLockGrantor());
|
||||
regionFactory.setMembershipAttributes(regionAttributes.getMembershipAttributes());
|
||||
regionFactory.setMulticastEnabled(regionAttributes.getMulticastEnabled());
|
||||
regionFactory.setOffHeap(regionAttributes.getOffHeap());
|
||||
|
||||
mergePartitionAttributes(regionFactory, regionAttributes);
|
||||
|
||||
regionFactory.setPoolName(regionAttributes.getPoolName());
|
||||
regionFactory.setRegionIdleTimeout(regionAttributes.getRegionIdleTimeout());
|
||||
regionFactory.setRegionTimeToLive(regionAttributes.getRegionTimeToLive());
|
||||
@@ -310,8 +456,12 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
|
||||
return regionFactory;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected <K, V> void mergePartitionAttributes(final RegionFactory<K, V> regionFactory,
|
||||
/**
|
||||
*
|
||||
* @param regionFactory
|
||||
* @param regionAttributes
|
||||
*/
|
||||
protected <K, V> void mergePartitionAttributes(RegionFactory<K, V> regionFactory,
|
||||
RegionAttributes<K, V> regionAttributes) {
|
||||
|
||||
// NOTE PartitionAttributes are created by certain RegionShortcuts; need the null check since RegionAttributes
|
||||
@@ -342,8 +492,9 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc) - This method should not be considered part of the RegionFactoryBean API
|
||||
* and is strictly for testing purposes!
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* This method is not part of the RegionFactoryBean API and is strictly used for testing purposes!
|
||||
*
|
||||
* @see org.apache.geode.cache.AttributesFactory#validateAttributes(:RegionAttributes)
|
||||
*/
|
||||
@@ -353,10 +504,12 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc) - This method should not be considered part of the RegionFactoryBean API
|
||||
* and is strictly for testing purposes!
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* This method is not part of the RegionFactoryBean API and is strictly used for testing purposes!
|
||||
*
|
||||
* NOTE unfortunately, must resort to using a GemFire internal class, ugh!
|
||||
*
|
||||
* @see org.apache.geode.internal.cache.UserSpecifiedRegionAttributes#hasEvictionAttributes
|
||||
*/
|
||||
boolean isUserSpecifiedEvictionAttributes(final RegionAttributes regionAttributes) {
|
||||
@@ -366,7 +519,8 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private boolean isDiskStoreConfigurationAllowed() {
|
||||
boolean allow = (diskStoreName != null);
|
||||
|
||||
boolean allow = StringUtils.hasText(this.diskStoreName);
|
||||
|
||||
allow &= (getDataPolicy().withPersistence() || (getAttributes() != null
|
||||
&& getAttributes().getEvictionAttributes() != null
|
||||
@@ -425,41 +579,21 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
|
||||
* @see org.apache.geode.cache.DataPolicy
|
||||
*/
|
||||
protected void assertDataPolicyAndPersistentAttributesAreCompatible(DataPolicy resolvedDataPolicy) {
|
||||
|
||||
if (resolvedDataPolicy.withPersistence()) {
|
||||
Assert.isTrue(isPersistentUnspecified() || isPersistent(), String.format(
|
||||
"Data Policy '%1$s' is invalid when persistent is false.", resolvedDataPolicy));
|
||||
"Data Policy [%1$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 '%1$s' is invalid when persistent is true.", resolvedDataPolicy));
|
||||
"Data Policy [%1$s] is invalid when persistent is true.", resolvedDataPolicy));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Post-process the RegionFactory used to create the GemFire Region for this factory bean during the initialization
|
||||
* process. The RegionFactory is already configured and initialized by the factory bean before this method
|
||||
* is invoked.
|
||||
*
|
||||
* @param regionFactory the GemFire RegionFactory used to create the Region for post-processing.
|
||||
* @see org.apache.geode.cache.RegionFactory
|
||||
*/
|
||||
protected RegionFactory<K, V> postProcess(RegionFactory<K, V> regionFactory) {
|
||||
return regionFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Post-process the Region for this factory bean during the initialization process. The Region is
|
||||
* already configured and initialized by the factory bean before this method is invoked.
|
||||
*
|
||||
* @param region the GemFire Region to post-process.
|
||||
* @see org.apache.geode.cache.Region
|
||||
*/
|
||||
protected Region<K, V> postProcess(Region<K, V> region) {
|
||||
return region;
|
||||
}
|
||||
|
||||
/**
|
||||
=======
|
||||
>>>>>>> c22ebe6... DATAGEODE-12 - Introduce Spring Configurers to flexibly alter Spring Data GemFire configuration when using Annotation config.
|
||||
* Validates and sets the Data Policy on the RegionFactory used to create and configure the Region from this
|
||||
* FactoryBean.
|
||||
*
|
||||
@@ -472,6 +606,7 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
|
||||
* @see org.apache.geode.cache.RegionFactory
|
||||
*/
|
||||
protected void resolveDataPolicy(RegionFactory<K, V> regionFactory, Boolean persistent, DataPolicy dataPolicy) {
|
||||
|
||||
if (dataPolicy != null) {
|
||||
assertDataPolicyAndPersistentAttributesAreCompatible(dataPolicy);
|
||||
regionFactory.setDataPolicy(dataPolicy);
|
||||
@@ -493,10 +628,11 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
|
||||
* @see org.apache.geode.cache.RegionFactory
|
||||
*/
|
||||
protected void resolveDataPolicy(RegionFactory<K, V> regionFactory, Boolean persistent, String dataPolicy) {
|
||||
|
||||
if (dataPolicy != null) {
|
||||
DataPolicy resolvedDataPolicy = new DataPolicyConverter().convert(dataPolicy);
|
||||
|
||||
Assert.notNull(resolvedDataPolicy, String.format("Data Policy '%1$s' is invalid.", dataPolicy));
|
||||
Assert.notNull(resolvedDataPolicy, String.format("Data Policy [%1$s] is invalid.", dataPolicy));
|
||||
assertDataPolicyAndPersistentAttributesAreCompatible(resolvedDataPolicy);
|
||||
|
||||
regionFactory.setDataPolicy(resolvedDataPolicy);
|
||||
@@ -515,16 +651,21 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private DataPolicy getDataPolicy(final RegionAttributes regionAttributes, final DataPolicy defaultDataPolicy) {
|
||||
return (regionAttributes != null ? regionAttributes.getDataPolicy() : defaultDataPolicy);
|
||||
private DataPolicy getDataPolicy(RegionAttributes regionAttributes, DataPolicy defaultDataPolicy) {
|
||||
return Optional.ofNullable(regionAttributes).map(RegionAttributes::getDataPolicy).orElse(defaultDataPolicy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes and destroys the {@link Region}.
|
||||
*
|
||||
* @throws Exception if destroy fails.
|
||||
* @see org.springframework.beans.factory.DisposableBean
|
||||
*/
|
||||
@Override
|
||||
public void destroy() throws Exception {
|
||||
Region<K, V> region = getObject();
|
||||
|
||||
if (region != null) {
|
||||
if (close) {
|
||||
Optional.ofNullable(getObject()).ifPresent(region -> {
|
||||
if (this.close) {
|
||||
if (!region.getRegionService().isClosed()) {
|
||||
try {
|
||||
region.close();
|
||||
@@ -535,10 +676,10 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
|
||||
|
||||
}
|
||||
|
||||
if (destroy) {
|
||||
if (this.destroy) {
|
||||
region.destroyRegion();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -568,9 +709,8 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
|
||||
* @return the RegionAttributes used to configure the Region created by this factory.
|
||||
* @see org.apache.geode.cache.RegionAttributes
|
||||
*/
|
||||
public RegionAttributes getAttributes() {
|
||||
Region<K, V> region = getRegion();
|
||||
return (region != null ? region.getAttributes() : attributes);
|
||||
public RegionAttributes<K, V> getAttributes() {
|
||||
return Optional.ofNullable(getRegion()).map(Region::getAttributes).orElse(this.attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -656,8 +796,8 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
|
||||
* @see org.apache.geode.cache.DataPolicy
|
||||
*/
|
||||
public DataPolicy getDataPolicy() {
|
||||
Assert.state(dataPolicy != null, "The Data Policy has not been properly resolved yet!");
|
||||
return dataPolicy;
|
||||
return Optional.ofNullable(this.dataPolicy)
|
||||
.orElseThrow(() -> newIllegalStateException("Data Policy has not been properly resolved yet"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -682,6 +822,37 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
|
||||
this.gatewaySenders = gatewaySenders;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether to enable this {@link Region} to store it's data in off-heap memory.
|
||||
*
|
||||
* @param offHeap Boolean value indicating whether to enable off-heap memory for this Region.
|
||||
* @see org.apache.geode.cache.RegionFactory#setOffHeap(boolean)
|
||||
*/
|
||||
public void setOffHeap(Boolean offHeap) {
|
||||
this.offHeap = offHeap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Boolean} value indicating whether off-heap memory was enabled for this {@link Region}.
|
||||
* Off-heap will be enabled if this method returns a non-{@literal null} {@link Boolean} value that evaluates
|
||||
* to {@literal true}.
|
||||
*
|
||||
* @return a {@link Boolean} value indicating whether off-heap is enabled for this {@link Region}.
|
||||
*/
|
||||
public Boolean getOffHeap() {
|
||||
return this.offHeap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a boolean value indicating whether off-heap has been enabled for this {@link Region}.
|
||||
*
|
||||
* @return a {@literal boolean} value indicating whether off-heap has been enabled for this {@link Region}.
|
||||
* @see #getOffHeap()
|
||||
*/
|
||||
public boolean isOffHeap() {
|
||||
return Boolean.TRUE.equals(getOffHeap());
|
||||
}
|
||||
|
||||
public void setKeyConstraint(Class<K> keyConstraint) {
|
||||
this.keyConstraint = keyConstraint;
|
||||
}
|
||||
@@ -690,6 +861,35 @@ 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the region scope. Used only when a new region is created. Overrides
|
||||
* the settings specified through {@link #setAttributes(RegionAttributes)}.
|
||||
@@ -712,23 +912,10 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
|
||||
this.shortcut = shortcut;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected final RegionShortcut getShortcut() {
|
||||
return shortcut;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the snapshots used for loading a newly <i>created</i> region. That
|
||||
* is, the snapshot will be used <i>only</i> when a new region is created -
|
||||
* if the region already exists, no loading will be performed.
|
||||
*
|
||||
* @see #setName(String)
|
||||
* @param snapshot the snapshot to set
|
||||
*/
|
||||
public void setSnapshot(Resource snapshot) {
|
||||
this.snapshot = snapshot;
|
||||
}
|
||||
|
||||
public void setValueConstraint(Class<V> valueConstraint) {
|
||||
this.valueConstraint = valueConstraint;
|
||||
}
|
||||
@@ -739,6 +926,7 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
|
||||
@Override
|
||||
@SuppressWarnings("all")
|
||||
public void start() {
|
||||
|
||||
if (!ObjectUtils.isEmpty(gatewaySenders)) {
|
||||
synchronized (gatewaySenders) {
|
||||
for (GatewaySender gatewaySender: gatewaySenders) {
|
||||
@@ -769,6 +957,7 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
|
||||
*/
|
||||
@Override
|
||||
public void stop() {
|
||||
|
||||
if (!ObjectUtils.isEmpty(gatewaySenders)) {
|
||||
synchronized (gatewaySenders) {
|
||||
for (GatewaySender gatewaySender : gatewaySenders) {
|
||||
|
||||
@@ -16,35 +16,39 @@
|
||||
|
||||
package org.springframework.data.gemfire;
|
||||
|
||||
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newRuntimeException;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.springframework.beans.factory.BeanInitializationException;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.data.gemfire.support.AbstractFactoryBeanSupport;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Spring {@link FactoryBean} for looking up generic GemFire {@link Region Regions}. If lookups are not enabled
|
||||
* or the {@link Region} does not exist, an Exception is thrown.
|
||||
* Spring {@link FactoryBean} for looking up {@link Region Regions}.
|
||||
*
|
||||
* If lookups are disabled or the {@link Region} does not exist, an exception is thrown.
|
||||
*
|
||||
* For declaring and configuring new Regions, see {@link RegionFactoryBean}.
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @author John Blum
|
||||
* @see org.springframework.beans.factory.BeanNameAware
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.springframework.beans.factory.FactoryBean
|
||||
* @see org.springframework.beans.factory.InitializingBean
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.springframework.data.gemfire.support.AbstractFactoryBeanSupport
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public abstract class RegionLookupFactoryBean<K, V>
|
||||
implements FactoryBean<Region<K, V>>, InitializingBean, BeanNameAware {
|
||||
|
||||
protected final Log log = LogFactory.getLog(getClass());
|
||||
public abstract class RegionLookupFactoryBean<K, V> extends AbstractFactoryBeanSupport<Region<K, V>>
|
||||
implements InitializingBean {
|
||||
|
||||
private Boolean lookupEnabled = false;
|
||||
|
||||
@@ -52,60 +56,109 @@ public abstract class RegionLookupFactoryBean<K, V>
|
||||
|
||||
private Region<?, ?> parent;
|
||||
|
||||
private Resource snapshot;
|
||||
|
||||
private volatile Region<K, V> region;
|
||||
|
||||
private String beanName;
|
||||
private String name;
|
||||
private String regionName;
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* Initializes this {@link RegionLookupFactoryBean} after properties have been set by the Spring container.
|
||||
*
|
||||
* @throws Exception if initialization fails.
|
||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||
* @see #createRegion(GemFireCache, String)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("all")
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(this.cache, "A 'Cache' reference must be set");
|
||||
|
||||
GemFireCache cache = getCache();
|
||||
|
||||
Assert.notNull(cache, "Cache is required");
|
||||
|
||||
String regionName = resolveRegionName();
|
||||
|
||||
Assert.hasText(regionName, "'regionName', 'name' or 'beanName' property must be set");
|
||||
Assert.hasText(regionName, "regionName, name or beanName property must be set");
|
||||
|
||||
synchronized (this.cache) {
|
||||
if (isLookupEnabled()) {
|
||||
this.region = Optional.ofNullable(getParent())
|
||||
synchronized (cache) {
|
||||
setRegion(isLookupEnabled()
|
||||
? Optional.ofNullable(getParent())
|
||||
.map(parentRegion -> parentRegion.<K, V>getSubregion(regionName))
|
||||
.orElseGet(() -> this.cache.<K, V>getRegion(regionName));
|
||||
}
|
||||
.orElseGet(() -> cache.<K, V>getRegion(regionName))
|
||||
: null);
|
||||
|
||||
if (region != null) {
|
||||
log.info(String.format("Found Region [%1$s] in Cache [%2$s]", regionName, cache.getName()));
|
||||
if (getRegion() != null) {
|
||||
logInfo("Found Region [%1$s] in Cache [%2$s]", regionName, cache.getName());
|
||||
}
|
||||
else {
|
||||
log.info(String.format("Falling back to creating Region [%1$s] in Cache [%2$s]",
|
||||
regionName, cache.getName()));
|
||||
logInfo("Falling back to creating Region [%1$s] in Cache [%2$s]",
|
||||
regionName, cache.getName());
|
||||
|
||||
region = lookupRegion(cache, regionName);
|
||||
setRegion(postProcess(loadSnapshot(createRegion(cache, regionName))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to perform a lookup when the named {@link Region} does not exist. By default, this implementation
|
||||
* throws an exception.
|
||||
* Creates a new {@link Region} with the given {@link String name}.
|
||||
*
|
||||
* @param cache reference to the GemFire cache.
|
||||
* @param regionName name of the GemFire {@link Region}.
|
||||
* @return the {@link Region} in the GemFire cache with the given name.
|
||||
* @throws BeanInitializationException if the lookup operation fails.
|
||||
* This method gets called when a {@link Region} with the specified {@link String name} does not already exist.
|
||||
* By default, this method implementation throws a {@link BeanInitializationException} and it is expected
|
||||
* that {@link Class subclasses} will override this method.
|
||||
*
|
||||
* @param cache 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}.
|
||||
* @throws BeanInitializationException by default unless a {@link Class subclass} overrides this method.
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.Region
|
||||
*/
|
||||
protected Region<K, V> lookupRegion(GemFireCache cache, String regionName) throws Exception {
|
||||
throw new BeanInitializationException(String.format(
|
||||
"Region [%1$s] in Cache [%2$s] not found", regionName, cache));
|
||||
protected Region<K, V> createRegion(GemFireCache cache, String regionName) throws Exception {
|
||||
throw new BeanInitializationException(
|
||||
String.format("Region [%1$s] in Cache [%2$s] not found", regionName, cache));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* Loads the configured data {@link Resource snapshot} into the given {@link Region}.
|
||||
*
|
||||
* @param region {@link Region} to load.
|
||||
* @return the given {@link Region}.
|
||||
* @throws RuntimeException if the snapshot load fails.
|
||||
* @see org.apache.geode.cache.Region#loadSnapshot(InputStream)
|
||||
*/
|
||||
protected Region<K, V> loadSnapshot(Region<K, V> region) {
|
||||
|
||||
Optional.ofNullable(this.snapshot).ifPresent(snapshot -> {
|
||||
try {
|
||||
region.loadSnapshot(snapshot.getInputStream());
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw newRuntimeException(e, "Failed to load snapshot [%s]", snapshot);
|
||||
}
|
||||
});
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
/**
|
||||
* Post-process the {@link Region} created by this {@link RegionFactoryBean}.
|
||||
*
|
||||
* @param region {@link Region} to process.
|
||||
* @see org.apache.geode.cache.Region
|
||||
*/
|
||||
protected Region<K, V> postProcess(Region<K, V> region) {
|
||||
return region;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an object reference to the {@link Region} created by this {@link RegionLookupFactoryBean}.
|
||||
*
|
||||
* @return an object reference to the {@link Region} created by this {@link RegionLookupFactoryBean}.
|
||||
* @see org.springframework.beans.factory.FactoryBean#getObject()
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see #getRegion()
|
||||
*/
|
||||
@Override
|
||||
public Region<K, V> getObject() throws Exception {
|
||||
@@ -113,49 +166,42 @@ public abstract class RegionLookupFactoryBean<K, V>
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
Region region = getRegion();
|
||||
return (region != null ? region.getClass() : Region.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the name of the GemFire {@link Region}.
|
||||
* Returns the {@link Class} type of the {@link Region} produced by this {@link RegionLookupFactoryBean}.
|
||||
*
|
||||
* @return a {@link String} indicating the name of the GemFire {@link Region}.
|
||||
* @return the {@link Class} type of the {@link Region} produced by this {@link RegionLookupFactoryBean}.
|
||||
* @see org.springframework.beans.factory.FactoryBean#getObjectType()
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Class<?> getObjectType() {
|
||||
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 : this.beanName));
|
||||
: (StringUtils.hasText(this.name) ? this.name : getBeanName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the {@link Region} based on the bean 'id' attribute. If no {@link Region} is found
|
||||
* with the given name, a new one will be created.
|
||||
* Returns a reference to the {@link GemFireCache} used to create the {@link Region}.
|
||||
*
|
||||
* @param name name of this {@link Region} bean in the Spring {@link org.springframework.context.ApplicationContext}.
|
||||
* @see org.springframework.beans.factory.BeanNameAware#setBeanName(String)
|
||||
* @return a reference to the {@link GemFireCache} used to create the {@link Region}..
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
*/
|
||||
public void setBeanName(String name) {
|
||||
this.beanName = name;
|
||||
public GemFireCache getCache() {
|
||||
return this.cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a reference to the {@link GemFireCache} used to create the {@link Region}.
|
||||
*
|
||||
* @param cache reference to the {@link GemFireCache}.
|
||||
* @see org.springframework.data.gemfire.CacheFactoryBean
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
*/
|
||||
public void setCache(GemFireCache cache) {
|
||||
@@ -174,7 +220,7 @@ public abstract class RegionLookupFactoryBean<K, V>
|
||||
|
||||
/* (non-Javadoc) */
|
||||
public Boolean getLookupEnabled() {
|
||||
return lookupEnabled;
|
||||
return this.lookupEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -213,13 +259,23 @@ public abstract class RegionLookupFactoryBean<K, V>
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the GemFire {@link Region} resolved by this Spring {@link FactoryBean}
|
||||
* during the lookup operation; maybe a new {@link Region}.
|
||||
* Sets a reference to the {@link Region} to be resolved by this Spring {@link FactoryBean}.
|
||||
*
|
||||
* @return a reference to the GemFire {@link Region} resolved during lookup.
|
||||
* @param region reference to the resolvable {@link Region}.
|
||||
* @see org.apache.geode.cache.Region
|
||||
*/
|
||||
protected Region<K, V> getRegion() {
|
||||
protected void setRegion(Region<K, V> region) {
|
||||
this.region = region;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the {@link Region} resolved by this Spring {@link FactoryBean}
|
||||
* during the lookup operation; maybe a new {@link Region}.
|
||||
*
|
||||
* @return a reference to the {@link Region} resolved during lookup.
|
||||
* @see org.apache.geode.cache.Region
|
||||
*/
|
||||
public Region<K, V> getRegion() {
|
||||
return this.region;
|
||||
}
|
||||
|
||||
@@ -233,4 +289,16 @@ public abstract class RegionLookupFactoryBean<K, V>
|
||||
public void setRegionName(String regionName) {
|
||||
this.regionName = regionName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the snapshots used for loading a newly <i>created</i> region. That
|
||||
* is, the snapshot will be used <i>only</i> when a new region is created -
|
||||
* if the region already exists, no loading will be performed.
|
||||
*
|
||||
* @see #setName(String)
|
||||
* @param snapshot the snapshot to set
|
||||
*/
|
||||
public void setSnapshot(Resource snapshot) {
|
||||
this.snapshot = snapshot;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,19 @@
|
||||
|
||||
package org.springframework.data.gemfire.client;
|
||||
|
||||
import static java.util.stream.StreamSupport.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 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;
|
||||
|
||||
import org.apache.geode.cache.CacheClosedException;
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
@@ -27,34 +37,32 @@ 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.apache.geode.pdx.PdxSerializer;
|
||||
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;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.data.gemfire.CacheFactoryBean;
|
||||
import org.springframework.data.gemfire.GemfireUtils;
|
||||
import org.springframework.data.gemfire.client.support.DefaultableDelegatingPoolAdapter;
|
||||
import org.springframework.data.gemfire.client.support.DelegatingPoolAdapter;
|
||||
import org.springframework.data.gemfire.config.annotation.ClientCacheConfigurer;
|
||||
import org.springframework.data.gemfire.config.xml.GemfireConstants;
|
||||
import org.springframework.data.gemfire.support.ConnectionEndpoint;
|
||||
import org.springframework.data.gemfire.support.ConnectionEndpointList;
|
||||
import org.springframework.data.gemfire.util.SpringUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* FactoryBean dedicated to creating GemFire client caches.
|
||||
* Spring {@link org.springframework.beans.factory.FactoryBean} used to create a Pivotal GemFire/Apache Geode
|
||||
* {@link ClientCache}.
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @author Lyndon Adams
|
||||
* @author John Blum
|
||||
* @see org.springframework.context.ApplicationListener
|
||||
* @see org.springframework.context.event.ContextRefreshedEvent
|
||||
* @see org.springframework.data.gemfire.CacheFactoryBean
|
||||
* @see org.springframework.data.gemfire.support.ConnectionEndpoint
|
||||
* @see org.springframework.data.gemfire.support.ConnectionEndpointList
|
||||
* @see java.net.InetSocketAddress
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @see org.apache.geode.cache.client.ClientCacheFactory
|
||||
@@ -62,6 +70,14 @@ import org.springframework.util.ObjectUtils;
|
||||
* @see org.apache.geode.cache.client.PoolManager
|
||||
* @see org.apache.geode.distributed.DistributedSystem
|
||||
* @see org.apache.geode.pdx.PdxSerializer
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see org.springframework.context.ApplicationContext
|
||||
* @see org.springframework.context.ApplicationListener
|
||||
* @see org.springframework.context.event.ContextRefreshedEvent
|
||||
* @see org.springframework.data.gemfire.CacheFactoryBean
|
||||
* @see org.springframework.data.gemfire.config.annotation.ClientCacheConfigurer
|
||||
* @see org.springframework.data.gemfire.support.ConnectionEndpoint
|
||||
* @see org.springframework.data.gemfire.support.ConnectionEndpointList
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class ClientCacheFactoryBean extends CacheFactoryBean implements ApplicationListener<ContextRefreshedEvent> {
|
||||
@@ -89,6 +105,8 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
|
||||
private Integer subscriptionMessageTrackingTimeout;
|
||||
private Integer subscriptionRedundancy;
|
||||
|
||||
private List<ClientCacheConfigurer> clientCacheConfigurers = Collections.emptyList();
|
||||
|
||||
private Long idleTimeout;
|
||||
private Long pingInterval;
|
||||
|
||||
@@ -98,37 +116,83 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
|
||||
private String poolName;
|
||||
private String serverGroup;
|
||||
|
||||
private final ClientCacheConfigurer compositeClientCacheConfigurer = (beanName, bean) ->
|
||||
nullSafeCollection(clientCacheConfigurers).forEach(clientCacheConfigurer ->
|
||||
clientCacheConfigurer.configure(beanName, bean));
|
||||
|
||||
/**
|
||||
* Post processes this {@link ClientCacheFactoryBean} before cache initialization.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
@Override
|
||||
protected void postProcessBeforeCacheInitialization(Properties gemfireProperties) {
|
||||
applyClientCacheConfigurers();
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private void applyClientCacheConfigurers() {
|
||||
applyClientCacheConfigurers(this.compositeClientCacheConfigurer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches an existing GemFire ClientCache instance from the ClientCacheFactory.
|
||||
* Null-safe operation to apply the given array of {@link ClientCacheConfigurer ClientCacheConfigurers}
|
||||
* to this {@link ClientCacheFactoryBean}.
|
||||
*
|
||||
* @param <T> is Class type extension of GemFireCache.
|
||||
* @return the existing GemFire ClientCache instance if available.
|
||||
* @throws org.apache.geode.cache.CacheClosedException if an existing GemFire Cache instance does not exist.
|
||||
* @throws java.lang.IllegalStateException if the GemFire cache instance is not a ClientCache.
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @param clientCacheConfigurers array of {@link ClientCacheConfigurer ClientCacheConfigurers} applied to
|
||||
* this {@link ClientCacheFactoryBean}.
|
||||
* @see org.springframework.data.gemfire.config.annotation.ClientCacheConfigurer
|
||||
* @see #applyClientCacheConfigurers(Iterable)
|
||||
*/
|
||||
protected void applyClientCacheConfigurers(ClientCacheConfigurer... clientCacheConfigurers) {
|
||||
applyClientCacheConfigurers(Arrays.asList(nullSafeArray(clientCacheConfigurers, ClientCacheConfigurer.class)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe operation to apply the given {@link Iterable} of {@link ClientCacheConfigurer ClientCacheConfigurers}
|
||||
* to this {@link ClientCacheFactoryBean}.
|
||||
*
|
||||
* @param clientCacheConfigurers {@link Iterable} of {@link ClientCacheConfigurer ClientCacheConfigurers}
|
||||
* applied to this {@link ClientCacheFactoryBean}.
|
||||
* @see org.springframework.data.gemfire.config.annotation.ClientCacheConfigurer
|
||||
* @see java.lang.Iterable
|
||||
*/
|
||||
protected void applyClientCacheConfigurers(Iterable<ClientCacheConfigurer> clientCacheConfigurers) {
|
||||
stream(nullSafeIterable(clientCacheConfigurers).spliterator(), false)
|
||||
.forEach(clientCacheConfigurer -> clientCacheConfigurer.configure(getBeanName(), this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches an existing {@link ClientCache} instance from the {@link ClientCacheFactory}.
|
||||
*
|
||||
* @param <T> parameterized {@link Class} type extension of {@link GemFireCache}.
|
||||
* @return an existing {@link ClientCache} instance if available.
|
||||
* @throws org.apache.geode.cache.CacheClosedException if an existing {@link ClientCache} instance does not exist.
|
||||
* @see org.apache.geode.cache.client.ClientCacheFactory#getAnyInstance()
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see #getCache()
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T extends GemFireCache> T fetchCache() {
|
||||
ClientCache cache = getCache();
|
||||
return (T) (cache != null ? cache : ClientCacheFactory.getAnyInstance());
|
||||
return (T) Optional.ofNullable(getCache()).orElseGet(ClientCacheFactory::getAnyInstance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the GemFire System properties used to configure the GemFire ClientCache instance.
|
||||
* Resolves the Pivotal GemFire/Apache Geode {@link Properties} used to configure the {@link ClientCache}.
|
||||
*
|
||||
* @return a Properties object containing GemFire System properties used to configure
|
||||
* the GemFire ClientCache instance.
|
||||
* @return the resolved Pivotal GemFire/Apache Geode {@link Properties} used to configure the {@link ClientCache}.
|
||||
* @see org.apache.geode.distributed.DistributedSystem#getProperties()
|
||||
* @see #getDistributedSystem()
|
||||
*/
|
||||
@Override
|
||||
protected Properties resolveProperties() {
|
||||
Properties gemfireProperties = super.resolveProperties();
|
||||
|
||||
Properties gemfireProperties = super.resolveProperties();
|
||||
DistributedSystem distributedSystem = getDistributedSystem();
|
||||
|
||||
if (GemfireUtils.isConnected(distributedSystem)) {
|
||||
@@ -137,24 +201,32 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
|
||||
gemfireProperties = distributedSystemProperties;
|
||||
}
|
||||
|
||||
GemfireUtils.configureDurableClient(gemfireProperties, durableClientId, durableClientTimeout);
|
||||
GemfireUtils.configureDurableClient(gemfireProperties, getDurableClientId(), getDurableClientTimeout());
|
||||
|
||||
return gemfireProperties;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
/**
|
||||
* Returns the {@link DistributedSystem} formed from cache initialization.
|
||||
*
|
||||
* @param <T> {@link Class} type of the {@link DistributedSystem}.
|
||||
* @return an instance of the {@link DistributedSystem}.
|
||||
* @see org.apache.geode.distributed.DistributedSystem
|
||||
*/
|
||||
<T extends DistributedSystem> T getDistributedSystem() {
|
||||
return GemfireUtils.getDistributedSystem();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of GemFire factory initialized with the given GemFire System Properties
|
||||
* to create an instance of a GemFire cache.
|
||||
* 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}.
|
||||
*
|
||||
* @param gemfireProperties a Properties object containing GemFire System properties.
|
||||
* @return an instance of a GemFire factory used to create a GemFire cache instance.
|
||||
* @see java.util.Properties
|
||||
* @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}.
|
||||
* @see org.apache.geode.cache.client.ClientCacheFactory
|
||||
* @see java.util.Properties
|
||||
*/
|
||||
@Override
|
||||
protected Object createFactory(Properties gemfireProperties) {
|
||||
@@ -162,61 +234,52 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the GemFire factory used to create the GemFire client cache instance. Sets PDX options
|
||||
* specified by the user.
|
||||
* Prepares and initializes the {@link ClientCacheFactory} used to create the {@link ClientCache}.
|
||||
*
|
||||
* @param factory the GemFire factory used to create an instance of the GemFire client cache.
|
||||
* @return the initialized GemFire client cache factory.
|
||||
* @see #isPdxOptionsSpecified()
|
||||
* Sets PDX 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)
|
||||
*/
|
||||
@Override
|
||||
protected Object prepareFactory(final Object factory) {
|
||||
protected Object prepareFactory(Object factory) {
|
||||
return initializePool(initializePdx((ClientCacheFactory) factory));
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the PDX settings on the {@link ClientCacheFactory}.
|
||||
* Configure PDX for the {@link ClientCacheFactory}.
|
||||
*
|
||||
* @param clientCacheFactory the GemFire {@link ClientCacheFactory} used to configure and create
|
||||
* a GemFire {@link ClientCache}.
|
||||
* @param clientCacheFactory {@link ClientCacheFactory} used to configure PDX.
|
||||
* @return the given {@link ClientCacheFactory}
|
||||
* @see org.apache.geode.cache.client.ClientCacheFactory
|
||||
*/
|
||||
ClientCacheFactory initializePdx(ClientCacheFactory clientCacheFactory) {
|
||||
if (isPdxOptionsSpecified()) {
|
||||
if (getPdxSerializer() != null) {
|
||||
Assert.isInstanceOf(PdxSerializer.class, getPdxSerializer(),
|
||||
String.format("[%1$s] of type [%2$s] is not a PdxSerializer;", getPdxSerializer(),
|
||||
ObjectUtils.nullSafeClassName(getPdxSerializer())));
|
||||
|
||||
clientCacheFactory.setPdxSerializer((PdxSerializer) getPdxSerializer());
|
||||
}
|
||||
if (getPdxDiskStoreName() != null) {
|
||||
clientCacheFactory.setPdxDiskStore(getPdxDiskStoreName());
|
||||
}
|
||||
if (getPdxIgnoreUnreadFields() != null) {
|
||||
clientCacheFactory.setPdxIgnoreUnreadFields(getPdxIgnoreUnreadFields());
|
||||
}
|
||||
if (getPdxPersistent() != null) {
|
||||
clientCacheFactory.setPdxPersistent(getPdxPersistent());
|
||||
}
|
||||
if (getPdxReadSerialized() != null) {
|
||||
clientCacheFactory.setPdxReadSerialized(getPdxReadSerialized());
|
||||
}
|
||||
}
|
||||
Optional.ofNullable(getPdxSerializer()).ifPresent(clientCacheFactory::setPdxSerializer);
|
||||
|
||||
Optional.ofNullable(getPdxDiskStoreName()).filter(StringUtils::hasText)
|
||||
.ifPresent(clientCacheFactory::setPdxDiskStore);
|
||||
|
||||
Optional.ofNullable(getPdxIgnoreUnreadFields()).ifPresent(clientCacheFactory::setPdxIgnoreUnreadFields);
|
||||
|
||||
Optional.ofNullable(getPdxPersistent()).ifPresent(clientCacheFactory::setPdxPersistent);
|
||||
|
||||
Optional.ofNullable(getPdxReadSerialized()).ifPresent(clientCacheFactory::setPdxReadSerialized);
|
||||
|
||||
return clientCacheFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the {@link Pool} settings on the {@link ClientCacheFactory} with a given {@link Pool} instance
|
||||
* or named {@link Pool}.
|
||||
* Configure the {@literal DEFAULT} {@link Pool} configuration settings with the {@link ClientCacheFactory}
|
||||
* using a given {@link Pool} instance or a named {@link Pool}.
|
||||
*
|
||||
* @param clientCacheFactory the GemFire {@link ClientCacheFactory} used to configure and create
|
||||
* a GemFire {@link ClientCache}.
|
||||
* @param clientCacheFactory {@link ClientCacheFactory} use to configure the {@literal DEFAULT} {@link Pool}.
|
||||
* @see org.apache.geode.cache.client.ClientCacheFactory
|
||||
* @see org.apache.geode.cache.client.Pool
|
||||
*/
|
||||
ClientCacheFactory initializePool(ClientCacheFactory clientCacheFactory) {
|
||||
|
||||
DefaultableDelegatingPoolAdapter pool = DefaultableDelegatingPoolAdapter.from(
|
||||
DelegatingPoolAdapter.from(resolvePool())).preferDefault();
|
||||
|
||||
@@ -239,48 +302,51 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
|
||||
clientCacheFactory.setPoolSubscriptionRedundancy(pool.getSubscriptionRedundancy(getSubscriptionRedundancy()));
|
||||
clientCacheFactory.setPoolThreadLocalConnections(pool.getThreadLocalConnections(getThreadLocalConnections()));
|
||||
|
||||
boolean noServers = getServers().isEmpty();
|
||||
boolean hasServers = !noServers;
|
||||
final AtomicBoolean noServers = new AtomicBoolean(getServers().isEmpty());
|
||||
|
||||
boolean hasServers = !noServers.get();
|
||||
boolean noLocators = getLocators().isEmpty();
|
||||
boolean hasLocators = !noLocators;
|
||||
|
||||
if (hasServers || noLocators) {
|
||||
Iterable<InetSocketAddress> servers = pool.getServers(getServers().toInetSocketAddresses());
|
||||
|
||||
for (InetSocketAddress server : servers) {
|
||||
stream(servers.spliterator(), false).forEach(server -> {
|
||||
clientCacheFactory.addPoolServer(server.getHostName(), server.getPort());
|
||||
noServers = false;
|
||||
}
|
||||
noServers.set(false);
|
||||
});
|
||||
}
|
||||
|
||||
if (hasLocators || noServers) {
|
||||
if (hasLocators || noServers.get()) {
|
||||
Iterable<InetSocketAddress> locators = pool.getLocators(getLocators().toInetSocketAddresses());
|
||||
|
||||
for (InetSocketAddress locator : locators) {
|
||||
clientCacheFactory.addPoolLocator(locator.getHostName(), locator.getPort());
|
||||
}
|
||||
stream(locators.spliterator(), false).forEach(locator ->
|
||||
clientCacheFactory.addPoolLocator(locator.getHostName(), locator.getPort()));
|
||||
}
|
||||
|
||||
return clientCacheFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the appropriate GemFire {@link Pool} from Spring configuration that will be used to configure
|
||||
* the GemFire {@link ClientCache}.
|
||||
* Resolves an appropriate {@link Pool} from the Spring container that will be used to configure
|
||||
* the {@link ClientCache}.
|
||||
*
|
||||
* @return the resolved GemFire {@link Pool}.
|
||||
* @see org.apache.geode.cache.client.PoolManager#find(String)
|
||||
* @return the resolved {@link Pool}.
|
||||
* @see org.apache.geode.cache.client.Pool
|
||||
* @see #findPool(String)
|
||||
*/
|
||||
Pool resolvePool() {
|
||||
Pool localPool = getPool();
|
||||
|
||||
if (localPool == null) {
|
||||
String poolName = SpringUtils.defaultIfNull(getPoolName(), GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME);
|
||||
|
||||
String poolName = Optional.ofNullable(getPoolName()).filter(StringUtils::hasText)
|
||||
.orElse(GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME);
|
||||
|
||||
localPool = findPool(poolName);
|
||||
|
||||
if (localPool == null) {
|
||||
|
||||
BeanFactory beanFactory = getBeanFactory();
|
||||
|
||||
if (beanFactory instanceof ListableBeanFactory) {
|
||||
@@ -295,8 +361,8 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
|
||||
}
|
||||
}
|
||||
catch (BeansException e) {
|
||||
log.info(String.format("unable to resolve bean of type [%1$s] with name [%2$s]",
|
||||
PoolFactoryBean.class.getName(), poolName));
|
||||
logInfo("Unable to resolve bean of type [%1$s] with name [%2$s]",
|
||||
PoolFactoryBean.class.getName(), poolName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -306,11 +372,11 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to find a GemFire {@link Pool} with the given name.
|
||||
* Attempts to find a {@link Pool} with the given {@link String name}.
|
||||
*
|
||||
* @param name a String indicating the name of the GemFire {@link Pool} to find.
|
||||
* @return a {@link Pool} instance with the given name registered in GemFire or <code>null</code> if no {@link Pool}
|
||||
* with name exists.
|
||||
* @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
|
||||
*/
|
||||
@@ -319,11 +385,11 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new GemFire cache instance using the provided factory.
|
||||
* Creates a new {@link ClientCache} instance using the provided factory.
|
||||
*
|
||||
* @param <T> parameterized Class type extension of {@link GemFireCache}.
|
||||
* @param factory the appropriate GemFire factory used to create a cache instance.
|
||||
* @return an instance of the GemFire cache.
|
||||
* @param <T> parameterized {@link Class} type extension of {@link GemFireCache}.
|
||||
* @param factory instance of {@link ClientCacheFactory}.
|
||||
* @return a new instance of {@link ClientCache} created by the provided factory.
|
||||
* @see org.apache.geode.cache.client.ClientCacheFactory#create()
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
*/
|
||||
@@ -334,28 +400,36 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
|
||||
}
|
||||
|
||||
/**
|
||||
* Inform the GemFire cluster that this client cache is ready to receive events iff the client is non-durable.
|
||||
* Inform the Pivotal GemFire/Apache Geode cluster that this cache client is ready to receive events
|
||||
* iff the client is non-durable.
|
||||
*
|
||||
* @param event the ApplicationContextEvent fired when the ApplicationContext is refreshed.
|
||||
* @param event {@link ApplicationContextEvent} fired when the {@link ApplicationContext} is refreshed.
|
||||
* @see org.apache.geode.cache.client.ClientCache#readyForEvents()
|
||||
* @see #getReadyForEvents()
|
||||
* @see #getObject()
|
||||
* @see #isReadyForEvents()
|
||||
* @see #fetchCache()
|
||||
*/
|
||||
@Override
|
||||
public void onApplicationEvent(final ContextRefreshedEvent event) {
|
||||
public void onApplicationEvent(ContextRefreshedEvent event) {
|
||||
if (isReadyForEvents()) {
|
||||
try {
|
||||
((ClientCache) fetchCache()).readyForEvents();
|
||||
this.<ClientCache>fetchCache().readyForEvents();
|
||||
}
|
||||
catch (IllegalStateException | CacheClosedException ignore) {
|
||||
// IllegalStateException thrown if clientCache.readyForEvents() is called on a non-durable client
|
||||
// CacheClosedException is throw when cache is closed or was shutdown so ready-for-events is moot
|
||||
// thrown if clientCache.readyForEvents() is called on a non-durable client
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
<<<<<<< HEAD
|
||||
* @inheritDoc
|
||||
=======
|
||||
* Null-safe internal method used to close the {@link ClientCache} and preserve durability.
|
||||
*
|
||||
* @param cache {@link GemFireCache} to close.
|
||||
* @see org.apache.geode.cache.client.ClientCache#close(boolean)
|
||||
* @see #isKeepAlive()
|
||||
>>>>>>> c22ebe6... DATAGEODE-12 - Introduce Spring Configurers to flexibly alter Spring Data GemFire configuration when using Annotation config.
|
||||
*/
|
||||
@Override
|
||||
protected void close(GemFireCache cache) {
|
||||
@@ -363,12 +437,19 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
|
||||
}
|
||||
|
||||
/**
|
||||
<<<<<<< HEAD
|
||||
* @inheritDoc
|
||||
=======
|
||||
* Returns the {@link Class} type of the {@link GemFireCache} produced by this {@link ClientCacheFactoryBean}.
|
||||
*
|
||||
* @return the {@link Class} type of the {@link GemFireCache} produced by this {@link ClientCacheFactoryBean}.
|
||||
* @see org.springframework.beans.factory.FactoryBean#getObjectType()
|
||||
>>>>>>> c22ebe6... DATAGEODE-12 - Introduce Spring Configurers to flexibly alter Spring Data GemFire configuration when using Annotation config.
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Class<? extends GemFireCache> getObjectType() {
|
||||
ClientCache cache = getCache();
|
||||
return (cache != null ? cache.getClass() : ClientCache.class);
|
||||
return Optional.ofNullable(getCache()).map(Object::getClass).orElse((Class) ClientCache.class);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@@ -391,6 +472,42 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
|
||||
this.servers.add(servers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe operation to set an array of {@link ClientCacheConfigurer ClientCacheConfigurers} used to apply
|
||||
* additional configuration to this {@link ClientCacheFactoryBean} when using Annotation-based configuration.
|
||||
*
|
||||
* @param clientCacheConfigurers array of {@link ClientCacheConfigurer ClientCacheConfigurers} used to apply
|
||||
* additional configuration to this {@link ClientCacheFactoryBean}.
|
||||
* @see org.springframework.data.gemfire.config.annotation.ClientCacheConfigurer
|
||||
* @see #setClientCacheConfigurers(List)
|
||||
*/
|
||||
public void setClientCacheConfigurers(ClientCacheConfigurer... clientCacheConfigurers) {
|
||||
setClientCacheConfigurers(Arrays.asList(nullSafeArray(clientCacheConfigurers, ClientCacheConfigurer.class)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe operation to set an {@link Iterable} of {@link ClientCacheConfigurer ClientCacheConfigurers} to apply
|
||||
* additional configuration to this {@link ClientCacheFactoryBean} when using Annotation-based configuration.
|
||||
*
|
||||
* @param peerCacheConfigurers {@link Iterable} of {@link ClientCacheConfigurer ClientCacheConfigurers} used to apply
|
||||
* additional configuration to this {@link ClientCacheFactoryBean}.
|
||||
* @see org.springframework.data.gemfire.config.annotation.ClientCacheConfigurer
|
||||
*/
|
||||
public void setClientCacheConfigurers(List<ClientCacheConfigurer> peerCacheConfigurers) {
|
||||
this.clientCacheConfigurers = Optional.ofNullable(peerCacheConfigurers).orElseGet(Collections::emptyList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the Composite {@link ClientCacheConfigurer} used to apply additional configuration
|
||||
* to this {@link ClientCacheFactoryBean} on Spring container initialization.
|
||||
*
|
||||
* @return the Composite {@link ClientCacheConfigurer}.
|
||||
* @see org.springframework.data.gemfire.config.annotation.ClientCacheConfigurer
|
||||
*/
|
||||
public ClientCacheConfigurer getCompositeClientCacheConfigurer() {
|
||||
return this.compositeClientCacheConfigurer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the GemFire System property 'durable-client-id' to indicate to the server that this client is durable.
|
||||
*
|
||||
@@ -407,7 +524,7 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
|
||||
* @return a String value indicating the durable client id.
|
||||
*/
|
||||
public String getDurableClientId() {
|
||||
return durableClientId;
|
||||
return this.durableClientId;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -429,15 +546,15 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
|
||||
* the durable client's queue around.
|
||||
*/
|
||||
public Integer getDurableClientTimeout() {
|
||||
return durableClientTimeout;
|
||||
return this.durableClientTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public final void setEnableAutoReconnect(final Boolean enableAutoReconnect) {
|
||||
throw new UnsupportedOperationException("Auto-reconnect does not apply to clients.");
|
||||
public final void setEnableAutoReconnect(Boolean enableAutoReconnect) {
|
||||
throw new UnsupportedOperationException("Auto-reconnect does not apply to clients");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -572,7 +689,7 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
|
||||
* to the GemFire cluster.
|
||||
*/
|
||||
public Pool getPool() {
|
||||
return pool;
|
||||
return this.pool;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -780,7 +897,7 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
|
||||
*/
|
||||
@Override
|
||||
public final void setUseClusterConfiguration(Boolean useClusterConfiguration) {
|
||||
throw new UnsupportedOperationException("Shared, cluster-based configuration is not applicable for clients.");
|
||||
throw new UnsupportedOperationException("Cluster-based Configuration is not applicable for clients");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,10 +16,18 @@
|
||||
|
||||
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 org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.geode.cache.CacheListener;
|
||||
import org.apache.geode.cache.CacheLoader;
|
||||
import org.apache.geode.cache.CacheWriter;
|
||||
@@ -33,28 +41,22 @@ import org.apache.geode.cache.client.ClientRegionFactory;
|
||||
import org.apache.geode.cache.client.ClientRegionShortcut;
|
||||
import org.apache.geode.cache.client.Pool;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.core.io.Resource;
|
||||
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.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Spring {@link FactoryBean} used to create a GemFire client cache {@link Region}.
|
||||
* Spring {@link FactoryBean} used to construct, configure and initialize a client {@link Region}.
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @author David Turanski
|
||||
* @author John Blum
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see org.springframework.beans.factory.BeanFactoryAware
|
||||
* @see org.springframework.beans.factory.DisposableBean
|
||||
* @see org.springframework.data.gemfire.RegionLookupFactoryBean
|
||||
* @see org.apache.geode.cache.DataPolicy
|
||||
* @see org.apache.geode.cache.EvictionAttributes
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
@@ -64,18 +66,18 @@ import org.springframework.util.StringUtils;
|
||||
* @see org.apache.geode.cache.client.ClientRegionFactory
|
||||
* @see org.apache.geode.cache.client.ClientRegionShortcut
|
||||
* @see org.apache.geode.cache.client.Pool
|
||||
* @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 org.springframework.data.gemfire.config.annotation.RegionConfigurer
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
|
||||
implements BeanFactoryAware, DisposableBean {
|
||||
|
||||
private static final Log log = LogFactory.getLog(ClientRegionFactoryBean.class);
|
||||
public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> implements DisposableBean {
|
||||
|
||||
private boolean close = false;
|
||||
private boolean destroy = false;
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
private Boolean persistent;
|
||||
|
||||
private CacheListener<K, V>[] cacheListeners;
|
||||
@@ -87,7 +89,7 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
|
||||
private Class<K> keyConstraint;
|
||||
private Class<V> valueConstraint;
|
||||
|
||||
private ClientRegionShortcut shortcut = null;
|
||||
private ClientRegionShortcut shortcut;
|
||||
|
||||
private DataPolicy dataPolicy;
|
||||
|
||||
@@ -95,97 +97,183 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
|
||||
|
||||
private Interest<K>[] interests;
|
||||
|
||||
private List<RegionConfigurer> regionConfigurers = Collections.emptyList();
|
||||
|
||||
private RegionAttributes<K, V> attributes;
|
||||
|
||||
private Resource snapshot;
|
||||
private RegionConfigurer compositeRegionConfigurer = new RegionConfigurer() {
|
||||
|
||||
@Override
|
||||
public void configure(String beanName, ClientRegionFactoryBean<?, ?> bean) {
|
||||
nullSafeCollection(regionConfigurers)
|
||||
.forEach(regionConfigurer -> regionConfigurer.configure(beanName, bean));
|
||||
}
|
||||
};
|
||||
|
||||
private String diskStoreName;
|
||||
private String poolName;
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* Creates a new {@link Region} with the given {@link String name}.
|
||||
*
|
||||
* @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 org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.Region
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
super.afterPropertiesSet();
|
||||
postProcess(getRegion());
|
||||
}
|
||||
protected Region<K, V> createRegion(GemFireCache gemfireCache, String regionName) throws Exception {
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
protected Region<K, V> lookupRegion(GemFireCache cache, String regionName) throws Exception {
|
||||
Assert.isTrue(GemfireUtils.isClient(cache), "A ClientCache is required to create a client Region");
|
||||
applyRegionConfigurers(regionName);
|
||||
|
||||
ClientCache cache = resolveCache(gemfireCache);
|
||||
|
||||
ClientRegionFactory<K, V> clientRegionFactory =
|
||||
((ClientCache) cache).createClientRegionFactory(resolveClientRegionShortcut());
|
||||
configure(createClientRegionFactory(cache, resolveClientRegionShortcut()));
|
||||
|
||||
setAttributes(clientRegionFactory);
|
||||
addCacheListeners(clientRegionFactory);
|
||||
setDiskStoreName(clientRegionFactory);
|
||||
setEvictionAttributes(clientRegionFactory);
|
||||
setPoolName(clientRegionFactory);
|
||||
|
||||
if (keyConstraint != null) {
|
||||
clientRegionFactory.setKeyConstraint(keyConstraint);
|
||||
}
|
||||
|
||||
if (valueConstraint != null) {
|
||||
clientRegionFactory.setValueConstraint(valueConstraint);
|
||||
}
|
||||
|
||||
return logCreateRegionEvent(create(clientRegionFactory, regionName));
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private Region<K, V> create(ClientRegionFactory<K, V> clientRegionFactory, String regionName) {
|
||||
return (getParent() != null ? clientRegionFactory.createSubregion(getParent(), regionName)
|
||||
: clientRegionFactory.create(regionName));
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private Region<K, V> logCreateRegionEvent(Region<K, V> region) {
|
||||
if (log.isInfoEnabled()) {
|
||||
if (getParent() != null) {
|
||||
log.info(String.format("Created new client cache Sub-Region [%1$s] under parent Region [%2$s].",
|
||||
region.getName(), getParent().getName()));
|
||||
}
|
||||
else {
|
||||
log.info(String.format("Created new client cache Region [%s].", region.getName()));
|
||||
}
|
||||
}
|
||||
@SuppressWarnings("all")
|
||||
Region<K, V> region = newRegion(clientRegionFactory, getParent(), regionName);
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private void applyRegionConfigurers(String regionName) {
|
||||
applyRegionConfigurers(regionName, getCompositeRegionConfigurer());
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the {@link ClientRegionShortcut} used to configure the data policy of the client {@link Region}.
|
||||
* Null-safe operation to apply the given array of {@link RegionConfigurer RegionConfigurers}
|
||||
* to this {@link ClientRegionFactoryBean}.
|
||||
*
|
||||
* @return a {@link ClientRegionShortcut} used to configure the data policy of the client {@link Region}.
|
||||
* @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)
|
||||
*/
|
||||
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 <gfe:*-region> 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 <gfe:*-region> 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) {
|
||||
|
||||
return Optional.ofNullable(parentRegion)
|
||||
.map(parent -> {
|
||||
logInfo("Creating client Subregion [%1$s] with parent Region [%2$s]",
|
||||
regionName, parent.getName());
|
||||
|
||||
return clientRegionFactory.<K, V>createSubregion(parent, regionName);
|
||||
})
|
||||
.orElseGet(() -> {
|
||||
logInfo("Created client Region [%s]", regionName);
|
||||
|
||||
return clientRegionFactory.create(regionName);
|
||||
});
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private ClientCache resolveCache(GemFireCache gemfireCache) {
|
||||
|
||||
return Optional.ofNullable(gemfireCache)
|
||||
.filter(GemfireUtils::isClient)
|
||||
.map(cache -> (ClientCache) cache)
|
||||
.orElseThrow(() -> newIllegalArgumentException("ClientCache is required"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the {@link ClientRegionShortcut} used to configure the {@link DataPolicy} of the client {@link Region}.
|
||||
*
|
||||
* @return a {@link ClientRegionShortcut} used to configure the {@link DataPolicy} of the client {@link Region}.
|
||||
* @see org.apache.geode.cache.client.ClientRegionShortcut
|
||||
* @see org.apache.geode.cache.DataPolicy
|
||||
*/
|
||||
ClientRegionShortcut resolveClientRegionShortcut() {
|
||||
ClientRegionShortcut resolvedShortcut = this.shortcut;
|
||||
|
||||
if (resolvedShortcut == null) {
|
||||
if (this.dataPolicy != null) {
|
||||
assertDataPolicyAndPersistentAttributeAreCompatible(this.dataPolicy);
|
||||
|
||||
if (DataPolicy.EMPTY.equals(this.dataPolicy)) {
|
||||
DataPolicy dataPolicy = this.dataPolicy;
|
||||
|
||||
if (dataPolicy != null) {
|
||||
|
||||
assertDataPolicyAndPersistentAttributeAreCompatible(dataPolicy);
|
||||
|
||||
if (DataPolicy.EMPTY.equals(dataPolicy)) {
|
||||
resolvedShortcut = ClientRegionShortcut.PROXY;
|
||||
}
|
||||
else if (DataPolicy.NORMAL.equals(this.dataPolicy)) {
|
||||
else if (DataPolicy.NORMAL.equals(dataPolicy)) {
|
||||
resolvedShortcut = ClientRegionShortcut.CACHING_PROXY;
|
||||
}
|
||||
else if (DataPolicy.PERSISTENT_REPLICATE.equals(this.dataPolicy)) {
|
||||
else if (DataPolicy.PERSISTENT_REPLICATE.equals(dataPolicy)) {
|
||||
resolvedShortcut = ClientRegionShortcut.LOCAL_PERSISTENT;
|
||||
}
|
||||
else {
|
||||
// NOTE the DataPolicy validation is based on the ClientRegionShortcut initialization logic
|
||||
// in org.apache.geode.internal.cache.GemFireCacheImpl.initializeClientRegionShortcuts
|
||||
throw new IllegalArgumentException(String.format("Data Policy '%s' is invalid for Client Regions",
|
||||
this.dataPolicy));
|
||||
throw newIllegalArgumentException("Data Policy [%s] is not valid for the client Region", dataPolicy);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -194,145 +282,20 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE the ClientRegionShortcut and Persistent attribute will be compatible if the shortcut
|
||||
// was derived from the Data Policy.
|
||||
// NOTE the ClientRegionShortcut and Persistent attribute will be compatible
|
||||
// if the shortcut was derived from the Data Policy.
|
||||
assertClientRegionShortcutAndPersistentAttributeAreCompatible(resolvedShortcut);
|
||||
|
||||
return resolvedShortcut;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that the settings for ClientRegionShortcut and the 'persistent' attribute in <gfe:*-region> elements
|
||||
* are compatible.
|
||||
*
|
||||
* @param resolvedShortcut the GemFire ClientRegionShortcut resolved form the Spring GemFire XML namespace
|
||||
* configuration meta-data.
|
||||
* @see #isPersistent()
|
||||
* @see #isNotPersistent()
|
||||
* @see org.apache.geode.cache.client.ClientRegionShortcut
|
||||
*/
|
||||
private void assertClientRegionShortcutAndPersistentAttributeAreCompatible(ClientRegionShortcut resolvedShortcut) {
|
||||
final boolean persistentNotSpecified = (this.persistent == null);
|
||||
|
||||
if (ClientRegionShortcut.LOCAL_PERSISTENT.equals(resolvedShortcut)
|
||||
|| ClientRegionShortcut.LOCAL_PERSISTENT_OVERFLOW.equals(resolvedShortcut)) {
|
||||
Assert.isTrue(persistentNotSpecified || isPersistent(), String.format(
|
||||
"Client Region Shortcut '%s' is invalid when persistent is false", resolvedShortcut));
|
||||
}
|
||||
else {
|
||||
Assert.isTrue(persistentNotSpecified || isNotPersistent(), String.format(
|
||||
"Client Region Shortcut '%s' is invalid when persistent is true", resolvedShortcut));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that the settings for Data Policy and the 'persistent' attribute in <gfe:*-region> 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
|
||||
*/
|
||||
private void assertDataPolicyAndPersistentAttributeAreCompatible(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 without persistence, so...
|
||||
Assert.isTrue(isPersistentUnspecified() || isNotPersistent(), String.format(
|
||||
"Data Policy '%s' is invalid when persistent is true", resolvedDataPolicy));
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private ClientRegionFactory<K, V> setAttributes(ClientRegionFactory<K, V> clientRegionFactory) {
|
||||
RegionAttributes<K, V> localAttributes = this.attributes;
|
||||
|
||||
if (localAttributes != null) {
|
||||
clientRegionFactory.setCloningEnabled(localAttributes.getCloningEnabled());
|
||||
clientRegionFactory.setCompressor(localAttributes.getCompressor());
|
||||
clientRegionFactory.setConcurrencyChecksEnabled(localAttributes.getConcurrencyChecksEnabled());
|
||||
clientRegionFactory.setConcurrencyLevel(localAttributes.getConcurrencyLevel());
|
||||
clientRegionFactory.setCustomEntryIdleTimeout(localAttributes.getCustomEntryIdleTimeout());
|
||||
clientRegionFactory.setCustomEntryTimeToLive(localAttributes.getCustomEntryTimeToLive());
|
||||
clientRegionFactory.setDiskStoreName(localAttributes.getDiskStoreName());
|
||||
clientRegionFactory.setDiskSynchronous(localAttributes.isDiskSynchronous());
|
||||
clientRegionFactory.setEntryIdleTimeout(localAttributes.getEntryIdleTimeout());
|
||||
clientRegionFactory.setEntryTimeToLive(localAttributes.getEntryTimeToLive());
|
||||
clientRegionFactory.setEvictionAttributes(localAttributes.getEvictionAttributes());
|
||||
clientRegionFactory.setInitialCapacity(localAttributes.getInitialCapacity());
|
||||
clientRegionFactory.setKeyConstraint(localAttributes.getKeyConstraint());
|
||||
clientRegionFactory.setLoadFactor(localAttributes.getLoadFactor());
|
||||
clientRegionFactory.setPoolName(localAttributes.getPoolName());
|
||||
clientRegionFactory.setRegionIdleTimeout(localAttributes.getRegionIdleTimeout());
|
||||
clientRegionFactory.setRegionTimeToLive(localAttributes.getRegionTimeToLive());
|
||||
clientRegionFactory.setStatisticsEnabled(localAttributes.getStatisticsEnabled());
|
||||
clientRegionFactory.setValueConstraint(localAttributes.getValueConstraint());
|
||||
}
|
||||
|
||||
return clientRegionFactory;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@SuppressWarnings("unchecked")
|
||||
private ClientRegionFactory<K, V> addCacheListeners(ClientRegionFactory<K, V> clientRegionFactory) {
|
||||
for (CacheListener<K, V> cacheListener : this.<K, V>attributesCacheListeners()) {
|
||||
clientRegionFactory.addCacheListener(cacheListener);
|
||||
}
|
||||
|
||||
for (CacheListener<K, V> cacheListener : nullSafeArray(this.cacheListeners, CacheListener.class)) {
|
||||
clientRegionFactory.addCacheListener(cacheListener);
|
||||
}
|
||||
|
||||
return clientRegionFactory;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@SuppressWarnings("unchecked")
|
||||
private <K, V> CacheListener<K, V>[] attributesCacheListeners() {
|
||||
CacheListener[] cacheListeners = (this.attributes != null ? this.attributes.getCacheListeners() : null);
|
||||
return nullSafeArray(cacheListeners, CacheListener.class);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private ClientRegionFactory<K, V> setDiskStoreName(ClientRegionFactory<K, V> clientRegionFactory) {
|
||||
if (StringUtils.hasText(this.diskStoreName)) {
|
||||
clientRegionFactory.setDiskStoreName(this.diskStoreName);
|
||||
}
|
||||
|
||||
return clientRegionFactory;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private ClientRegionFactory<K, V> setEvictionAttributes(ClientRegionFactory<K, V> clientRegionFactory) {
|
||||
if (this.evictionAttributes != null) {
|
||||
clientRegionFactory.setEvictionAttributes(this.evictionAttributes);
|
||||
}
|
||||
|
||||
return clientRegionFactory;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private ClientRegionFactory<K, V> setPoolName(ClientRegionFactory<K, V> clientRegionFactory) {
|
||||
String poolName = resolvePoolName();
|
||||
|
||||
if (StringUtils.hasText(poolName)) {
|
||||
clientRegionFactory.setPoolName(eagerlyInitializePool(poolName));
|
||||
}
|
||||
|
||||
return clientRegionFactory;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private String resolvePoolName() {
|
||||
String poolName = this.poolName;
|
||||
|
||||
if (!StringUtils.hasText(poolName)) {
|
||||
String defaultPoolName = GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME;
|
||||
poolName = (this.beanFactory.containsBean(defaultPoolName) ? defaultPoolName : poolName);
|
||||
poolName = (getBeanFactory().containsBean(defaultPoolName) ? defaultPoolName : poolName);
|
||||
}
|
||||
|
||||
return poolName;
|
||||
@@ -340,35 +303,117 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private String eagerlyInitializePool(String poolName) {
|
||||
try {
|
||||
if (this.beanFactory.isTypeMatch(poolName, Pool.class)) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(String.format("Found bean definition for Pool [%1$s]; Eagerly initializing...", poolName));
|
||||
}
|
||||
|
||||
this.beanFactory.getBean(poolName, Pool.class);
|
||||
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) {
|
||||
log.warn(ignore.getMessage());
|
||||
getLog().warn(ignore.getMessage(), ignore.getCause());
|
||||
}
|
||||
|
||||
return poolName;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected void postProcess(Region<K, V> region) throws Exception {
|
||||
loadSnapshot(region);
|
||||
registerInterests(region);
|
||||
setCacheLoader(region);
|
||||
setCacheWriter(region);
|
||||
/**
|
||||
* Constructs a new instance of {@link ClientRegionFactory} using the given {@link ClientCache}
|
||||
* and {@link ClientRegionShortcut}.
|
||||
*
|
||||
* @param cache reference to the {@link ClientCache}.
|
||||
* @param shortcut {@link ClientRegionShortcut} used to specify the client {@link 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 cache, ClientRegionShortcut shortcut) {
|
||||
return cache.createClientRegionFactory(shortcut);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private Region<K, V> loadSnapshot(Region<K, V> region) throws Exception {
|
||||
if (snapshot != null) {
|
||||
region.loadSnapshot(snapshot.getInputStream());
|
||||
}
|
||||
/**
|
||||
* Configures the given {@link ClientRegionFactoryBean} from the configuration settings
|
||||
* of this {@link ClientRegionFactoryBean}.
|
||||
*
|
||||
* @param clientRegionFactory {@link ClientRegionFactory} to configure.
|
||||
* @return the given {@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.setPoolName(attributes.getPoolName());
|
||||
clientRegionFactory.setRegionIdleTimeout(attributes.getRegionIdleTimeout());
|
||||
clientRegionFactory.setRegionTimeToLive(attributes.getRegionTimeToLive());
|
||||
clientRegionFactory.setStatisticsEnabled(attributes.getStatisticsEnabled());
|
||||
clientRegionFactory.setValueConstraint(attributes.getValueConstraint());
|
||||
});
|
||||
|
||||
stream(nullSafeArray(this.cacheListeners, CacheListener.class)).forEach(clientRegionFactory::addCacheListener);
|
||||
|
||||
Optional.ofNullable(this.diskStoreName).filter(StringUtils::hasText)
|
||||
.ifPresent(clientRegionFactory::setDiskStoreName);
|
||||
|
||||
Optional.ofNullable(this.evictionAttributes).ifPresent(clientRegionFactory::setEvictionAttributes);
|
||||
|
||||
Optional.ofNullable(this.keyConstraint).ifPresent(clientRegionFactory::setKeyConstraint);
|
||||
|
||||
Optional.ofNullable(resolvePoolName()).filter(StringUtils::hasText)
|
||||
.ifPresent(poolName -> clientRegionFactory.setPoolName(eagerlyInitializePool(poolName)));
|
||||
|
||||
Optional.ofNullable(this.valueConstraint).ifPresent(clientRegionFactory::setValueConstraint);
|
||||
|
||||
return clientRegionFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Post-process the given {@link ClientRegionFactory} setup by this {@link ClientRegionFactoryBean}.
|
||||
*
|
||||
* @param clientRegionFactory {@link ClientRegionFactory} to process.
|
||||
* @return the given {@link ClientRegionFactory}.
|
||||
* @see org.apache.geode.cache.client.ClientRegionFactory
|
||||
*/
|
||||
protected ClientRegionFactory<K, V> postProcess(ClientRegionFactory<K, V> clientRegionFactory) {
|
||||
return clientRegionFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Post-process the {@link Region} created by this {@link ClientRegionFactoryBean}.
|
||||
*
|
||||
* @param region {@link Region} to process.
|
||||
* @see org.apache.geode.cache.Region
|
||||
*/
|
||||
@Override
|
||||
protected Region<K, V> postProcess(Region<K, V> region) {
|
||||
|
||||
super.postProcess(region);
|
||||
|
||||
registerInterests(region);
|
||||
|
||||
Optional.ofNullable(this.cacheLoader)
|
||||
.ifPresent(cacheLoader -> region.getAttributesMutator().setCacheLoader(cacheLoader));
|
||||
|
||||
Optional.ofNullable(this.cacheWriter)
|
||||
.ifPresent(cacheWriter -> region.getAttributesMutator().setCacheWriter(cacheWriter));
|
||||
|
||||
return region;
|
||||
}
|
||||
@@ -376,47 +421,32 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
|
||||
/* (non-Javadoc) */
|
||||
@SuppressWarnings("unchecked")
|
||||
private Region<K, V> registerInterests(Region<K, V> region) {
|
||||
for (Interest<K> interest : nullSafeArray(interests, Interest.class)) {
|
||||
|
||||
stream(nullSafeArray(this.interests, Interest.class)).forEach(interest -> {
|
||||
if (interest.isRegexType()) {
|
||||
region.registerInterestRegex((String) interest.getKey(), interest.getPolicy(),
|
||||
interest.isDurable(), interest.isReceiveValues());
|
||||
}
|
||||
else {
|
||||
region.registerInterest(interest.getKey(), interest.getPolicy(), interest.isDurable(),
|
||||
interest.isReceiveValues());
|
||||
region.registerInterest(((Interest<K>) interest).getKey(), interest.getPolicy(),
|
||||
interest.isDurable(), interest.isReceiveValues());
|
||||
}
|
||||
}
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private Region<K, V> setCacheLoader(Region<K, V> region) {
|
||||
if (cacheLoader != null) {
|
||||
region.getAttributesMutator().setCacheLoader(this.cacheLoader);
|
||||
}
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private Region<K, V> setCacheWriter(Region<K, V> region) {
|
||||
if (cacheWriter != null) {
|
||||
region.getAttributesMutator().setCacheWriter(this.cacheWriter);
|
||||
}
|
||||
});
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* Closes and destroys the {@link Region}.
|
||||
*
|
||||
* @throws Exception if destroy fails.
|
||||
* @see org.springframework.beans.factory.DisposableBean
|
||||
*/
|
||||
@Override
|
||||
public void destroy() throws Exception {
|
||||
Region<K, V> region = getObject();
|
||||
|
||||
if (region != null) {
|
||||
if (close) {
|
||||
Optional.ofNullable(getObject()).ifPresent(region -> {
|
||||
if (isClose()) {
|
||||
if (!region.getRegionService().isClosed()) {
|
||||
try {
|
||||
region.close();
|
||||
@@ -426,10 +456,21 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
|
||||
}
|
||||
}
|
||||
|
||||
if (destroy) {
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -446,29 +487,6 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
|
||||
this.attributes = attributes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
final boolean isClose() {
|
||||
return close;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the region referred by this factory bean, will be
|
||||
* closed on shutdown (default true). Note: destroy and close are mutually
|
||||
* exclusive. Enabling one will automatically disable the other.
|
||||
*
|
||||
* @param close whether to close or not the region
|
||||
* @see #setDestroy(boolean)
|
||||
*/
|
||||
public void setClose(boolean close) {
|
||||
this.close = close;
|
||||
this.destroy = (this.destroy && !close); // retain previous value iff close is false.
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cache listeners used for the region used by this factory. Used
|
||||
* only when a new region is created.Overrides the settings specified
|
||||
@@ -500,6 +518,24 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
|
||||
this.cacheWriter = cacheWriter;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
final boolean isClose() {
|
||||
return this.close;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the region referred by this factory bean will be closed on shutdown (default true).
|
||||
*
|
||||
* Note: destroy and close are mutually exclusive. Enabling one will automatically disable the other.
|
||||
*
|
||||
* @param close whether to close or not the region
|
||||
* @see #setDestroy(boolean)
|
||||
*/
|
||||
public void setClose(boolean close) {
|
||||
this.close = close;
|
||||
this.destroy = (this.destroy && !close); // retain previous value iff close is false.
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Data Policy. Used only when a new Region is created.
|
||||
*
|
||||
@@ -521,13 +557,13 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
|
||||
@Deprecated
|
||||
public void setDataPolicyName(String dataPolicyName) {
|
||||
DataPolicy resolvedDataPolicy = new DataPolicyConverter().convert(dataPolicyName);
|
||||
Assert.notNull(resolvedDataPolicy, String.format("Data Policy '%1$s' is invalid.", dataPolicyName));
|
||||
Assert.notNull(resolvedDataPolicy, String.format("Data Policy [%1$s] is not valid", dataPolicyName));
|
||||
setDataPolicy(resolvedDataPolicy);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
final boolean isDestroy() {
|
||||
return destroy;
|
||||
return this.destroy;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -598,8 +634,8 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
|
||||
* @see org.apache.geode.cache.client.Pool
|
||||
*/
|
||||
public void setPool(Pool pool) {
|
||||
Assert.notNull(pool, "Pool cannot be null");
|
||||
setPoolName(pool.getName());
|
||||
setPoolName(Optional.ofNullable(pool).map(Pool::getName)
|
||||
.orElseThrow(() -> newIllegalArgumentException("Pool cannot be null")));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -608,8 +644,33 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
|
||||
* @param poolName String specifying the name of the GemFire client {@link Pool}.
|
||||
*/
|
||||
public void setPoolName(String poolName) {
|
||||
Assert.hasText(poolName, "Pool name is required");
|
||||
this.poolName = poolName;
|
||||
this.poolName = Optional.ofNullable(poolName).filter(StringUtils::hasText)
|
||||
.orElseThrow(() -> newIllegalArgumentException("Pool name is required"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -621,18 +682,6 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
|
||||
this.shortcut = shortcut;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the data snapshots used for loading a newly <i>created</i> {@link Region}.
|
||||
* The snapshot will be used <i>only</i> when a new {@link Region} is created.
|
||||
* If the {@link Region} already exists, no loading will be performed.
|
||||
*
|
||||
* @param snapshot {@link Resource} referencing the snapshot used to load the {@link Region} with data.
|
||||
* @see org.springframework.core.io.Resource
|
||||
*/
|
||||
public void setSnapshot(Resource snapshot) {
|
||||
this.snapshot = snapshot;
|
||||
}
|
||||
|
||||
public void setValueConstraint(Class<V> valueConstraint) {
|
||||
this.valueConstraint = valueConstraint;
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.springframework.util.ObjectUtils;
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public enum ClientRegionShortcutWrapper {
|
||||
|
||||
CACHING_PROXY(ClientRegionShortcut.CACHING_PROXY, DataPolicy.NORMAL),
|
||||
CACHING_PROXY_HEAP_LRU(ClientRegionShortcut.CACHING_PROXY_HEAP_LRU, DataPolicy.NORMAL),
|
||||
CACHING_PROXY_OVERFLOW(ClientRegionShortcut.CACHING_PROXY_OVERFLOW, DataPolicy.NORMAL),
|
||||
@@ -45,11 +46,6 @@ public enum ClientRegionShortcutWrapper {
|
||||
|
||||
private final DataPolicy dataPolicy;
|
||||
|
||||
ClientRegionShortcutWrapper(ClientRegionShortcut clientRegionShortcut, DataPolicy dataPolicy) {
|
||||
this.clientRegionShortcut = clientRegionShortcut;
|
||||
this.dataPolicy = dataPolicy;
|
||||
}
|
||||
|
||||
public static ClientRegionShortcutWrapper valueOf(ClientRegionShortcut clientRegionShortcut) {
|
||||
for (ClientRegionShortcutWrapper wrapper : values()) {
|
||||
if (ObjectUtils.nullSafeEquals(wrapper.getClientRegionShortcut(), clientRegionShortcut)) {
|
||||
@@ -60,6 +56,11 @@ public enum ClientRegionShortcutWrapper {
|
||||
return ClientRegionShortcutWrapper.UNSPECIFIED;
|
||||
}
|
||||
|
||||
ClientRegionShortcutWrapper(ClientRegionShortcut clientRegionShortcut, DataPolicy dataPolicy) {
|
||||
this.clientRegionShortcut = clientRegionShortcut;
|
||||
this.dataPolicy = dataPolicy;
|
||||
}
|
||||
|
||||
public ClientRegionShortcut getClientRegionShortcut() {
|
||||
return this.clientRegionShortcut;
|
||||
}
|
||||
|
||||
@@ -16,73 +16,68 @@
|
||||
|
||||
package org.springframework.data.gemfire.client;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.List;
|
||||
import static java.util.stream.StreamSupport.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.net.InetSocketAddress;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.geode.cache.client.ClientCache;
|
||||
import org.apache.geode.cache.client.Pool;
|
||||
import org.apache.geode.cache.client.PoolFactory;
|
||||
import org.apache.geode.cache.client.PoolManager;
|
||||
import org.apache.geode.cache.query.QueryService;
|
||||
import org.apache.geode.distributed.DistributedSystem;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.data.gemfire.GemfireUtils;
|
||||
import org.springframework.data.gemfire.config.annotation.PoolConfigurer;
|
||||
import org.springframework.data.gemfire.support.AbstractFactoryBeanSupport;
|
||||
import org.springframework.data.gemfire.support.ConnectionEndpoint;
|
||||
import org.springframework.data.gemfire.support.ConnectionEndpointList;
|
||||
import org.springframework.data.gemfire.util.DistributedSystemUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* FactoryBean for easy declaration and configuration of a GemFire {@link Pool}. If a new {@link Pool} is created,
|
||||
* its lifecycle is bound to that of this declaring factory.
|
||||
* Spring {@link FactoryBean} to construct, configure and initialize a {@link Pool}.
|
||||
*
|
||||
* Note, if a {@link Pool} having the configured name already exists, then the existing {@link Pool} will be returned
|
||||
* as is without any modifications and its lifecycle will be unaffected by this factory.
|
||||
* If a new {@link Pool} is created, its lifecycle is bound to that of this declaring {@link FactoryBean}
|
||||
* and indirectly, the Spring container.
|
||||
*
|
||||
* If a {@link Pool} having the configured {@link String name} already exists, then the existing {@link Pool}
|
||||
* will be returned as is without any modifications and its lifecycle will be unaffected by this {@link FactoryBean}.
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @author John Blum
|
||||
* @see java.net.InetSocketAddress
|
||||
* @see org.springframework.beans.factory.BeanNameAware
|
||||
* @see org.springframework.beans.factory.DisposableBean
|
||||
* @see org.springframework.beans.factory.FactoryBean
|
||||
* @see org.springframework.beans.factory.InitializingBean
|
||||
* @see org.springframework.data.gemfire.support.ConnectionEndpoint
|
||||
* @see org.springframework.data.gemfire.support.ConnectionEndpointList
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @see org.apache.geode.cache.client.Pool
|
||||
* @see org.apache.geode.cache.client.PoolFactory
|
||||
* @see org.apache.geode.cache.client.PoolManager
|
||||
* @see org.apache.geode.distributed.DistributedSystem
|
||||
* @see org.springframework.beans.factory.DisposableBean
|
||||
* @see org.springframework.beans.factory.InitializingBean
|
||||
* @see org.springframework.data.gemfire.config.annotation.PoolConfigurer
|
||||
* @see org.springframework.data.gemfire.support.AbstractFactoryBeanSupport
|
||||
* @see org.springframework.data.gemfire.support.ConnectionEndpoint
|
||||
* @see org.springframework.data.gemfire.support.ConnectionEndpointList
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean, DisposableBean,
|
||||
BeanNameAware, BeanFactoryAware {
|
||||
public class PoolFactoryBean extends AbstractFactoryBeanSupport<Pool> implements DisposableBean, InitializingBean {
|
||||
|
||||
protected static final int DEFAULT_LOCATOR_PORT = DistributedSystemUtils.DEFAULT_LOCATOR_PORT;
|
||||
protected static final int DEFAULT_SERVER_PORT = DistributedSystemUtils.DEFAULT_CACHE_SERVER_PORT;
|
||||
|
||||
private static final Log log = LogFactory.getLog(PoolFactoryBean.class);
|
||||
|
||||
// indicates whether the Pool has been created internally (by this FactoryBean) or not
|
||||
volatile boolean springBasedPool = true;
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
private ConnectionEndpointList locators = new ConnectionEndpointList();
|
||||
private ConnectionEndpointList servers = new ConnectionEndpointList();
|
||||
|
||||
private volatile Pool pool;
|
||||
|
||||
private String beanName;
|
||||
private String name;
|
||||
|
||||
// GemFire Pool Configuration Settings
|
||||
private boolean keepAlive = false;
|
||||
private boolean multiUserAuthentication = PoolFactory.DEFAULT_MULTIUSER_AUTHENTICATION;
|
||||
@@ -105,109 +100,150 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean, Dis
|
||||
private long idleTimeout = PoolFactory.DEFAULT_IDLE_TIMEOUT;
|
||||
private long pingInterval = PoolFactory.DEFAULT_PING_INTERVAL;
|
||||
|
||||
private ConnectionEndpointList locators = new ConnectionEndpointList();
|
||||
private ConnectionEndpointList servers = new ConnectionEndpointList();
|
||||
|
||||
private List<PoolConfigurer> poolConfigurers = Collections.emptyList();
|
||||
|
||||
private volatile Pool pool;
|
||||
|
||||
private PoolConfigurer compositePoolConfigurer = (beanName, bean) ->
|
||||
nullSafeCollection(poolConfigurers).forEach(poolConfigurer -> poolConfigurer.configure(beanName, bean));
|
||||
|
||||
private String name;
|
||||
private String serverGroup = PoolFactory.DEFAULT_SERVER_GROUP;
|
||||
|
||||
/**
|
||||
* Constructs and initializes a GemFire {@link Pool}.
|
||||
* Prepares the construction, configuration and initialization of a new {@link Pool}.
|
||||
*
|
||||
* @throws Exception if the {@link Pool} creation and initialization fails.
|
||||
* @see org.apache.geode.cache.client.Pool
|
||||
* @see org.apache.geode.cache.client.PoolFactory
|
||||
* @throws Exception if {@link Pool} initialization fails.
|
||||
* @see org.apache.geode.cache.client.PoolManager
|
||||
* @see #createPoolFactory()
|
||||
* @see org.apache.geode.cache.client.PoolFactory
|
||||
* @see org.apache.geode.cache.client.Pool
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
if (!StringUtils.hasText(name)) {
|
||||
Assert.hasText(beanName, "Pool 'name' is required");
|
||||
this.name = beanName;
|
||||
}
|
||||
|
||||
// check for an existing, configured Pool with name first
|
||||
Pool existingPool = PoolManager.find(name);
|
||||
|
||||
if (existingPool != null) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(String.format("A Pool with name [%1$s] already exists; using existing Pool.", name));
|
||||
}
|
||||
|
||||
this.springBasedPool = false;
|
||||
this.pool = existingPool;
|
||||
}
|
||||
else {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(String.format("No Pool with name [%1$s] was found. Creating new Pool.", name));
|
||||
}
|
||||
|
||||
this.springBasedPool = true;
|
||||
}
|
||||
init(Optional.ofNullable(PoolManager.find(validatePoolName())));
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys the GemFire {@link Pool} if created by this {@link PoolFactoryBean} and releases all system resources
|
||||
* used by the {@link Pool}.
|
||||
*
|
||||
* @throws Exception if the {@link Pool} destruction caused an error.
|
||||
* @see DisposableBean#destroy()
|
||||
*/
|
||||
@Override
|
||||
public void destroy() throws Exception {
|
||||
if (springBasedPool && pool != null && !pool.isDestroyed()) {
|
||||
pool.releaseThreadLocalConnection();
|
||||
pool.destroy(keepAlive);
|
||||
pool = null;
|
||||
/* (non-Javadoc) */
|
||||
@SuppressWarnings("all")
|
||||
private void init(Optional<Pool> existingPool) {
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(String.format("Destroyed Pool [%1$s]", name));
|
||||
}
|
||||
if (existingPool.isPresent()) {
|
||||
this.pool = existingPool.get();
|
||||
this.springBasedPool = false;
|
||||
|
||||
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()));
|
||||
}
|
||||
else {
|
||||
this.springBasedPool = true;
|
||||
applyPoolConfigurers();
|
||||
|
||||
logDebug("No Pool with name [%s] was found; Creating new Pool", getName());
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@Override
|
||||
public Pool getObject() throws Exception {
|
||||
if (this.pool == null) {
|
||||
eagerlyInitializeClientCacheIfNotPresent();
|
||||
|
||||
PoolFactory poolFactory = createPoolFactory();
|
||||
|
||||
poolFactory.setFreeConnectionTimeout(freeConnectionTimeout);
|
||||
poolFactory.setIdleTimeout(idleTimeout);
|
||||
poolFactory.setLoadConditioningInterval(loadConditioningInterval);
|
||||
poolFactory.setMaxConnections(maxConnections);
|
||||
poolFactory.setMinConnections(minConnections);
|
||||
poolFactory.setMultiuserAuthentication(multiUserAuthentication);
|
||||
poolFactory.setPingInterval(pingInterval);
|
||||
poolFactory.setPRSingleHopEnabled(prSingleHopEnabled);
|
||||
poolFactory.setReadTimeout(readTimeout);
|
||||
poolFactory.setRetryAttempts(retryAttempts);
|
||||
poolFactory.setServerGroup(serverGroup);
|
||||
poolFactory.setSocketBufferSize(socketBufferSize);
|
||||
poolFactory.setStatisticInterval(statisticInterval);
|
||||
poolFactory.setSubscriptionAckInterval(subscriptionAckInterval);
|
||||
poolFactory.setSubscriptionEnabled(subscriptionEnabled);
|
||||
poolFactory.setSubscriptionMessageTrackingTimeout(subscriptionMessageTrackingTimeout);
|
||||
poolFactory.setSubscriptionRedundancy(subscriptionRedundancy);
|
||||
poolFactory.setThreadLocalConnections(threadLocalConnections);
|
||||
|
||||
for (ConnectionEndpoint locator : this.locators) {
|
||||
poolFactory.addLocator(locator.getHost(), locator.getPort());
|
||||
}
|
||||
|
||||
for (ConnectionEndpoint server : this.servers) {
|
||||
poolFactory.addServer(server.getHost(), server.getPort());
|
||||
}
|
||||
|
||||
pool = poolFactory.create(name);
|
||||
}
|
||||
|
||||
return pool;
|
||||
private void applyPoolConfigurers() {
|
||||
applyPoolConfigurers(getCompositePoolConfigurer());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the GemFire DistributedSystem exists yet or not.
|
||||
* Null-safe operation to apply the given array of {@link PoolConfigurer PoolConfigurers}
|
||||
* to this {@link PoolFactoryBean}.
|
||||
*
|
||||
* @return a boolean value indicating whether the single, GemFire DistributedSystem has been created already.
|
||||
* @param poolConfigurers array of {@link PoolConfigurer PoolConfigurers} applied to this {@link PoolFactoryBean}.
|
||||
* @see org.springframework.data.gemfire.config.annotation.PoolConfigurer
|
||||
* @see #applyPoolConfigurers(Iterable)
|
||||
*/
|
||||
protected void applyPoolConfigurers(PoolConfigurer... poolConfigurers) {
|
||||
applyPoolConfigurers(Arrays.asList(nullSafeArray(poolConfigurers, PoolConfigurer.class)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe operation to apply the given {@link Iterable} of {@link PoolConfigurer PoolConfigurers}
|
||||
* to this {@link PoolFactoryBean}.
|
||||
*
|
||||
* @param poolConfigurers {@link Iterable} of {@link PoolConfigurer PoolConfigurers}
|
||||
* applied to this {@link PoolFactoryBean}.
|
||||
* @see org.springframework.data.gemfire.config.annotation.PoolConfigurer
|
||||
*/
|
||||
protected void applyPoolConfigurers(Iterable<PoolConfigurer> poolConfigurers) {
|
||||
stream(nullSafeIterable(poolConfigurers).spliterator(), false)
|
||||
.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}.
|
||||
*
|
||||
* @throws Exception if the {@link Pool} destruction caused an error.
|
||||
* @see org.springframework.beans.factory.DisposableBean#destroy()
|
||||
*/
|
||||
@Override
|
||||
public void destroy() throws Exception {
|
||||
|
||||
Optional.ofNullable(this.pool)
|
||||
.filter(pool -> this.springBasedPool)
|
||||
.filter(pool -> !pool.isDestroyed())
|
||||
.ifPresent(pool -> {
|
||||
pool.releaseThreadLocalConnection();
|
||||
pool.destroy(this.keepAlive);
|
||||
setPool(null);
|
||||
logDebug("Destroyed Pool [%s]", pool.getName());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 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}.
|
||||
*
|
||||
* @return an object reference to the {@link Pool} created by this {@link PoolFactoryBean}.
|
||||
* @see org.springframework.beans.factory.FactoryBean#getObject()
|
||||
* @see org.apache.geode.cache.client.Pool
|
||||
*/
|
||||
@Override
|
||||
public Pool getObject() throws Exception {
|
||||
|
||||
return Optional.ofNullable(this.pool).orElseGet(() -> {
|
||||
|
||||
eagerlyInitializeClientCacheIfNotPresent();
|
||||
|
||||
PoolFactory poolFactory = configure(createPoolFactory());
|
||||
|
||||
this.pool = create(poolFactory, 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
|
||||
@@ -217,22 +253,22 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean, Dis
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to eagerly initialize the GemFire {@link ClientCache} if not already present so that the single
|
||||
* {@link org.apache.geode.distributed.DistributedSystem} will exists, which is required to create
|
||||
* a {@link Pool} instance.
|
||||
* 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.
|
||||
*
|
||||
* @see org.springframework.beans.factory.BeanFactory#getBean(Class)
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @see org.apache.geode.distributed.DistributedSystem
|
||||
* @see #isDistributedSystemPresent()
|
||||
*/
|
||||
void eagerlyInitializeClientCacheIfNotPresent() {
|
||||
private void eagerlyInitializeClientCacheIfNotPresent() {
|
||||
if (!isDistributedSystemPresent()) {
|
||||
getBeanFactory().getBean(ClientCache.class);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of the GemFire {@link PoolFactory} interface to construct, configure and initialize
|
||||
* a GemFire {@link Pool}.
|
||||
* Creates an instance of the {@link PoolFactory} interface to construct, configure and initialize a {@link Pool}.
|
||||
*
|
||||
* @return a {@link PoolFactory} implementation to create a {@link Pool}.
|
||||
* @see org.apache.geode.cache.client.PoolManager#createFactory()
|
||||
@@ -242,16 +278,68 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean, Dis
|
||||
return PoolManager.createFactory();
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return (this.pool != null ? this.pool.getClass() : Pool.class);
|
||||
/**
|
||||
* Configures the given {@link PoolFactory} from this {@link PoolFactoryBean}.
|
||||
*
|
||||
* @param poolFactory {@link PoolFactory} to configure.
|
||||
* @return the given {@link PoolFactory}.
|
||||
* @see org.apache.geode.cache.client.PoolFactory
|
||||
*/
|
||||
protected PoolFactory configure(PoolFactory poolFactory) {
|
||||
|
||||
Optional.ofNullable(poolFactory).ifPresent(it -> {
|
||||
it.setFreeConnectionTimeout(this.freeConnectionTimeout);
|
||||
it.setIdleTimeout(this.idleTimeout);
|
||||
it.setLoadConditioningInterval(this.loadConditioningInterval);
|
||||
it.setMaxConnections(this.maxConnections);
|
||||
it.setMinConnections(this.minConnections);
|
||||
it.setMultiuserAuthentication(this.multiUserAuthentication);
|
||||
it.setPingInterval(this.pingInterval);
|
||||
it.setPRSingleHopEnabled(this.prSingleHopEnabled);
|
||||
it.setReadTimeout(this.readTimeout);
|
||||
it.setRetryAttempts(this.retryAttempts);
|
||||
it.setServerGroup(this.serverGroup);
|
||||
it.setSocketBufferSize(this.socketBufferSize);
|
||||
it.setStatisticInterval(this.statisticInterval);
|
||||
it.setSubscriptionAckInterval(this.subscriptionAckInterval);
|
||||
it.setSubscriptionEnabled(this.subscriptionEnabled);
|
||||
it.setSubscriptionMessageTrackingTimeout(this.subscriptionMessageTrackingTimeout);
|
||||
it.setSubscriptionRedundancy(this.subscriptionRedundancy);
|
||||
it.setThreadLocalConnections(this.threadLocalConnections);
|
||||
|
||||
nullSafeCollection(this.locators).forEach(locator ->
|
||||
it.addLocator(locator.getHost(), locator.getPort()));
|
||||
|
||||
nullSafeCollection(this.servers).forEach(server ->
|
||||
it.addServer(server.getHost(), server.getPort()));
|
||||
});
|
||||
|
||||
return poolFactory;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
/**
|
||||
* Creates a {@link Pool} with the given {@link String name} using the provided {@link PoolFactory}.
|
||||
*
|
||||
* @param poolFactory {@link PoolFactory} used to create the {@link Pool}.
|
||||
* @param poolName {@link String name} of the new {@link Pool}.
|
||||
* @return a new instance of {@link Pool} with the given {@link String name}.
|
||||
* @see org.apache.geode.cache.client.PoolFactory#create(String)
|
||||
* @see org.apache.geode.cache.client.Pool
|
||||
*/
|
||||
protected Pool create(PoolFactory poolFactory, String poolName) {
|
||||
return poolFactory.create(poolName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Class} type of the {@link Pool} produced by this {@link PoolFactoryBean}.
|
||||
*
|
||||
* @return the {@link Class} type of the {@link Pool} produced by this {@link PoolFactoryBean}.
|
||||
* @see org.springframework.beans.factory.FactoryBean#getObjectType()
|
||||
*/
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
@SuppressWarnings("unchecked")
|
||||
public Class<?> getObjectType() {
|
||||
return Optional.ofNullable(this.pool).map(Pool::getClass).orElse((Class) Pool.class);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@@ -274,29 +362,14 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean, Dis
|
||||
this.servers.add(servers);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected BeanFactory getBeanFactory() {
|
||||
return beanFactory;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
public void setBeanName(String name) {
|
||||
this.beanName = name;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
String getName() {
|
||||
return name;
|
||||
protected String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@@ -350,9 +423,8 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean, Dis
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
String name = PoolFactoryBean.this.name;
|
||||
name = (StringUtils.hasText(name) ? name : PoolFactoryBean.this.beanName);
|
||||
return name;
|
||||
return Optional.ofNullable(PoolFactoryBean.this.getName()).filter(StringUtils::hasText)
|
||||
.orElseGet(PoolFactoryBean.this::getBeanName);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -525,6 +597,31 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean, Dis
|
||||
this.pingInterval = pingInterval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe operation to set an array of {@link PoolConfigurer PoolConfigurers} used to apply
|
||||
* additional configuration to this {@link PoolFactoryBean} when using Annotation-based configuration.
|
||||
*
|
||||
* @param poolConfigurers array of {@link PoolConfigurer PoolConfigurers} used to apply
|
||||
* additional configuration to this {@link PoolFactoryBean}.
|
||||
* @see org.springframework.data.gemfire.config.annotation.PoolConfigurer
|
||||
* @see #setPoolConfigurers(List)
|
||||
*/
|
||||
public void setPoolConfigurers(PoolConfigurer... poolConfigurers) {
|
||||
setPoolConfigurers(Arrays.asList(nullSafeArray(poolConfigurers, PoolConfigurer.class)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe operation to set an {@link Iterable} of {@link PoolConfigurer PoolConfigurers} used to apply
|
||||
* additional configuration to this {@link PoolFactoryBean} when using Annotation-based configuration.
|
||||
*
|
||||
* @param poolConfigurers {@link Iterable} of {@link PoolConfigurer PoolConfigurers} used to apply
|
||||
* additional configuration to this {@link PoolFactoryBean}.
|
||||
* @see org.springframework.data.gemfire.config.annotation.PoolConfigurer
|
||||
*/
|
||||
public void setPoolConfigurers(List<PoolConfigurer> poolConfigurers) {
|
||||
this.poolConfigurers = Optional.ofNullable(poolConfigurers).orElseGet(Collections::emptyList);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
public void setPrSingleHopEnabled(boolean prSingleHopEnabled) {
|
||||
this.prSingleHopEnabled = prSingleHopEnabled;
|
||||
@@ -596,11 +693,17 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean, Dis
|
||||
this.threadLocalConnections = threadLocalConnections;
|
||||
}
|
||||
|
||||
/* (non-Javadoc; internal framework use only) */
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* internal framework use only
|
||||
*/
|
||||
public final void setLocatorsConfiguration(Object locatorsConfiguration) {
|
||||
}
|
||||
|
||||
/* (non-Javadoc; internal framework use only) */
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* internal framework use only
|
||||
*/
|
||||
public final void setServersConfiguration(Object serversConfiguration) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,29 +20,26 @@ package org.springframework.data.gemfire.config.annotation;
|
||||
import static org.springframework.data.gemfire.CacheFactoryBean.DynamicRegionSupport;
|
||||
import static org.springframework.data.gemfire.CacheFactoryBean.JndiDataSource;
|
||||
import static org.springframework.data.gemfire.util.CollectionUtils.nullSafeList;
|
||||
import static org.springframework.data.gemfire.util.SpringUtils.defaultIfNull;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.apache.geode.cache.Cache;
|
||||
import org.apache.geode.cache.TransactionListener;
|
||||
import org.apache.geode.cache.TransactionWriter;
|
||||
import org.apache.geode.cache.client.ClientCache;
|
||||
import org.apache.geode.cache.server.CacheServer;
|
||||
import org.apache.geode.cache.util.GatewayConflictResolver;
|
||||
import org.apache.geode.pdx.PdxSerializer;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ImportAware;
|
||||
@@ -50,6 +47,7 @@ import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.data.gemfire.CacheFactoryBean;
|
||||
import org.springframework.data.gemfire.config.annotation.support.AbstractAnnotationConfigSupport;
|
||||
import org.springframework.data.gemfire.config.support.CustomEditorBeanFactoryPostProcessor;
|
||||
import org.springframework.data.gemfire.config.support.DefinedIndexesApplicationListener;
|
||||
import org.springframework.data.gemfire.config.support.DiskStoreDirectoryBeanPostProcessor;
|
||||
@@ -57,33 +55,48 @@ import org.springframework.data.gemfire.config.support.PdxDiskStoreAwareBeanFact
|
||||
import org.springframework.data.gemfire.mapping.GemfireMappingContext;
|
||||
import org.springframework.data.gemfire.mapping.MappingPdxSerializer;
|
||||
import org.springframework.data.gemfire.util.PropertiesBuilder;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* {@link AbstractCacheConfiguration} is an abstract base class for configuring either a Pivotal GemFire/Apache Geode
|
||||
* client or peer-based cache instance using Spring's Java-based, Annotation
|
||||
* {@link org.springframework.context.annotation.Configuration} support.
|
||||
* client or peer-based cache instance using Spring's Java-based, Annotation {@link Configuration} support.
|
||||
*
|
||||
* This class encapsulates configuration settings common to both GemFire peer
|
||||
* {@link org.apache.geode.cache.Cache caches} and
|
||||
* {@link org.apache.geode.cache.client.ClientCache client caches}.
|
||||
* This class encapsulates configuration settings common to both Pivotal GemFire/Apache Geode
|
||||
* {@link org.apache.geode.cache.Cache peer caches}
|
||||
* and {@link org.apache.geode.cache.client.ClientCache client caches}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.beans.factory.BeanClassLoaderAware
|
||||
* @see java.lang.annotation.Annotation
|
||||
* @see java.util.Properties
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @see org.apache.geode.cache.server.CacheServer
|
||||
* @see org.apache.geode.pdx.PdxSerializer
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see org.springframework.beans.factory.BeanFactoryAware
|
||||
* @see org.springframework.beans.factory.config.BeanDefinition
|
||||
* @see org.springframework.beans.factory.support.BeanDefinitionBuilder
|
||||
* @see org.springframework.beans.factory.support.BeanDefinitionRegistry
|
||||
* @see org.springframework.context.annotation.Bean
|
||||
* @see org.springframework.context.annotation.Configuration
|
||||
* @see org.springframework.context.annotation.ImportAware
|
||||
* @see org.springframework.core.convert.ConversionService
|
||||
* @see org.springframework.core.io.Resource
|
||||
* @see org.springframework.core.type.AnnotationMetadata
|
||||
* @see org.springframework.data.gemfire.CacheFactoryBean
|
||||
* @see org.springframework.data.gemfire.client.ClientCacheFactoryBean
|
||||
* @see org.springframework.data.gemfire.config.annotation.support.AbstractAnnotationConfigSupport
|
||||
* @see org.springframework.data.gemfire.config.support.CustomEditorBeanFactoryPostProcessor
|
||||
* @see org.springframework.data.gemfire.config.support.DefinedIndexesApplicationListener
|
||||
* @see org.springframework.data.gemfire.config.support.DiskStoreDirectoryBeanPostProcessor
|
||||
* @see org.springframework.data.gemfire.config.support.PdxDiskStoreAwareBeanFactoryPostProcessor
|
||||
* @see org.springframework.data.gemfire.mapping.GemfireMappingContext
|
||||
* @see org.springframework.data.gemfire.mapping.MappingPdxSerializer
|
||||
* @since 1.9.0
|
||||
*/
|
||||
@Configuration
|
||||
@SuppressWarnings("unused")
|
||||
public abstract class AbstractCacheConfiguration implements BeanClassLoaderAware, BeanFactoryAware, ImportAware {
|
||||
public abstract class AbstractCacheConfiguration extends AbstractAnnotationConfigSupport implements ImportAware {
|
||||
|
||||
private static final AtomicBoolean CUSTOM_EDITORS_REGISTERED = new AtomicBoolean(false);
|
||||
private static final AtomicBoolean DEFINED_INDEXES_APPLICATION_LISTENER_REGISTERED = new AtomicBoolean(false);
|
||||
@@ -104,14 +117,10 @@ public abstract class AbstractCacheConfiguration implements BeanClassLoaderAware
|
||||
private boolean copyOnRead = DEFAULT_COPY_ON_READ;
|
||||
private boolean useBeanFactoryLocator = DEFAULT_USE_BEAN_FACTORY_LOCATOR;
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
private Boolean pdxIgnoreUnreadFields;
|
||||
private Boolean pdxPersistent;
|
||||
private Boolean pdxReadSerialized;
|
||||
|
||||
private ClassLoader beanClassLoader;
|
||||
|
||||
private DynamicRegionSupport dynamicRegionSupport;
|
||||
|
||||
private Integer mcastPort = 0;
|
||||
@@ -142,59 +151,30 @@ public abstract class AbstractCacheConfiguration implements BeanClassLoaderAware
|
||||
private TransactionWriter transactionWriter;
|
||||
|
||||
/**
|
||||
* Determines whether the given {@link Object} has value. The {@link Object} is valuable
|
||||
* if it is not {@literal null}.
|
||||
* Returns a {@link Properties} object containing Pivotal GemFire/Apache Geode properties used to configure
|
||||
* the Pivotal GemFire/Apache Geode cache.
|
||||
*
|
||||
* @param value {@link Object} to evaluate.
|
||||
* @return a boolean value indicating whether the given {@link Object} has value.
|
||||
*/
|
||||
protected static boolean hasValue(Object value) {
|
||||
return (value != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the given {@link Number} has value. The {@link Number} is valuable
|
||||
* if it is not {@literal null} and is not equal to 0.0d.
|
||||
* The {@literal name} of the Pivotal GemFire/Apache Geode member/node in the cluster is set to a default,
|
||||
* pre-defined and descriptive value depending on the type of configuration meta-data applied.
|
||||
*
|
||||
* @param value {@link Number} to evaluate.
|
||||
* @return a boolean value indicating whether the given {@link Number} has value.
|
||||
*/
|
||||
protected static boolean hasValue(Number value) {
|
||||
return (value != null && value.doubleValue() != 0.0d);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the given {@link String} has value. The {@link String} is valuable
|
||||
* if it is not {@literal null} or empty.
|
||||
* {@literal mcast-port} is set to {@literal 0} and {@literal locators} is set to an {@link String empty String},
|
||||
* which is necessary for {@link ClientCache cache client}-based applications. These values can be changed
|
||||
* and set accoridingly for {@link Cache peer cache} and {@link CacheServer cache server} applications.
|
||||
*
|
||||
* @param value {@link String} to evaluate.
|
||||
* @return a boolean value indicating whether the given {@link String} is valuable.
|
||||
*/
|
||||
protected static boolean hasValue(String value) {
|
||||
return StringUtils.hasText(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Properties} object containing GemFire System properties used to configure the GemFire cache.
|
||||
* Finally, the {@literal log-level} property defaults to {@literal config}.
|
||||
*
|
||||
* The name of the GemFire member/node in the cluster is set to a default, pre-defined, descriptive value
|
||||
* depending on the type of configuration meta-data applied.
|
||||
*
|
||||
* Both 'mcast-port' and 'locators' are to set 0 and empty String respectively, which is necessary
|
||||
* for {@link org.apache.geode.cache.client.ClientCache cache client}-based applications. These values
|
||||
* can be changed for peer cache and cache server applications.
|
||||
*
|
||||
* Finally, GemFire's {@literal log-level} System property defaults to {@literal config}.
|
||||
*
|
||||
* @return a {@link Properties} object containing GemFire System properties used to configure the GemFire cache.
|
||||
* @return a {@link Properties} object containing Pivotal GemFire/Apache Geode properties used to configure
|
||||
* the Pivotal GemFire/Apache Geode cache instance.
|
||||
* @see <a link="http://gemfire.docs.pivotal.io/docs-gemfire/reference/topics/gemfire_properties.html">GemFire Properties</a>
|
||||
* @see java.util.Properties
|
||||
* @see #name()
|
||||
* @see #logLevel()
|
||||
* @see #locators()
|
||||
* @see #logLevel()
|
||||
* @see #mcastPort()
|
||||
* @see #name()
|
||||
*/
|
||||
@Bean
|
||||
protected Properties gemfireProperties() {
|
||||
|
||||
PropertiesBuilder gemfireProperties = PropertiesBuilder.create();
|
||||
|
||||
gemfireProperties.setProperty("name", name());
|
||||
@@ -202,100 +182,87 @@ public abstract class AbstractCacheConfiguration implements BeanClassLoaderAware
|
||||
gemfireProperties.setProperty("log-level", logLevel());
|
||||
gemfireProperties.setProperty("locators", locators());
|
||||
gemfireProperties.setProperty("start-locator", startLocator());
|
||||
gemfireProperties.add(customGemFireProperties);
|
||||
gemfireProperties.add(this.customGemFireProperties);
|
||||
|
||||
return gemfireProperties.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setBeanClassLoader(ClassLoader beanClassLoader) {
|
||||
this.beanClassLoader = beanClassLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the {@link ClassLoader} use by the Spring {@link BeanFactory} to load classes
|
||||
* for bean definitions.
|
||||
*
|
||||
* @return the {@link ClassLoader} used by the Spring {@link BeanFactory} to load classes for bean definitions.
|
||||
* @see #setBeanClassLoader(ClassLoader)
|
||||
*/
|
||||
protected ClassLoader beanClassLoader() {
|
||||
return beanClassLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the Spring {@link BeanFactory} in the current application context.
|
||||
*
|
||||
* @return a reference to the Spring {@link BeanFactory}.
|
||||
* @throws IllegalStateException if the Spring {@link BeanFactory} was not properly initialized.
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
*/
|
||||
protected BeanFactory beanFactory() {
|
||||
Assert.state(this.beanFactory != null, "BeanFactory was not properly initialized");
|
||||
return this.beanFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setImportMetadata(AnnotationMetadata importMetadata) {
|
||||
|
||||
configureInfrastructure(importMetadata);
|
||||
configureCache(importMetadata);
|
||||
configurePdx(importMetadata);
|
||||
configureOther(importMetadata);
|
||||
configureTheRest(importMetadata);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures Spring container infrastructure components used by Spring Data GemFire
|
||||
* to enable GemFire to function properly inside a Spring context.
|
||||
* Configures Spring container infrastructure components and beans used by Spring Data GemFire
|
||||
* to enable Pivotal GemFire or Apache Geode to function properly inside a Spring context.
|
||||
*
|
||||
* @param importMetadata {@link AnnotationMetadata} containing annotation meta-data
|
||||
* for the Spring GemFire cache application class.
|
||||
* for the Spring Data GemFire cache application class.
|
||||
* @see org.springframework.core.type.AnnotationMetadata
|
||||
*/
|
||||
protected void configureInfrastructure(AnnotationMetadata importMetadata) {
|
||||
|
||||
registerCustomEditorBeanFactoryPostProcessor(importMetadata);
|
||||
registerDefinedIndexesApplicationListener(importMetadata);
|
||||
registerDiskStoreDirectoryBeanPostProcessor(importMetadata);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private void registerCustomEditorBeanFactoryPostProcessor(AnnotationMetadata importMetadata) {
|
||||
|
||||
if (CUSTOM_EDITORS_REGISTERED.compareAndSet(false, true)) {
|
||||
register(BeanDefinitionBuilder.rootBeanDefinition(CustomEditorBeanFactoryPostProcessor.class)
|
||||
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE).getBeanDefinition());
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private void registerDefinedIndexesApplicationListener(AnnotationMetadata importMetadata) {
|
||||
|
||||
if (DEFINED_INDEXES_APPLICATION_LISTENER_REGISTERED.compareAndSet(false, true)) {
|
||||
register(BeanDefinitionBuilder.rootBeanDefinition(DefinedIndexesApplicationListener.class)
|
||||
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE).getBeanDefinition());
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private void registerDiskStoreDirectoryBeanPostProcessor(AnnotationMetadata importMetadata) {
|
||||
|
||||
if (DISK_STORE_DIRECTORY_BEAN_POST_PROCESSOR_REGISTERED.compareAndSet(false, true)) {
|
||||
register(BeanDefinitionBuilder.rootBeanDefinition(DiskStoreDirectoryBeanPostProcessor.class)
|
||||
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE).getBeanDefinition());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the GemFire cache settings.
|
||||
* Configures Pivotal GemFire/Apache Geode cache specific settings.
|
||||
*
|
||||
* @param importMetadata {@link AnnotationMetadata} containing the cache meta-data used to configure
|
||||
* the GemFire cache.
|
||||
* @param importMetadata {@link AnnotationMetadata} containing the cache meta-data used to configure the cache.
|
||||
* @see org.springframework.core.type.AnnotationMetadata
|
||||
*/
|
||||
protected void configureCache(AnnotationMetadata importMetadata) {
|
||||
|
||||
if (isClientPeerOrServerCacheApplication(importMetadata)) {
|
||||
|
||||
Map<String, Object> cacheMetadataAttributes =
|
||||
importMetadata.getAnnotationAttributes(getAnnotationTypeName());
|
||||
|
||||
setCopyOnRead(Boolean.TRUE.equals(cacheMetadataAttributes.get("copyOnRead")));
|
||||
|
||||
Float criticalHeapPercentage = (Float) cacheMetadataAttributes.get("criticalHeapPercentage");
|
||||
Optional.ofNullable((Float) cacheMetadataAttributes.get("criticalHeapPercentage"))
|
||||
.filter(AbstractAnnotationConfigSupport::hasValue)
|
||||
.ifPresent(this::setCriticalHeapPercentage);
|
||||
|
||||
if (hasValue(criticalHeapPercentage)) {
|
||||
setCriticalHeapPercentage(criticalHeapPercentage);
|
||||
}
|
||||
|
||||
Float evictionHeapPercentage = (Float) cacheMetadataAttributes.get("evictionHeapPercentage");
|
||||
|
||||
if (hasValue(evictionHeapPercentage)) {
|
||||
setEvictionHeapPercentage(evictionHeapPercentage);
|
||||
}
|
||||
Optional.ofNullable((Float) cacheMetadataAttributes.get("evictionHeapPercentage"))
|
||||
.filter(AbstractAnnotationConfigSupport::hasValue)
|
||||
.ifPresent(this::setEvictionHeapPercentage);
|
||||
|
||||
setLogLevel((String) cacheMetadataAttributes.get("logLevel"));
|
||||
setName((String) cacheMetadataAttributes.get("name"));
|
||||
@@ -304,17 +271,19 @@ public abstract class AbstractCacheConfiguration implements BeanClassLoaderAware
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures GemFire's PDX Serialization components.
|
||||
* Configures Pivotal GemFire/Apache Geode cache PDX Serialization.
|
||||
*
|
||||
* @param importMetadata {@link AnnotationMetadata} containing PDX meta-data used to configure
|
||||
* the GemFire cache with PDX de/serialization capabilities.
|
||||
* @param importMetadata {@link AnnotationMetadata} containing PDX meta-data used to configure the cache
|
||||
* with PDX de/serialization capabilities.
|
||||
* @see org.springframework.core.type.AnnotationMetadata
|
||||
* @see <a href="http://gemfire.docs.pivotal.io/docs-gemfire/latest/developing/data_serialization/gemfire_pdx_serialization.html">GemFire PDX Serialization</a>
|
||||
*/
|
||||
protected void configurePdx(AnnotationMetadata importMetadata) {
|
||||
|
||||
String enablePdxTypeName = EnablePdx.class.getName();
|
||||
|
||||
if (importMetadata.hasAnnotation(enablePdxTypeName)) {
|
||||
|
||||
Map<String, Object> enablePdxAttributes = importMetadata.getAnnotationAttributes(enablePdxTypeName);
|
||||
|
||||
setPdxDiskStoreName((String) enablePdxAttributes.get("diskStoreName"));
|
||||
@@ -328,97 +297,158 @@ public abstract class AbstractCacheConfiguration implements BeanClassLoaderAware
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback method to configure other, specific GemFire cache configuration settings.
|
||||
* Resolves the {@link PdxSerializer} used to configure the cache for PDX De/Serialization.
|
||||
*
|
||||
* @param importMetadata {@link AnnotationMetadata} containing meta-data used to configure
|
||||
* the GemFire cache.
|
||||
* @see org.springframework.core.type.AnnotationMetadata
|
||||
*/
|
||||
protected void configureOther(AnnotationMetadata importMetadata) {
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected PdxSerializer resolvePdxSerializer(String pdxSerializerBeanName) {
|
||||
BeanFactory beanFactory = beanFactory();
|
||||
PdxSerializer pdxSerializer = pdxSerializer();
|
||||
|
||||
return (beanFactory.containsBean(pdxSerializerBeanName)
|
||||
? beanFactory.getBean(pdxSerializerBeanName, PdxSerializer.class)
|
||||
: (pdxSerializer != null ? pdxSerializer : newPdxSerializer()));
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T extends PdxSerializer> T newPdxSerializer() {
|
||||
BeanFactory beanFactory = beanFactory();
|
||||
|
||||
ConversionService conversionService = (beanFactory instanceof ConfigurableBeanFactory
|
||||
? ((ConfigurableBeanFactory) beanFactory).getConversionService() : null);
|
||||
|
||||
return (T) MappingPdxSerializer.create(this.mappingContext, conversionService);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected void registerCustomEditorBeanFactoryPostProcessor(AnnotationMetadata importMetadata) {
|
||||
if (CUSTOM_EDITORS_REGISTERED.compareAndSet(false, true)) {
|
||||
register(BeanDefinitionBuilder.rootBeanDefinition(CustomEditorBeanFactoryPostProcessor.class)
|
||||
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE).getBeanDefinition());
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected void registerDefinedIndexesApplicationListener(AnnotationMetadata importMetadata) {
|
||||
if (DEFINED_INDEXES_APPLICATION_LISTENER_REGISTERED.compareAndSet(false, true)) {
|
||||
register(BeanDefinitionBuilder.rootBeanDefinition(DefinedIndexesApplicationListener.class)
|
||||
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE).getBeanDefinition());
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected void registerDiskStoreDirectoryBeanPostProcessor(AnnotationMetadata importMetadata) {
|
||||
if (DISK_STORE_DIRECTORY_BEAN_POST_PROCESSOR_REGISTERED.compareAndSet(false, true)) {
|
||||
register(BeanDefinitionBuilder.rootBeanDefinition(DiskStoreDirectoryBeanPostProcessor.class)
|
||||
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE).getBeanDefinition());
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected void registerPdxDiskStoreAwareBeanFactoryPostProcessor(AnnotationMetadata importMetadata) {
|
||||
if (StringUtils.hasText(pdxDiskStoreName())) {
|
||||
if (PDX_DISK_STORE_AWARE_BEAN_FACTORY_POST_PROCESSOR_REGISTERED.compareAndSet(false, true)) {
|
||||
register(BeanDefinitionBuilder.rootBeanDefinition(PdxDiskStoreAwareBeanFactoryPostProcessor.class)
|
||||
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
.addConstructorArgValue(pdxDiskStoreName())
|
||||
.getBeanDefinition());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the given {@link BeanDefinition} with the {@link BeanDefinitionRegistry} using a generated bean name.
|
||||
*
|
||||
* @param beanDefinition {@link AbstractBeanDefinition} to register.
|
||||
* @return the given {@link BeanDefinition}.
|
||||
* @see org.springframework.beans.factory.support.AbstractBeanDefinition
|
||||
* @see org.springframework.beans.factory.support.BeanDefinitionRegistry
|
||||
* @see org.springframework.beans.factory.support.BeanDefinitionReaderUtils
|
||||
* #registerWithGeneratedName(AbstractBeanDefinition, BeanDefinitionRegistry)
|
||||
* @param pdxSerializerBeanName {@link String} containing the name of a Spring bean
|
||||
* implementing the {@link PdxSerializer} interface.
|
||||
* @return the resolved {@link PdxSerializer} from configuration.
|
||||
* @see org.apache.geode.pdx.PdxSerializer
|
||||
* @see #newPdxSerializer(BeanFactory)
|
||||
* @see #beanFactory()
|
||||
*/
|
||||
protected AbstractBeanDefinition register(AbstractBeanDefinition beanDefinition) {
|
||||
if (beanFactory() instanceof BeanDefinitionRegistry) {
|
||||
BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition,
|
||||
((BeanDefinitionRegistry) beanFactory()));
|
||||
}
|
||||
protected PdxSerializer resolvePdxSerializer(String pdxSerializerBeanName) {
|
||||
|
||||
return beanDefinition;
|
||||
BeanFactory beanFactory = beanFactory();
|
||||
|
||||
return Optional.ofNullable(pdxSerializerBeanName)
|
||||
.filter(beanFactory::containsBean)
|
||||
.map(beanName -> beanFactory.getBean(beanName, PdxSerializer.class))
|
||||
.orElseGet(() -> Optional.ofNullable(pdxSerializer()).orElseGet(() -> newPdxSerializer(beanFactory)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the GemFire cache application {@link java.lang.annotation.Annotation} type pertaining to
|
||||
* this configuration.
|
||||
* Constructs a new instance of {@link PdxSerializer}.
|
||||
*
|
||||
* @return the GemFire cache application {@link java.lang.annotation.Annotation} type used by this application.
|
||||
* @param <T> {@link Class} type of the {@link PdxSerializer}.
|
||||
* @return a new instance of {@link PdxSerializer}.
|
||||
* @see org.apache.geode.pdx.PdxSerializer
|
||||
* @see #newPdxSerializer(BeanFactory)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T extends PdxSerializer> T newPdxSerializer() {
|
||||
return newPdxSerializer(beanFactory());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new instance of {@link MappingPdxSerializer}.
|
||||
*
|
||||
* @param <T> {@link Class} type of the {@link PdxSerializer}; this method returns a {@link MappingPdxSerializer}.
|
||||
* @param beanFactory {@link BeanFactory} used to get an instance of {@link ConversionService}
|
||||
* used by the {@link MappingPdxSerializer}.
|
||||
* @return a new instance of {@link MappingPdxSerializer}.
|
||||
* @see org.springframework.data.gemfire.mapping.MappingPdxSerializer
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see org.apache.geode.pdx.PdxSerializer
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T extends PdxSerializer> T newPdxSerializer(BeanFactory beanFactory) {
|
||||
|
||||
Optional<ConversionService> conversionService = Optional.ofNullable(beanFactory)
|
||||
.filter(it -> it instanceof ConfigurableBeanFactory)
|
||||
.map(it -> ((ConfigurableBeanFactory) it).getConversionService());
|
||||
|
||||
return (T) MappingPdxSerializer.create(this.mappingContext, conversionService.orElse(null));
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private void registerPdxDiskStoreAwareBeanFactoryPostProcessor(AnnotationMetadata importMetadata) {
|
||||
|
||||
Optional.ofNullable(pdxDiskStoreName())
|
||||
.filter(StringUtils::hasText)
|
||||
.ifPresent(pdxDiskStoreName -> {
|
||||
if (PDX_DISK_STORE_AWARE_BEAN_FACTORY_POST_PROCESSOR_REGISTERED.compareAndSet(false, true)) {
|
||||
register(BeanDefinitionBuilder.rootBeanDefinition(PdxDiskStoreAwareBeanFactoryPostProcessor.class)
|
||||
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
.addConstructorArgValue(pdxDiskStoreName)
|
||||
.getBeanDefinition());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback method allowing developers to configure other cache or application specific configuration settings.
|
||||
*
|
||||
* @param importMetadata {@link AnnotationMetadata} containing meta-data used to configure the cache or application.
|
||||
* @see org.springframework.core.type.AnnotationMetadata
|
||||
*/
|
||||
protected void configureTheRest(AnnotationMetadata importMetadata) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new, initialized instance of {@link CacheFactoryBean} based on the Spring application's
|
||||
* cache type preference (i.e. client or peer), which is expressed via the appropriate annotation.
|
||||
*
|
||||
* Use the {@link ClientCacheApplication} Annotation to construct a {@link ClientCache cache client} application.
|
||||
*
|
||||
* Use the {@link PeerCacheApplication} Annotation to construct a {@link Cache peer cache} application.
|
||||
*
|
||||
* @param <T> {@link Class} specific sub-type of the {@link CacheFactoryBean}.
|
||||
* @return a new instance of the appropriate {@link CacheFactoryBean} given the Spring application's
|
||||
* cache type preference (i.e client or peer), (e.g. {@link ClientCacheApplication}
|
||||
* or {@link PeerCacheApplication}).
|
||||
* @see org.springframework.data.gemfire.client.ClientCacheFactoryBean
|
||||
* @see org.springframework.data.gemfire.CacheFactoryBean
|
||||
* @see #configureCacheFactoryBean(CacheFactoryBean)
|
||||
* @see #newCacheFactoryBean()
|
||||
*/
|
||||
protected <T extends CacheFactoryBean> T constructCacheFactoryBean() {
|
||||
return configureCacheFactoryBean(this.<T>newCacheFactoryBean());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new, uninitialized instance of {@link CacheFactoryBean} based on the Spring application's
|
||||
* cache type preference (i.e. client or peer), which is expressed via the appropriate annotation.
|
||||
*
|
||||
* Use the {@link ClientCacheApplication} Annotation to construct a {@link ClientCache cache client} application.
|
||||
*
|
||||
* Use the {@link PeerCacheApplication} Annotation to construct a {@link Cache peer cache} application.
|
||||
*
|
||||
* @param <T> {@link Class} specific sub-type of the {@link CacheFactoryBean}.
|
||||
* @return a new instance of the appropriate {@link CacheFactoryBean} given the Spring application's
|
||||
* cache type preference (i.e client or peer), (e.g. {@link ClientCacheApplication}
|
||||
* or {@link PeerCacheApplication}).
|
||||
* @see org.springframework.data.gemfire.client.ClientCacheFactoryBean
|
||||
* @see org.springframework.data.gemfire.CacheFactoryBean
|
||||
*/
|
||||
protected abstract <T extends CacheFactoryBean> T newCacheFactoryBean();
|
||||
|
||||
/**
|
||||
* Configures the {@link CacheFactoryBean} with common cache configuration settings.
|
||||
*
|
||||
* @param <T> {@link Class} specific sub-type of the {@link CacheFactoryBean}.
|
||||
* @param gemfireCache {@link CacheFactoryBean} to configure.
|
||||
* @return the given {@link CacheFactoryBean} with common cache configuration settings applied.
|
||||
* @see org.springframework.data.gemfire.client.ClientCacheFactoryBean
|
||||
* @see org.springframework.data.gemfire.CacheFactoryBean
|
||||
*/
|
||||
protected <T extends CacheFactoryBean> T configureCacheFactoryBean(T gemfireCache) {
|
||||
|
||||
gemfireCache.setBeanClassLoader(beanClassLoader());
|
||||
gemfireCache.setBeanFactory(beanFactory());
|
||||
gemfireCache.setCacheXml(cacheXml());
|
||||
gemfireCache.setClose(close());
|
||||
gemfireCache.setCopyOnRead(copyOnRead());
|
||||
gemfireCache.setCriticalHeapPercentage(criticalHeapPercentage());
|
||||
gemfireCache.setDynamicRegionSupport(dynamicRegionSupport());
|
||||
gemfireCache.setEvictionHeapPercentage(evictionHeapPercentage());
|
||||
gemfireCache.setGatewayConflictResolver(gatewayConflictResolver());
|
||||
gemfireCache.setJndiDataSources(jndiDataSources());
|
||||
gemfireCache.setProperties(gemfireProperties());
|
||||
gemfireCache.setPdxDiskStoreName(pdxDiskStoreName());
|
||||
gemfireCache.setPdxIgnoreUnreadFields(pdxIgnoreUnreadFields());
|
||||
gemfireCache.setPdxPersistent(pdxPersistent());
|
||||
gemfireCache.setPdxReadSerialized(pdxReadSerialized());
|
||||
gemfireCache.setPdxSerializer(pdxSerializer());
|
||||
gemfireCache.setTransactionListeners(transactionListeners());
|
||||
gemfireCache.setTransactionWriter(transactionWriter());
|
||||
|
||||
return gemfireCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cache application {@link java.lang.annotation.Annotation} type pertaining to this configuration.
|
||||
*
|
||||
* @return the cache application {@link java.lang.annotation.Annotation} type used by this application.
|
||||
* @see org.springframework.data.gemfire.config.annotation.CacheServerApplication
|
||||
* @see org.springframework.data.gemfire.config.annotation.ClientCacheApplication
|
||||
* @see org.springframework.data.gemfire.config.annotation.PeerCacheApplication
|
||||
@@ -426,11 +456,11 @@ public abstract class AbstractCacheConfiguration implements BeanClassLoaderAware
|
||||
protected abstract Class getAnnotationType();
|
||||
|
||||
/**
|
||||
* Returns the fully-qualified class name of the GemFire cache application {@link java.lang.annotation.Annotation}
|
||||
* type.
|
||||
* Returns the fully-qualified {@link Class#getName() class name} of the cache application
|
||||
* {@link java.lang.annotation.Annotation} type.
|
||||
*
|
||||
* @return the fully-qualified class name of the GemFire cache application {@link java.lang.annotation.Annotation}
|
||||
* type.
|
||||
* @return the fully-qualified {@link Class#getName() class name} of the cache application
|
||||
* {@link java.lang.annotation.Annotation} type.
|
||||
* @see java.lang.Class#getName()
|
||||
* @see #getAnnotationType()
|
||||
*/
|
||||
@@ -439,9 +469,11 @@ public abstract class AbstractCacheConfiguration implements BeanClassLoaderAware
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the simple class name of the GemFire cache application {@link java.lang.annotation.Annotation} type.
|
||||
* Returns the simple {@link Class#getName() class name} of the cache application
|
||||
* {@link java.lang.annotation.Annotation} type.
|
||||
*
|
||||
* @return the simple class name of the GemFire cache application {@link java.lang.annotation.Annotation} type.
|
||||
* @return the simple {@link Class#getName() class name} of the cache application
|
||||
* {@link java.lang.annotation.Annotation} type.
|
||||
* @see java.lang.Class#getSimpleName()
|
||||
* @see #getAnnotationType()
|
||||
*/
|
||||
@@ -449,6 +481,8 @@ public abstract class AbstractCacheConfiguration implements BeanClassLoaderAware
|
||||
return getAnnotationType().getSimpleName();
|
||||
}
|
||||
|
||||
// REVIEW JAVADOC FROM HERE
|
||||
|
||||
/**
|
||||
* Determines whether this is a GemFire {@link org.apache.geode.cache.server.CacheServer} application,
|
||||
* which is indicated by the presence of the {@link CacheServerApplication} annotation on a Spring application
|
||||
@@ -508,7 +542,7 @@ public abstract class AbstractCacheConfiguration implements BeanClassLoaderAware
|
||||
* @see #getAnnotationType()
|
||||
*/
|
||||
protected boolean isTypedCacheApplication(Class<? extends Annotation> annotationType,
|
||||
AnnotationMetadata importMetadata) {
|
||||
AnnotationMetadata importMetadata) {
|
||||
|
||||
return (annotationType.equals(getAnnotationType()) && importMetadata.hasAnnotation(getAnnotationTypeName()));
|
||||
}
|
||||
@@ -549,68 +583,6 @@ public abstract class AbstractCacheConfiguration implements BeanClassLoaderAware
|
||||
|| isPeerCacheApplication(importMetadata));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new, initialized instance of the {@link CacheFactoryBean} based on the Spring application's
|
||||
* GemFire cache type (i.e. client or peer) preference specified via annotation.
|
||||
*
|
||||
* @param <T> Class type of the {@link CacheFactoryBean}.
|
||||
* @return a new instance of an appropriate {@link CacheFactoryBean} given the Spring application's
|
||||
* GemFire cache type preference (i.e client or peer) specified with the corresponding annotation
|
||||
* (e.g. {@link ClientCacheApplication} or {@link PeerCacheApplication});
|
||||
* @see org.springframework.data.gemfire.client.ClientCacheFactoryBean
|
||||
* @see org.springframework.data.gemfire.CacheFactoryBean
|
||||
* @see #setCommonCacheConfiguration(CacheFactoryBean)
|
||||
* @see #newCacheFactoryBean()
|
||||
*/
|
||||
protected <T extends CacheFactoryBean> T constructCacheFactoryBean() {
|
||||
return setCommonCacheConfiguration(this.<T>newCacheFactoryBean());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new, uninitialized instance of the {@link CacheFactoryBean} based on the Spring application's
|
||||
* GemFire cache type (i.e. client or peer) preference specified via annotation.
|
||||
*
|
||||
* @param <T> Class type of the {@link CacheFactoryBean}.
|
||||
* @return a new instance of an appropriate {@link CacheFactoryBean} given the Spring application's
|
||||
* GemFire cache type preference (i.e client or peer) specified with the corresponding annotation
|
||||
* (e.g. {@link ClientCacheApplication} or {@link PeerCacheApplication}).
|
||||
* @see org.springframework.data.gemfire.client.ClientCacheFactoryBean
|
||||
* @see org.springframework.data.gemfire.CacheFactoryBean
|
||||
*/
|
||||
protected abstract <T extends CacheFactoryBean> T newCacheFactoryBean();
|
||||
|
||||
/**
|
||||
* Configures common GemFire cache configuration settings.
|
||||
*
|
||||
* @param <T> Class type of the {@link CacheFactoryBean}.
|
||||
* @param gemfireCache {@link CacheFactoryBean} instance to configure.
|
||||
* @return the given {@link CacheFactoryBean} after common configuration settings have been applied.
|
||||
* @see org.springframework.data.gemfire.client.ClientCacheFactoryBean
|
||||
* @see org.springframework.data.gemfire.CacheFactoryBean
|
||||
*/
|
||||
protected <T extends CacheFactoryBean> T setCommonCacheConfiguration(T gemfireCache) {
|
||||
gemfireCache.setBeanClassLoader(beanClassLoader());
|
||||
gemfireCache.setBeanFactory(beanFactory());
|
||||
gemfireCache.setCacheXml(cacheXml());
|
||||
gemfireCache.setClose(close());
|
||||
gemfireCache.setCopyOnRead(copyOnRead());
|
||||
gemfireCache.setCriticalHeapPercentage(criticalHeapPercentage());
|
||||
gemfireCache.setDynamicRegionSupport(dynamicRegionSupport());
|
||||
gemfireCache.setEvictionHeapPercentage(evictionHeapPercentage());
|
||||
gemfireCache.setGatewayConflictResolver(gatewayConflictResolver());
|
||||
gemfireCache.setJndiDataSources(jndiDataSources());
|
||||
gemfireCache.setProperties(gemfireProperties());
|
||||
gemfireCache.setPdxDiskStoreName(pdxDiskStoreName());
|
||||
gemfireCache.setPdxIgnoreUnreadFields(pdxIgnoreUnreadFields());
|
||||
gemfireCache.setPdxPersistent(pdxPersistent());
|
||||
gemfireCache.setPdxReadSerialized(pdxReadSerialized());
|
||||
gemfireCache.setPdxSerializer(pdxSerializer());
|
||||
gemfireCache.setTransactionListeners(transactionListeners());
|
||||
gemfireCache.setTransactionWriter(transactionWriter());
|
||||
|
||||
return gemfireCache;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
void setCacheXml(Resource cacheXml) {
|
||||
this.cacheXml = cacheXml;
|
||||
@@ -699,7 +671,7 @@ public abstract class AbstractCacheConfiguration implements BeanClassLoaderAware
|
||||
}
|
||||
|
||||
protected String logLevel() {
|
||||
return defaultIfNull(this.logLevel, DEFAULT_LOG_LEVEL);
|
||||
return Optional.ofNullable(this.logLevel).orElse(DEFAULT_LOG_LEVEL);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@@ -717,7 +689,7 @@ public abstract class AbstractCacheConfiguration implements BeanClassLoaderAware
|
||||
}
|
||||
|
||||
protected Integer mcastPort() {
|
||||
return (mcastPort != null ? mcastPort : DEFAULT_MCAST_PORT);
|
||||
return Optional.ofNullable(mcastPort).orElse(DEFAULT_MCAST_PORT);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@@ -726,7 +698,7 @@ public abstract class AbstractCacheConfiguration implements BeanClassLoaderAware
|
||||
}
|
||||
|
||||
protected String name() {
|
||||
return (StringUtils.hasText(name) ? name : toString());
|
||||
return Optional.ofNullable(this.name).filter(StringUtils::hasText).orElseGet(this::toString);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
|
||||
@@ -17,8 +17,22 @@
|
||||
|
||||
package org.springframework.data.gemfire.config.annotation;
|
||||
|
||||
import java.util.Map;
|
||||
import static org.springframework.data.gemfire.util.CollectionUtils.nullSafeMap;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
@@ -26,27 +40,49 @@ import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.data.gemfire.config.xml.GemfireConstants;
|
||||
import org.springframework.data.gemfire.server.CacheServerFactoryBean;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* The {@link AddCacheServerConfiguration} class is a Spring {@link ImportBeanDefinitionRegistrar} that registers
|
||||
* a {@link CacheServerFactoryBean} definition for the {@link org.apache.geode.cache.server.CacheServer}
|
||||
* configuration meta-data defined in {@link EnableCacheServer}.
|
||||
* configuration meta-data defined in {@link EnableCacheServer} annotation.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.server.CacheServer
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see org.springframework.beans.factory.BeanFactoryAware
|
||||
* @see org.springframework.beans.factory.config.BeanDefinition
|
||||
* @see org.springframework.beans.factory.config.BeanDefinitionHolder
|
||||
* @see org.springframework.beans.factory.support.BeanDefinitionBuilder
|
||||
* @see org.springframework.beans.factory.support.BeanDefinitionRegistry
|
||||
* @see org.springframework.context.annotation.ImportBeanDefinitionRegistrar
|
||||
* @see org.springframework.core.type.AnnotationMetadata
|
||||
* @see org.springframework.data.gemfire.config.annotation.AddCacheServersConfiguration
|
||||
* @see org.springframework.data.gemfire.config.annotation.CacheServerApplication
|
||||
* @see org.springframework.data.gemfire.config.annotation.CacheServerConfiguration
|
||||
* @see org.springframework.data.gemfire.config.annotation.CacheServerConfigurer
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableCacheServers
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableCacheServer
|
||||
* @see org.springframework.data.gemfire.server.CacheServerFactoryBean
|
||||
* @since 1.9.0
|
||||
*/
|
||||
public class AddCacheServerConfiguration implements ImportBeanDefinitionRegistrar {
|
||||
public class AddCacheServerConfiguration implements BeanFactoryAware, ImportBeanDefinitionRegistrar {
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
@Autowired(required = false)
|
||||
private List<CacheServerConfigurer> cacheServerConfigurers = Collections.emptyList();
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
|
||||
|
||||
if (importingClassMetadata.hasAnnotation(EnableCacheServer.class.getName())) {
|
||||
Map<String, Object> enableCacheServerAttributes = importingClassMetadata.getAnnotationAttributes(
|
||||
EnableCacheServer.class.getName());
|
||||
|
||||
Map<String, Object> enableCacheServerAttributes =
|
||||
importingClassMetadata.getAnnotationAttributes(EnableCacheServer.class.getName());
|
||||
|
||||
registerCacheServerFactoryBeanDefinition(enableCacheServerAttributes, registry);
|
||||
}
|
||||
@@ -69,6 +105,7 @@ public class AddCacheServerConfiguration implements ImportBeanDefinitionRegistra
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(CacheServerFactoryBean.class);
|
||||
|
||||
builder.addPropertyReference("cache", GemfireConstants.DEFAULT_GEMFIRE_CACHE_NAME);
|
||||
builder.addPropertyValue("cacheServerConfigurers", resolveCacheServerConfigurers());
|
||||
builder.addPropertyValue("autoStartup", enableCacheServerAttributes.get("autoStartup"));
|
||||
builder.addPropertyValue("bindAddress", enableCacheServerAttributes.get("bindAddress"));
|
||||
builder.addPropertyValue("hostNameForClients", enableCacheServerAttributes.get("hostnameForClients"));
|
||||
@@ -84,6 +121,49 @@ public class AddCacheServerConfiguration implements ImportBeanDefinitionRegistra
|
||||
builder.addPropertyValue("subscriptionDiskStore", enableCacheServerAttributes.get("subscriptionDiskStoreName"));
|
||||
builder.addPropertyValue("subscriptionEvictionPolicy", enableCacheServerAttributes.get("subscriptionEvictionPolicy"));
|
||||
|
||||
BeanDefinitionReaderUtils.registerWithGeneratedName(builder.getBeanDefinition(), registry);
|
||||
registerCacheServerFactoryBeanDefinition(builder.getBeanDefinition(),
|
||||
(String) enableCacheServerAttributes.get("name"), registry);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private List<CacheServerConfigurer> resolveCacheServerConfigurers() {
|
||||
|
||||
return Optional.ofNullable(this.cacheServerConfigurers)
|
||||
.filter(cacheServerConfigurers -> !cacheServerConfigurers.isEmpty())
|
||||
.orElseGet(() ->
|
||||
Optional.of(this.beanFactory)
|
||||
.filter(beanFactory -> beanFactory instanceof ListableBeanFactory)
|
||||
.map(beanFactory -> {
|
||||
Map<String, CacheServerConfigurer> beansOfType = ((ListableBeanFactory) beanFactory)
|
||||
.getBeansOfType(CacheServerConfigurer.class, true, true);
|
||||
|
||||
return nullSafeMap(beansOfType).values().stream().collect(Collectors.toList());
|
||||
})
|
||||
.orElseGet(Collections::emptyList)
|
||||
);
|
||||
|
||||
}
|
||||
/* (non-Javadoc) */
|
||||
protected void registerCacheServerFactoryBeanDefinition(AbstractBeanDefinition beanDefinition, String beanName,
|
||||
BeanDefinitionRegistry registry) {
|
||||
|
||||
if (StringUtils.hasText(beanName)) {
|
||||
BeanDefinitionReaderUtils.registerBeanDefinition(
|
||||
newBeanDefinitionHolder(beanDefinition, beanName), registry);
|
||||
}
|
||||
else {
|
||||
BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, registry);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected BeanDefinitionHolder newBeanDefinitionHolder(BeanDefinition beanDefinition, String beanName) {
|
||||
return new BeanDefinitionHolder(beanDefinition, beanName);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,19 @@
|
||||
|
||||
package org.springframework.data.gemfire.config.annotation;
|
||||
|
||||
import java.util.Map;
|
||||
import static org.springframework.data.gemfire.util.CollectionUtils.nullSafeMap;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
||||
@@ -32,25 +43,42 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* The {@link AddCacheServerConfiguration} class is a Spring {@link ImportBeanDefinitionRegistrar} that registers
|
||||
* The {@link AddPoolConfiguration} class is a Spring {@link ImportBeanDefinitionRegistrar} that registers
|
||||
* a {@link PoolFactoryBean} definition for the {@link org.apache.geode.cache.client.Pool}
|
||||
* configuration meta-data defined in {@link EnablePool}.
|
||||
* configuration meta-data defined in {@link EnablePool} annotations.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.client.Pool
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see org.springframework.beans.factory.BeanFactoryAware
|
||||
* @see org.springframework.beans.factory.support.BeanDefinitionBuilder
|
||||
* @see org.springframework.beans.factory.support.BeanDefinitionRegistry
|
||||
* @see org.springframework.context.annotation.ImportBeanDefinitionRegistrar
|
||||
* @see org.springframework.core.type.AnnotationMetadata
|
||||
* @see org.springframework.data.gemfire.client.PoolFactoryBean
|
||||
* @see org.springframework.data.gemfire.config.annotation.AddPoolsConfiguration
|
||||
* @see org.springframework.data.gemfire.config.annotation.PoolConfigurer
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnablePools
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnablePool
|
||||
* @since 1.9.0
|
||||
*/
|
||||
public class AddPoolConfiguration implements ImportBeanDefinitionRegistrar {
|
||||
public class AddPoolConfiguration implements BeanFactoryAware, ImportBeanDefinitionRegistrar {
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
@Autowired(required = false)
|
||||
private List<PoolConfigurer> poolConfigurers = Collections.emptyList();
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
|
||||
|
||||
if (importingClassMetadata.hasAnnotation(EnablePool.class.getName())) {
|
||||
Map<String, Object> enablePoolAttributes = importingClassMetadata.getAnnotationAttributes(
|
||||
EnablePool.class.getName());
|
||||
|
||||
Map<String, Object> enablePoolAttributes =
|
||||
importingClassMetadata.getAnnotationAttributes(EnablePool.class.getName());
|
||||
|
||||
registerPoolFactoryBeanDefinition(enablePoolAttributes, registry);
|
||||
}
|
||||
@@ -61,7 +89,7 @@ public class AddPoolConfiguration implements ImportBeanDefinitionRegistrar {
|
||||
* the {@link EnablePool} annotation meta-data.
|
||||
*
|
||||
* @param enablePoolAttributes {@link EnablePool} annotation attributes.
|
||||
* @param registry Spring {@link BeanDefinitionRegistry used to register the {@link PoolFactoryBean} definition.
|
||||
* @param registry Spring {@link BeanDefinitionRegistry} used to register the {@link PoolFactoryBean} definition.
|
||||
* @see org.springframework.beans.factory.support.BeanDefinitionRegistry
|
||||
* @see org.springframework.data.gemfire.client.PoolFactoryBean
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnablePool
|
||||
@@ -81,6 +109,7 @@ public class AddPoolConfiguration implements ImportBeanDefinitionRegistrar {
|
||||
poolFactoryBean.addPropertyValue("minConnections", enablePoolAttributes.get("minConnections"));
|
||||
poolFactoryBean.addPropertyValue("multiUserAuthentication", enablePoolAttributes.get("multiUserAuthentication"));
|
||||
poolFactoryBean.addPropertyValue("pingInterval", enablePoolAttributes.get("pingInterval"));
|
||||
poolFactoryBean.addPropertyValue("poolConfigurers", resolvePoolConfigurers());
|
||||
poolFactoryBean.addPropertyValue("prSingleHopEnabled", enablePoolAttributes.get("prSingleHopEnabled"));
|
||||
poolFactoryBean.addPropertyValue("readTimeout", enablePoolAttributes.get("readTimeout"));
|
||||
poolFactoryBean.addPropertyValue("retryAttempts", enablePoolAttributes.get("retryAttempts"));
|
||||
@@ -98,9 +127,27 @@ public class AddPoolConfiguration implements ImportBeanDefinitionRegistrar {
|
||||
registry.registerBeanDefinition(poolName, poolFactoryBean.getBeanDefinition());
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private List<PoolConfigurer> resolvePoolConfigurers() {
|
||||
|
||||
return Optional.ofNullable(this.poolConfigurers)
|
||||
.filter(poolConfigurers -> !poolConfigurers.isEmpty())
|
||||
.orElseGet(() ->
|
||||
Optional.of(this.beanFactory)
|
||||
.filter(beanFactory -> beanFactory instanceof ListableBeanFactory)
|
||||
.map(beanFactory -> {
|
||||
Map<String, PoolConfigurer> beansOfType = ((ListableBeanFactory) beanFactory)
|
||||
.getBeansOfType(PoolConfigurer.class, true, true);
|
||||
|
||||
return nullSafeMap(beansOfType).values().stream().collect(Collectors.toList());
|
||||
})
|
||||
.orElseGet(Collections::emptyList)
|
||||
);
|
||||
}
|
||||
|
||||
protected String getAndValidatePoolName(Map<String, Object> enablePoolAttributes) {
|
||||
String poolName = (String) enablePoolAttributes.get("name");
|
||||
Assert.hasText(poolName, "Pool name must be specified");
|
||||
Assert.hasText(poolName, "Pool name is required");
|
||||
return poolName;
|
||||
}
|
||||
|
||||
@@ -166,4 +213,9 @@ public class AddPoolConfiguration implements ImportBeanDefinitionRegistrar {
|
||||
protected ConnectionEndpoint newConnectionEndpoint(String host, Integer port) {
|
||||
return new ConnectionEndpoint(host, port);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.springframework.core.type.AnnotationMetadata;
|
||||
* the {@link EnablePools} annotation on a GemFire client cache application class.
|
||||
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.client.Pool
|
||||
* @see org.springframework.data.gemfire.config.annotation.AddPoolConfiguration
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnablePool
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnablePools
|
||||
|
||||
@@ -43,6 +43,8 @@ import org.springframework.data.gemfire.server.SubscriptionEvictionPolicy;
|
||||
* @see org.springframework.context.annotation.Configuration
|
||||
* @see org.springframework.context.annotation.Import
|
||||
* @see org.springframework.data.gemfire.config.annotation.CacheServerConfiguration
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableCacheServers
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableCacheServer
|
||||
* @see org.apache.geode.cache.control.ResourceManager
|
||||
* @see org.apache.geode.cache.server.CacheServer
|
||||
* @see org.apache.geode.cache.server.ClientSubscriptionConfig
|
||||
|
||||
@@ -17,32 +17,47 @@
|
||||
|
||||
package org.springframework.data.gemfire.config.annotation;
|
||||
|
||||
import static org.springframework.data.gemfire.util.CollectionUtils.nullSafeMap;
|
||||
import static org.springframework.data.gemfire.util.CollectionUtils.nullSafeSet;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.geode.cache.Cache;
|
||||
import org.apache.geode.cache.InterestRegistrationListener;
|
||||
import org.apache.geode.cache.client.ClientCache;
|
||||
import org.apache.geode.cache.server.CacheServer;
|
||||
import org.apache.geode.cache.server.ClientSubscriptionConfig;
|
||||
import org.apache.geode.cache.server.ServerLoadProbe;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.data.gemfire.server.CacheServerFactoryBean;
|
||||
import org.springframework.data.gemfire.server.SubscriptionEvictionPolicy;
|
||||
import org.springframework.data.gemfire.util.CollectionUtils;
|
||||
import org.springframework.data.gemfire.util.SpringUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Spring {@link Configuration} class used to configure, construct and initialize and GemFire {@link CacheServer}
|
||||
* instance in a Spring application context.
|
||||
* Spring {@link Configuration} class used to construct, configure and initialize a {@link CacheServer} instance
|
||||
* in a Spring application context.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.context.annotation.Bean
|
||||
* @see org.springframework.context.annotation.Configuration
|
||||
* @see org.springframework.data.gemfire.config.annotation.PeerCacheConfiguration
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see org.apache.geode.cache.server.CacheServer
|
||||
* @see org.springframework.context.annotation.Bean
|
||||
* @see org.springframework.context.annotation.Configuration
|
||||
* @see org.springframework.data.gemfire.config.annotation.AddCacheServerConfiguration
|
||||
* @see org.springframework.data.gemfire.config.annotation.AddCacheServersConfiguration
|
||||
* @see org.springframework.data.gemfire.config.annotation.CacheServerConfigurer
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableCacheServer
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableCacheServers
|
||||
* @see org.springframework.data.gemfire.config.annotation.PeerCacheConfiguration
|
||||
* @see org.springframework.data.gemfire.server.CacheServerFactoryBean
|
||||
* @since 1.9.0
|
||||
*/
|
||||
@Configuration
|
||||
@@ -64,6 +79,9 @@ public class CacheServerConfiguration extends PeerCacheConfiguration {
|
||||
private Integer socketBufferSize;
|
||||
private Integer subscriptionCapacity;
|
||||
|
||||
@Autowired(required = false)
|
||||
private List<CacheServerConfigurer> cacheServerConfigurers = Collections.emptyList();
|
||||
|
||||
private Long loadPollInterval;
|
||||
|
||||
private ServerLoadProbe serverLoadProbe;
|
||||
@@ -76,11 +94,23 @@ public class CacheServerConfiguration extends PeerCacheConfiguration {
|
||||
|
||||
private SubscriptionEvictionPolicy subscriptionEvictionPolicy;
|
||||
|
||||
/**
|
||||
* Bean declaration for a single, {@link CacheServer} to serve {@link ClientCache cache client} applications.
|
||||
*
|
||||
* @param gemfireCache peer {@link Cache} instance in which to add the {@link CacheServer}.
|
||||
* @return a {@link CacheServerFactoryBean} used to construct, configure and initialize
|
||||
* the {@link CacheServer} instance.
|
||||
* @see org.springframework.data.gemfire.server.CacheServerFactoryBean
|
||||
* @see org.apache.geode.cache.server.CacheServer
|
||||
* @see org.apache.geode.cache.Cache
|
||||
*/
|
||||
@Bean
|
||||
public CacheServerFactoryBean gemfireCacheServer(Cache gemfireCache) {
|
||||
|
||||
CacheServerFactoryBean gemfireCacheServer = new CacheServerFactoryBean();
|
||||
|
||||
gemfireCacheServer.setCache(gemfireCache);
|
||||
gemfireCacheServer.setCacheServerConfigurers(resolveCacheServerConfigurers());
|
||||
gemfireCacheServer.setAutoStartup(autoStartup());
|
||||
gemfireCacheServer.setBindAddress(bindAddress());
|
||||
gemfireCacheServer.setHostNameForClients(hostnameForClients());
|
||||
@@ -101,18 +131,40 @@ public class CacheServerConfiguration extends PeerCacheConfiguration {
|
||||
return gemfireCacheServer;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private List<CacheServerConfigurer> resolveCacheServerConfigurers() {
|
||||
|
||||
return Optional.ofNullable(this.cacheServerConfigurers)
|
||||
.filter(cacheServerConfigurers -> !cacheServerConfigurers.isEmpty())
|
||||
.orElseGet(() ->
|
||||
Optional.of(this.beanFactory())
|
||||
.filter(beanFactory -> beanFactory instanceof ListableBeanFactory)
|
||||
.map(beanFactory -> {
|
||||
Map<String, CacheServerConfigurer> beansOfType = ((ListableBeanFactory) beanFactory)
|
||||
.getBeansOfType(CacheServerConfigurer.class, true, true);
|
||||
|
||||
return nullSafeMap(beansOfType).values().stream().collect(Collectors.toList());
|
||||
})
|
||||
.orElseGet(Collections::emptyList)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures GemFire {@link CacheServer} specific settings.
|
||||
* Configures {@link CacheServer} specific settings.
|
||||
*
|
||||
* @param importMetadata {@link AnnotationMetadata} containing cache server meta-data used to configure
|
||||
* the GemFire {@link CacheServer}.
|
||||
* @param importMetadata {@link AnnotationMetadata} containing cache server meta-data used to
|
||||
* configure the {@link CacheServer}.
|
||||
* @see org.springframework.core.type.AnnotationMetadata
|
||||
* @see org.apache.geode.cache.server.CacheServer
|
||||
*/
|
||||
@Override
|
||||
protected void configureOther(AnnotationMetadata importMetadata) {
|
||||
protected void configureTheRest(AnnotationMetadata importMetadata) {
|
||||
|
||||
super.configureCache(importMetadata);
|
||||
|
||||
if (isCacheServerApplication(importMetadata)) {
|
||||
|
||||
Map<String, Object> cacheServerApplicationMetadata =
|
||||
importMetadata.getAnnotationAttributes(getAnnotationTypeName());
|
||||
|
||||
@@ -129,8 +181,8 @@ public class CacheServerConfiguration extends PeerCacheConfiguration {
|
||||
setSocketBufferSize((Integer) cacheServerApplicationMetadata.get("socketBufferSize"));
|
||||
setSubscriptionCapacity((Integer) cacheServerApplicationMetadata.get("subscriptionCapacity"));
|
||||
setSubscriptionDiskStoreName((String) cacheServerApplicationMetadata.get("subscriptionDiskStoreName"));
|
||||
setSubscriptionEvictionPolicy((SubscriptionEvictionPolicy) cacheServerApplicationMetadata.get(
|
||||
"subscriptionEvictionPolicy"));
|
||||
setSubscriptionEvictionPolicy((SubscriptionEvictionPolicy)
|
||||
cacheServerApplicationMetadata.get("subscriptionEvictionPolicy"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,7 +209,8 @@ public class CacheServerConfiguration extends PeerCacheConfiguration {
|
||||
}
|
||||
|
||||
protected String bindAddress() {
|
||||
return SpringUtils.defaultIfNull(this.bindAddress, CacheServer.DEFAULT_BIND_ADDRESS);
|
||||
return Optional.ofNullable(this.bindAddress).filter(StringUtils::hasText)
|
||||
.orElse(CacheServer.DEFAULT_BIND_ADDRESS);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@@ -166,7 +219,8 @@ public class CacheServerConfiguration extends PeerCacheConfiguration {
|
||||
}
|
||||
|
||||
protected String hostnameForClients() {
|
||||
return SpringUtils.defaultIfNull(this.hostnameForClients, CacheServer.DEFAULT_HOSTNAME_FOR_CLIENTS);
|
||||
return Optional.ofNullable(this.hostnameForClients).filter(StringUtils::hasText)
|
||||
.orElse(CacheServer.DEFAULT_HOSTNAME_FOR_CLIENTS);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@@ -175,7 +229,7 @@ public class CacheServerConfiguration extends PeerCacheConfiguration {
|
||||
}
|
||||
|
||||
protected Set<InterestRegistrationListener> interestRegistrationListeners() {
|
||||
return CollectionUtils.nullSafeSet(this.interestRegistrationListeners);
|
||||
return nullSafeSet(this.interestRegistrationListeners);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@@ -184,7 +238,7 @@ public class CacheServerConfiguration extends PeerCacheConfiguration {
|
||||
}
|
||||
|
||||
protected Long loadPollInterval() {
|
||||
return SpringUtils.defaultIfNull(this.loadPollInterval, CacheServer.DEFAULT_LOAD_POLL_INTERVAL);
|
||||
return Optional.ofNullable(this.loadPollInterval).orElse(CacheServer.DEFAULT_LOAD_POLL_INTERVAL);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@@ -193,7 +247,7 @@ public class CacheServerConfiguration extends PeerCacheConfiguration {
|
||||
}
|
||||
|
||||
protected Integer maxConnections() {
|
||||
return SpringUtils.defaultIfNull(this.maxConnections, CacheServer.DEFAULT_MAX_CONNECTIONS);
|
||||
return Optional.ofNullable(this.maxConnections).orElse(CacheServer.DEFAULT_MAX_CONNECTIONS);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@@ -202,7 +256,7 @@ public class CacheServerConfiguration extends PeerCacheConfiguration {
|
||||
}
|
||||
|
||||
protected Integer maxMessageCount() {
|
||||
return SpringUtils.defaultIfNull(this.maxMessageCount, CacheServer.DEFAULT_MAXIMUM_MESSAGE_COUNT);
|
||||
return Optional.ofNullable(this.maxMessageCount).orElse(CacheServer.DEFAULT_MAXIMUM_MESSAGE_COUNT);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@@ -211,7 +265,7 @@ public class CacheServerConfiguration extends PeerCacheConfiguration {
|
||||
}
|
||||
|
||||
protected Integer maxThreads() {
|
||||
return SpringUtils.defaultIfNull(this.maxThreads, CacheServer.DEFAULT_MAX_THREADS);
|
||||
return Optional.ofNullable(this.maxThreads).orElse(CacheServer.DEFAULT_MAX_THREADS);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@@ -220,7 +274,7 @@ public class CacheServerConfiguration extends PeerCacheConfiguration {
|
||||
}
|
||||
|
||||
protected Integer maxTimeBetweenPings() {
|
||||
return SpringUtils.defaultIfNull(this.maxTimeBetweenPings, CacheServer.DEFAULT_MAXIMUM_TIME_BETWEEN_PINGS);
|
||||
return Optional.ofNullable(this.maxTimeBetweenPings).orElse(CacheServer.DEFAULT_MAXIMUM_TIME_BETWEEN_PINGS);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@@ -229,7 +283,7 @@ public class CacheServerConfiguration extends PeerCacheConfiguration {
|
||||
}
|
||||
|
||||
protected Integer messageTimeToLive() {
|
||||
return SpringUtils.defaultIfNull(this.messageTimeToLive, CacheServer.DEFAULT_MESSAGE_TIME_TO_LIVE);
|
||||
return Optional.ofNullable(this.messageTimeToLive).orElse(CacheServer.DEFAULT_MESSAGE_TIME_TO_LIVE);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@@ -238,7 +292,7 @@ public class CacheServerConfiguration extends PeerCacheConfiguration {
|
||||
}
|
||||
|
||||
protected Integer port() {
|
||||
return SpringUtils.defaultIfNull(this.port, CacheServer.DEFAULT_PORT);
|
||||
return Optional.ofNullable(this.port).orElse(CacheServer.DEFAULT_PORT);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@@ -247,7 +301,7 @@ public class CacheServerConfiguration extends PeerCacheConfiguration {
|
||||
}
|
||||
|
||||
protected ServerLoadProbe serverLoadProbe() {
|
||||
return SpringUtils.defaultIfNull(this.serverLoadProbe, CacheServer.DEFAULT_LOAD_PROBE);
|
||||
return Optional.ofNullable(this.serverLoadProbe).orElse(CacheServer.DEFAULT_LOAD_PROBE);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@@ -256,7 +310,7 @@ public class CacheServerConfiguration extends PeerCacheConfiguration {
|
||||
}
|
||||
|
||||
protected Integer socketBufferSize() {
|
||||
return SpringUtils.defaultIfNull(this.socketBufferSize, CacheServer.DEFAULT_SOCKET_BUFFER_SIZE);
|
||||
return Optional.ofNullable(this.socketBufferSize).orElse(CacheServer.DEFAULT_SOCKET_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@@ -265,7 +319,7 @@ public class CacheServerConfiguration extends PeerCacheConfiguration {
|
||||
}
|
||||
|
||||
protected Integer subscriptionCapacity() {
|
||||
return SpringUtils.defaultIfNull(this.subscriptionCapacity, ClientSubscriptionConfig.DEFAULT_CAPACITY);
|
||||
return Optional.ofNullable(this.subscriptionCapacity).orElse(ClientSubscriptionConfig.DEFAULT_CAPACITY);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@@ -283,7 +337,7 @@ public class CacheServerConfiguration extends PeerCacheConfiguration {
|
||||
}
|
||||
|
||||
protected SubscriptionEvictionPolicy subscriptionEvictionPolicy() {
|
||||
return SpringUtils.defaultIfNull(this.subscriptionEvictionPolicy, SubscriptionEvictionPolicy.DEFAULT);
|
||||
return Optional.ofNullable(this.subscriptionEvictionPolicy).orElse(SubscriptionEvictionPolicy.DEFAULT);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.springframework.data.gemfire.config.annotation;
|
||||
|
||||
import org.apache.geode.cache.server.CacheServer;
|
||||
import org.springframework.data.gemfire.server.CacheServerFactoryBean;
|
||||
|
||||
/**
|
||||
* The {@link CacheServerConfigurer} interface defines a contract for implementations to customize the configuration
|
||||
* of a {@link CacheServerFactoryBean} used to construct, configure and initialize an instance of a {@link CacheServer}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.server.CacheServer
|
||||
* @see org.springframework.data.gemfire.config.annotation.CacheServerApplication
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableCacheServers
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableCacheServer
|
||||
* @see org.springframework.data.gemfire.server.CacheServerFactoryBean
|
||||
* @since 1.9.0
|
||||
*/
|
||||
public interface CacheServerConfigurer {
|
||||
|
||||
/**
|
||||
* Configuration callback method providing a reference to a {@link CacheServerFactoryBean} used to construct,
|
||||
* configure and initialize an instance of {@link CacheServer}.
|
||||
*
|
||||
* @param beanName name of {@link CacheServer} bean declared in the Spring application context.
|
||||
* @param bean reference to the {@link CacheServerFactoryBean}.
|
||||
* @see org.springframework.data.gemfire.server.CacheServerFactoryBean
|
||||
*/
|
||||
void configure(String beanName, CacheServerFactoryBean bean);
|
||||
|
||||
}
|
||||
@@ -37,11 +37,11 @@ import org.springframework.data.gemfire.support.GemfireBeanFactoryLocator;
|
||||
* a GemFire cache client (i.e. {@link org.apache.geode.cache.client.ClientCache}).
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.client.PoolFactory
|
||||
* @see org.apache.geode.cache.control.ResourceManager
|
||||
* @see org.springframework.context.annotation.Configuration
|
||||
* @see org.springframework.context.annotation.Import
|
||||
* @see org.springframework.data.gemfire.config.annotation.ClientCacheConfiguration
|
||||
* @see org.apache.geode.cache.client.PoolFactory
|
||||
* @see org.apache.geode.cache.control.ResourceManager
|
||||
* @since 1.9.0
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@@ -195,7 +195,7 @@ public @interface ClientCacheApplication {
|
||||
int retryAttempts() default PoolFactory.DEFAULT_RETRY_ATTEMPTS;
|
||||
|
||||
/**
|
||||
* Configures the group that all servers this pool connects to must belong to.
|
||||
* Configures the group that all servers in which this pool connects to must belong to.
|
||||
*
|
||||
* @see org.apache.geode.cache.client.PoolFactory#DEFAULT_SERVER_GROUP
|
||||
*/
|
||||
|
||||
@@ -17,9 +17,19 @@
|
||||
|
||||
package org.springframework.data.gemfire.config.annotation;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import static org.springframework.data.gemfire.util.CollectionUtils.nullSafeMap;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.geode.cache.client.ClientCache;
|
||||
import org.apache.geode.cache.client.Pool;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -33,14 +43,24 @@ import org.springframework.data.gemfire.support.ConnectionEndpoint;
|
||||
import org.springframework.data.gemfire.support.ConnectionEndpointList;
|
||||
|
||||
/**
|
||||
* Spring {@link Configuration} class used to configure, construct and initialize
|
||||
* a GemFire {@link org.apache.geode.cache.client.ClientCache} instance in a Spring application context.
|
||||
* Spring {@link Configuration} class used to construct, configure and initialize
|
||||
* a {@link org.apache.geode.cache.client.ClientCache} instance in a Spring application context.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @see org.apache.geode.cache.client.Pool
|
||||
* @see org.springframework.beans.factory.config.BeanDefinition
|
||||
* @see org.springframework.beans.factory.support.BeanDefinitionBuilder
|
||||
* @see org.springframework.context.annotation.Bean
|
||||
* @see org.springframework.context.annotation.Configuration
|
||||
* @see org.springframework.core.type.AnnotationMetadata
|
||||
* @see org.springframework.data.gemfire.CacheFactoryBean
|
||||
* @see org.springframework.data.gemfire.client.ClientCacheFactoryBean
|
||||
* @see org.springframework.data.gemfire.config.annotation.AbstractCacheConfiguration
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @see org.springframework.data.gemfire.config.annotation.ClientCacheConfigurer
|
||||
* @see org.springframework.data.gemfire.config.support.ClientRegionPoolBeanFactoryPostProcessor
|
||||
* @see org.springframework.data.gemfire.support.ConnectionEndpoint
|
||||
* @see org.springframework.data.gemfire.support.ConnectionEndpointList
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
@@ -78,16 +98,30 @@ public class ClientCacheConfiguration extends AbstractCacheConfiguration {
|
||||
private Iterable<ConnectionEndpoint> locators;
|
||||
private Iterable<ConnectionEndpoint> servers;
|
||||
|
||||
@Autowired(required = false)
|
||||
private List<ClientCacheConfigurer> clientCacheConfigurers = Collections.emptyList();
|
||||
|
||||
private Long idleTimeout;
|
||||
private Long pingInterval;
|
||||
|
||||
private String durableClientId;
|
||||
private String serverGroup;
|
||||
|
||||
/**
|
||||
* Bean declaration for a single, peer {@link ClientCache} instance.
|
||||
*
|
||||
* @return a new instance of a peer {@link ClientCache}.
|
||||
* @see org.springframework.data.gemfire.client.ClientCacheFactoryBean
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see #constructCacheFactoryBean()
|
||||
*/
|
||||
@Bean
|
||||
public ClientCacheFactoryBean gemfireCache() {
|
||||
|
||||
ClientCacheFactoryBean gemfireCache = constructCacheFactoryBean();
|
||||
|
||||
gemfireCache.setClientCacheConfigurers(resolveClientCacheConfigurers());
|
||||
gemfireCache.setDurableClientId(durableClientId());
|
||||
gemfireCache.setDurableClientTimeout(durableClientTimeout());
|
||||
gemfireCache.setFreeConnectionTimeout(freeConnectionTimeout());
|
||||
@@ -116,8 +150,30 @@ public class ClientCacheConfiguration extends AbstractCacheConfiguration {
|
||||
return gemfireCache;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private List<ClientCacheConfigurer> resolveClientCacheConfigurers() {
|
||||
|
||||
return Optional.ofNullable(this.clientCacheConfigurers)
|
||||
.filter(clientCacheConfigurers -> !clientCacheConfigurers.isEmpty())
|
||||
.orElseGet(() ->
|
||||
Optional.of(this.beanFactory())
|
||||
.filter(beanFactory -> beanFactory instanceof ListableBeanFactory)
|
||||
.map(beanFactory -> {
|
||||
Map<String, ClientCacheConfigurer> beansOfType = ((ListableBeanFactory) beanFactory)
|
||||
.getBeansOfType(ClientCacheConfigurer.class, true, true);
|
||||
|
||||
return nullSafeMap(beansOfType).values().stream().collect(Collectors.toList());
|
||||
})
|
||||
.orElseGet(Collections::emptyList)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* Constructs a new instance of {@link ClientCacheFactoryBean} used to create a peer {@link ClientCache}.
|
||||
*
|
||||
* @param <T> {@link Class} sub-type of {@link CacheFactoryBean}.
|
||||
* @return a new instance of {@link ClientCacheFactoryBean}.
|
||||
* @see org.springframework.data.gemfire.client.ClientCacheFactoryBean
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -126,16 +182,27 @@ public class ClientCacheConfiguration extends AbstractCacheConfiguration {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* Configures Spring container infrastructure components and beans used by Spring Data GemFire
|
||||
* to enable Pivotal GemFire or Apache Geode to function properly inside a Spring context.
|
||||
*
|
||||
* This overridden method configures and registers additional Spring components and bean applicable to
|
||||
* {@link ClientCache ClientCaches}.
|
||||
*
|
||||
* @param importMetadata {@link AnnotationMetadata} containing annotation meta-data
|
||||
* for the Spring Data GemFire cache application class.
|
||||
* @see org.springframework.core.type.AnnotationMetadata
|
||||
*/
|
||||
@Override
|
||||
protected void configureInfrastructure(AnnotationMetadata importMetadata) {
|
||||
|
||||
super.configureInfrastructure(importMetadata);
|
||||
|
||||
registerClientRegionPoolBeanFactoryPostProcessor(importMetadata);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected void registerClientRegionPoolBeanFactoryPostProcessor(AnnotationMetadata importMetadata) {
|
||||
private void registerClientRegionPoolBeanFactoryPostProcessor(AnnotationMetadata importMetadata) {
|
||||
|
||||
if (CLIENT_REGION_POOL_BEAN_FACTORY_POST_PROCESSOR_REGISTERED.compareAndSet(false, true)) {
|
||||
register(BeanDefinitionBuilder.rootBeanDefinition(ClientRegionPoolBeanFactoryPostProcessor.class)
|
||||
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE).getBeanDefinition());
|
||||
@@ -143,17 +210,20 @@ public class ClientCacheConfiguration extends AbstractCacheConfiguration {
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures GemFire {@link org.apache.geode.cache.client.ClientCache} specific settings.
|
||||
* Configures {@link ClientCache} specific settings.
|
||||
*
|
||||
* @param importMetadata {@link AnnotationMetadata} containing client cache meta-data used to configure
|
||||
* the GemFire {@link org.apache.geode.cache.client.ClientCache}.
|
||||
* @param importMetadata {@link AnnotationMetadata} containing client cache meta-data used to
|
||||
* configure the {@link ClientCache}.
|
||||
* @see org.springframework.core.type.AnnotationMetadata
|
||||
* @see #configureLocatorsAndServers(Map)
|
||||
*/
|
||||
@Override
|
||||
protected void configureCache(AnnotationMetadata importMetadata) {
|
||||
|
||||
super.configureCache(importMetadata);
|
||||
|
||||
if (isClientCacheApplication(importMetadata)) {
|
||||
|
||||
Map<String, Object> clientCacheApplicationAttributes =
|
||||
importMetadata.getAnnotationAttributes(getAnnotationTypeName());
|
||||
|
||||
@@ -185,16 +255,16 @@ public class ClientCacheConfiguration extends AbstractCacheConfiguration {
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses the list of GemFire Locator and Server connection endpoint definitions and meta-data to configure
|
||||
* the GemFire client {@link org.apache.geode.cache.client.Pool} used to communicate with the servers
|
||||
* in the GemFire cluster.
|
||||
* Uses the list of Pivotal GemFire/Apache Geode Locator and Server connection endpoint definitions and meta-data
|
||||
* to configure the client {@link Pool} used to communicate with the servers in the cluster.
|
||||
*
|
||||
* @param clientCacheApplicationAttributes {@link ClientCacheApplication} annotation containing
|
||||
* {@link org.apache.geode.cache.client.Pool} Locator/Server connection endpoint meta-data.
|
||||
* @param clientCacheApplicationAttributes {@link ClientCacheApplication} annotation containing {@link Pool}
|
||||
* Locator/Server connection endpoint meta-data.
|
||||
* @see org.springframework.data.gemfire.config.annotation.ClientCacheApplication
|
||||
* @see java.util.Map
|
||||
*/
|
||||
protected void configureLocatorsAndServers(Map<String, Object> clientCacheApplicationAttributes) {
|
||||
private void configureLocatorsAndServers(Map<String, Object> clientCacheApplicationAttributes) {
|
||||
|
||||
ConnectionEndpointList poolLocators = new ConnectionEndpointList();
|
||||
|
||||
AnnotationAttributes[] locators = (AnnotationAttributes[]) clientCacheApplicationAttributes.get("locators");
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.springframework.data.gemfire.config.annotation;
|
||||
|
||||
import org.apache.geode.cache.client.ClientCache;
|
||||
import org.springframework.data.gemfire.client.ClientCacheFactoryBean;
|
||||
|
||||
/**
|
||||
* The {@link ClientCacheConfigurer} interface defines a contract for implementations to customize the configuration
|
||||
* of a {@link ClientCacheFactoryBean} used to construct, configure and initialize an instance of a {@link ClientCache}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @see org.springframework.data.gemfire.client.ClientCacheFactoryBean
|
||||
* @see org.springframework.data.gemfire.config.annotation.ClientCacheApplication
|
||||
* @since 1.9.0
|
||||
*/
|
||||
public interface ClientCacheConfigurer {
|
||||
|
||||
/**
|
||||
* Configuration callback method providing a reference to a {@link ClientCacheFactoryBean} used to construct,
|
||||
* configure and initialize an instance of {@link ClientCache}.
|
||||
*
|
||||
* @param beanName name of {@link ClientCache} bean declared in the Spring application context.
|
||||
* @param bean reference to the {@link ClientCacheFactoryBean}.
|
||||
* @see org.springframework.data.gemfire.CacheFactoryBean
|
||||
*/
|
||||
void configure(String beanName, ClientCacheFactoryBean bean);
|
||||
|
||||
}
|
||||
@@ -17,6 +17,19 @@
|
||||
|
||||
package org.springframework.data.gemfire.config.annotation;
|
||||
|
||||
import static org.springframework.data.gemfire.util.CollectionUtils.nullSafeMap;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
@@ -40,17 +53,25 @@ import org.springframework.data.gemfire.util.ArrayUtils;
|
||||
* @see org.springframework.data.gemfire.DiskStoreFactoryBean
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableDiskStore
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableDiskStores
|
||||
* @see org.springframework.data.gemfire.config.annotation.DiskStoreConfigurer
|
||||
* @see org.apache.geode.cache.DiskStore
|
||||
* @since 1.9.0
|
||||
*/
|
||||
public class DiskStoreConfiguration implements ImportBeanDefinitionRegistrar {
|
||||
public class DiskStoreConfiguration implements BeanFactoryAware, ImportBeanDefinitionRegistrar {
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
@Autowired(required = false)
|
||||
private List<DiskStoreConfigurer> diskStoreConfigurers = Collections.emptyList();
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
|
||||
|
||||
if (importingClassMetadata.hasAnnotation(EnableDiskStore.class.getName())) {
|
||||
|
||||
AnnotationAttributes enableDiskStoreAttributes = AnnotationAttributes.fromMap(
|
||||
importingClassMetadata.getAnnotationAttributes(EnableDiskStore.class.getName()));
|
||||
|
||||
@@ -71,6 +92,8 @@ public class DiskStoreConfiguration implements ImportBeanDefinitionRegistrar {
|
||||
|
||||
diskStoreFactoryBeanBuilder.addPropertyReference("cache", GemfireConstants.DEFAULT_GEMFIRE_CACHE_NAME);
|
||||
|
||||
diskStoreFactoryBeanBuilder.addPropertyValue("diskStoreConfigurers", resolveDiskStoreConfigurers());
|
||||
|
||||
setPropertyValueIfNotDefault(diskStoreFactoryBeanBuilder, "allowForceCompaction",
|
||||
enableDiskStoreAttributes.getBoolean("allowForceCompaction"), false);
|
||||
|
||||
@@ -103,6 +126,24 @@ public class DiskStoreConfiguration implements ImportBeanDefinitionRegistrar {
|
||||
registry.registerBeanDefinition(diskStoreName, diskStoreFactoryBeanBuilder.getBeanDefinition());
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private List<DiskStoreConfigurer> resolveDiskStoreConfigurers() {
|
||||
|
||||
return Optional.ofNullable(this.diskStoreConfigurers)
|
||||
.filter(diskStoreConfigurers -> !diskStoreConfigurers.isEmpty())
|
||||
.orElseGet(() ->
|
||||
Optional.of(this.beanFactory)
|
||||
.filter(beanFactory -> beanFactory instanceof ListableBeanFactory)
|
||||
.map(beanFactory -> {
|
||||
Map<String, DiskStoreConfigurer> beansOfType = ((ListableBeanFactory) beanFactory)
|
||||
.getBeansOfType(DiskStoreConfigurer.class, true, true);
|
||||
|
||||
return nullSafeMap(beansOfType).values().stream().collect(Collectors.toList());
|
||||
})
|
||||
.orElseGet(Collections::emptyList)
|
||||
);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected BeanDefinitionBuilder parseDiskStoreDiskDirectories(AnnotationMetadata importingClassMetadata,
|
||||
AnnotationAttributes enableDiskStoreAttributes, BeanDefinitionBuilder diskStoreBeanFactoryBuilder) {
|
||||
@@ -131,9 +172,14 @@ public class DiskStoreConfiguration implements ImportBeanDefinitionRegistrar {
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private <T> BeanDefinitionBuilder setPropertyValueIfNotDefault(BeanDefinitionBuilder beanDefinitionBuilder,
|
||||
String propertyName, T value, T defaultValue) {
|
||||
String propertyName, T value, T defaultValue) {
|
||||
|
||||
return (value != null && !value.equals(defaultValue) ?
|
||||
beanDefinitionBuilder.addPropertyValue(propertyName, value) : beanDefinitionBuilder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.gemfire.config.annotation;
|
||||
|
||||
import org.apache.geode.cache.DiskStore;
|
||||
import org.springframework.data.gemfire.DiskStoreFactoryBean;
|
||||
|
||||
/**
|
||||
* The {@link DiskStoreConfigurer} interface defines a contract for implementations to customize the configuration
|
||||
* of a {@link DiskStoreFactoryBean} used to construct, configure and initialize a {@link DiskStore}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.DiskStore
|
||||
* @see org.springframework.data.gemfire.DiskStoreFactoryBean
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableDiskStore
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableDiskStores
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public interface DiskStoreConfigurer {
|
||||
|
||||
/**
|
||||
* Configuration callback method providing a reference to a {@link DiskStoreFactoryBean} used to construct,
|
||||
* configure and initialize an instance of {@link DiskStore}.
|
||||
*
|
||||
* @param beanName name of the {@link DiskStore} bean declared in the Spring application context.
|
||||
* @param bean reference to the {@link DiskStoreFactoryBean}.
|
||||
* @see org.springframework.data.gemfire.DiskStoreFactoryBean
|
||||
*/
|
||||
void configure(String beanName, DiskStoreFactoryBean bean);
|
||||
|
||||
}
|
||||
@@ -41,8 +41,10 @@ import org.springframework.data.gemfire.server.SubscriptionEvictionPolicy;
|
||||
* the {@link EnableCacheServers} annotation.
|
||||
|
||||
* @author John Blum
|
||||
* @see org.springframework.data.gemfire.config.annotation.AddCacheServerConfiguration
|
||||
* @see org.apache.geode.cache.server.CacheServer
|
||||
* @see org.springframework.data.gemfire.config.annotation.AddCacheServerConfiguration
|
||||
* @see org.springframework.data.gemfire.config.annotation.CacheServerConfigurer
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableCacheServers
|
||||
* @since 1.9.0
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@@ -117,6 +119,13 @@ public @interface EnableCacheServer {
|
||||
*/
|
||||
int messageTimeToLive() default CacheServer.DEFAULT_MESSAGE_TIME_TO_LIVE;
|
||||
|
||||
/**
|
||||
* Configures the name of the Spring bean defined in the Spring application context.
|
||||
*
|
||||
* Defaults to empty.
|
||||
*/
|
||||
String name() default "";
|
||||
|
||||
/**
|
||||
* Configures the port on which this cache server listens for clients.
|
||||
*
|
||||
|
||||
@@ -24,14 +24,17 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.apache.geode.cache.server.CacheServer;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* The {@link EnableCacheServers} annotation enables 1 or more GemFire {@link org.apache.geode.cache.server.CacheServer CacheServers}
|
||||
* to be defined and used in a GemFire peer cache application configured with Spring (Data GemFire).
|
||||
* The {@link EnableCacheServers} annotation enables 1 or more {@link CacheServer CacheServers}
|
||||
* to be defined and used in a peer cache application configured with Spring (Data GemFire/Geode).
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.server.CacheServer
|
||||
* @see org.springframework.data.gemfire.config.annotation.AddCacheServersConfiguration
|
||||
* @see org.springframework.data.gemfire.config.annotation.CacheServerConfigurer
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableCacheServer
|
||||
* @since 1.9.0
|
||||
*/
|
||||
|
||||
@@ -34,12 +34,13 @@ import org.springframework.core.annotation.AliasFor;
|
||||
* {@link org.apache.geode.cache.Region Regions}
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.DiskStore
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.springframework.context.annotation.Import
|
||||
* @see org.springframework.core.annotation.AliasFor
|
||||
* @see org.springframework.data.gemfire.config.annotation.DiskStoreConfiguration
|
||||
* @see org.springframework.data.gemfire.config.annotation.DiskStoreConfigurer
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableDiskStores
|
||||
* @see org.apache.geode.cache.DiskStore
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @since 1.9.0
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
|
||||
@@ -33,11 +33,12 @@ import org.springframework.context.annotation.Import;
|
||||
* {@link org.apache.geode.cache.Region Regions}
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.context.annotation.Import
|
||||
* @see org.springframework.data.gemfire.config.annotation.DiskStoresConfiguration
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableDiskStore
|
||||
* @see org.apache.geode.cache.DiskStore
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.springframework.context.annotation.Import
|
||||
* @see org.springframework.data.gemfire.config.annotation.DiskStoresConfiguration
|
||||
* @see org.springframework.data.gemfire.config.annotation.DiskStoreConfigurer
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableDiskStore
|
||||
* @since 1.9.0
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
|
||||
@@ -26,21 +26,26 @@ import java.lang.annotation.Target;
|
||||
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
|
||||
/**
|
||||
* The {@link EnableEntityDefinedRegions} annotation marks a Spring {@link org.springframework.context.annotation.Configuration @Configuration}
|
||||
* The {@link EnableEntityDefinedRegions} annotation marks a Spring {@link Configuration @Configuration} application
|
||||
* annotated class to enable the creation of the GemFire/Geode {@link Region Regions} based on
|
||||
* the application domain model object entities.
|
||||
* the application persistent entities.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.springframework.context.annotation.ComponentScan
|
||||
* @see org.springframework.context.annotation.ComponentScan.Filter
|
||||
* @see org.springframework.context.annotation.Import
|
||||
* @see org.springframework.core.annotation.AliasFor
|
||||
* @see org.springframework.data.gemfire.RegionFactoryBean
|
||||
* @see org.springframework.data.gemfire.client.ClientRegionFactoryBean
|
||||
* @see org.springframework.data.gemfire.config.annotation.EntityDefinedRegionsConfiguration
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.springframework.data.gemfire.config.annotation.IndexConfiguration
|
||||
* @see org.springframework.data.gemfire.config.annotation.support.GemFireCacheTypeAwareRegionFactoryBean
|
||||
* @since 1.9.0
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@@ -62,7 +67,10 @@ public @interface EnableEntityDefinedRegions {
|
||||
|
||||
/**
|
||||
* Base packages to scan for {@link org.springframework.data.gemfire.mapping.annotation.Region @Region} annotated
|
||||
* application persistent entities. {@link #value()} is an alias for this attribute.
|
||||
* application persistent entities.
|
||||
*
|
||||
* The {@link #value()} attribute is an alias for this attribute.
|
||||
*
|
||||
* Use {@link #basePackageClasses()} for a type-safe alternative to String-based package names.
|
||||
*
|
||||
* @return a {@link String} array specifying the packages to search for application persistent entities.
|
||||
@@ -72,10 +80,13 @@ public @interface EnableEntityDefinedRegions {
|
||||
String[] basePackages() default {};
|
||||
|
||||
/**
|
||||
* Type-safe alternative to {@link #basePackages()} for specifying the packages to scan for
|
||||
* Type-safe alternative to the {@link #basePackages()} attribute for specifying the packages to scan for
|
||||
* {@link org.springframework.data.gemfire.mapping.annotation.Region @Region} annotated application persistent entities.
|
||||
* The package of each class specified will be scanned. Consider creating a special no-op marker class or interface
|
||||
* in each package that serves no other purpose than being referenced by this attribute.
|
||||
*
|
||||
* The package of each class specified will be scanned.
|
||||
*
|
||||
* Consider creating a special no-op marker class or interface in each package that serves no other purpose
|
||||
* than being referenced by this attribute.
|
||||
*
|
||||
* @return an array of {@link Class classes} used to determine the packages to scan
|
||||
* for application persistent entities.
|
||||
@@ -91,12 +102,13 @@ public @interface EnableEntityDefinedRegions {
|
||||
ComponentScan.Filter[] excludeFilters() default {};
|
||||
|
||||
/**
|
||||
* Specifies which types are eligible for component scanning. Further narrows the set of candidate components
|
||||
* from everything in {@link #basePackages()} to everything in the base packages that matches the given filter
|
||||
* or filters.
|
||||
* Specifies which types are eligible for component scanning.
|
||||
*
|
||||
* @return an array {@link org.springframework.context.annotation.ComponentScan.Filter} of Filters used to
|
||||
* specify application persistent entities to be included during the component scan.
|
||||
* Further narrows the set of candidate components from everything in {@link #basePackages()}
|
||||
* or {@link #basePackageClasses()} to everything in the base packages that matches the given filter or filters.
|
||||
*
|
||||
* @return an array {@link ComponentScan.Filter} of Filters used to specify application persistent entities
|
||||
* to be included during the component scan.
|
||||
*/
|
||||
ComponentScan.Filter[] includeFilters() default {};
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import java.lang.annotation.Target;
|
||||
|
||||
import org.apache.geode.cache.EvictionAttributes;
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.apache.geode.cache.util.ObjectSizer;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.gemfire.eviction.EvictionActionType;
|
||||
import org.springframework.data.gemfire.eviction.EvictionPolicyType;
|
||||
@@ -72,7 +73,7 @@ public @interface EnableEviction {
|
||||
*
|
||||
* Defaults to {@link EvictionActionType#LOCAL_DESTROY}.
|
||||
*
|
||||
* @see org.springframework.data.gemfire.EvictionActionType
|
||||
* @see org.springframework.data.gemfire.eviction.EvictionActionType
|
||||
*/
|
||||
EvictionActionType action() default EvictionActionType.LOCAL_DESTROY;
|
||||
|
||||
@@ -84,8 +85,8 @@ public @interface EnableEviction {
|
||||
int maximum() default EvictionAttributes.DEFAULT_ENTRIES_MAXIMUM;
|
||||
|
||||
/**
|
||||
* Name of a Spring bean of type {@link ObjectSizer} defined in the Spring context used
|
||||
* to size {@link Region} entry values.
|
||||
* Name of a Spring bean of type {@link ObjectSizer} defined in the Spring application context
|
||||
* used to size {@link Region} entry values.
|
||||
*
|
||||
* Defaults to empty.
|
||||
*
|
||||
@@ -94,14 +95,14 @@ public @interface EnableEviction {
|
||||
String objectSizerName() default "";
|
||||
|
||||
/**
|
||||
* Names of {@link Region Regions} for which this Eviction policy applies.
|
||||
* Names of all the {@link Region Regions} in which this Eviction policy will be applied.
|
||||
*
|
||||
* Defaults to empty.
|
||||
*/
|
||||
String[] regionNames() default {};
|
||||
|
||||
/**
|
||||
* Eviction alorithm used during Eviction.
|
||||
* Eviction algorithm used during Eviction.
|
||||
*
|
||||
* Defaults to {@link EvictionPolicyType#ENTRY_COUNT}.
|
||||
*
|
||||
|
||||
@@ -133,6 +133,7 @@ public @interface EnableExpiration {
|
||||
* @see <a href="http://geode.incubator.apache.org/docs/guide/developing/expiration/chapter_overview.html">Geode Expiration</a>
|
||||
*/
|
||||
enum ExpirationType {
|
||||
|
||||
IDLE_TIMEOUT("TTI"),
|
||||
TIME_TO_LIVE("TTL");
|
||||
|
||||
|
||||
@@ -24,16 +24,23 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.apache.geode.cache.lucene.LuceneIndex;
|
||||
import org.apache.geode.cache.query.Index;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* The {@link EnableIndexing} annotation marks a Spring {@link org.springframework.context.annotation.Configuration @Configuration}
|
||||
* annotated application class to enable the creation of GemFire/Geode Indexes based on application persistent entity
|
||||
* field/property annotations, such as the {@link @Id}, {@link @Indexed} and {@link @LuceneIndex} annotations.
|
||||
* The {@link EnableIndexing} annotation marks a Spring {@link Configuration @Configuration} annotated application class
|
||||
* to enable the creation of GemFire/Geode {@link Index Indexes} and {@link LuceneIndex LuceneIndexes} based on
|
||||
* application persistent entity field/property annotations, such as the {@link @Id}, {@link @Indexed}
|
||||
* and {@link @LuceneIndex} annotations.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.data.gemfire.config.annotation.IndexConfiguration
|
||||
* @see org.apache.geode.cache.lucene.LuceneIndex
|
||||
* @see org.apache.geode.cache.query.Index
|
||||
* @see org.springframework.data.gemfire.IndexFactoryBean
|
||||
* @see org.springframework.data.gemfire.config.annotation.IndexConfiguration
|
||||
* @see org.springframework.data.gemfire.config.annotation.IndexConfigurer
|
||||
* @see org.springframework.data.gemfire.search.lucene.LuceneIndexFactoryBean
|
||||
* @since 1.9.0
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@@ -46,9 +53,12 @@ public @interface EnableIndexing {
|
||||
/**
|
||||
* Determines whether all GemFire/Geode {@link Index Indexes} will be defined before created.
|
||||
* If set to {@literal true}, then all {@link Index Indexes} are defined first and the created
|
||||
* in a single, bulk operation, thereby improving index creation efficiency.
|
||||
* in a single, bulk operation, thereby improving {@link Index} creation process efficiency.
|
||||
*
|
||||
* Defaults to false.
|
||||
* Only applies to OQL-based {@link Index Indexes}. {@link LuceneIndex LuceneIndexes} are managed differently
|
||||
* by GemFire/Geode.
|
||||
*
|
||||
* Defaults to {@literal false}.
|
||||
*/
|
||||
boolean define() default false;
|
||||
|
||||
|
||||
@@ -40,9 +40,11 @@ import org.springframework.data.gemfire.GemfireUtils;
|
||||
* annotation.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.data.gemfire.config.annotation.AddPoolConfiguration
|
||||
* @see org.apache.geode.cache.client.Pool
|
||||
* @see org.apache.geode.cache.client.PoolFactory
|
||||
* @see org.springframework.data.gemfire.config.annotation.AddPoolConfiguration
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnablePools
|
||||
* @see org.springframework.data.gemfire.config.annotation.PoolConfigurer
|
||||
* @since 1.9.0
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.springframework.context.annotation.Import;
|
||||
* @author John Blum
|
||||
* @see org.springframework.data.gemfire.config.annotation.AddPoolsConfiguration
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnablePool
|
||||
* @see org.springframework.data.gemfire.config.annotation.PoolConfigurer
|
||||
* @since 1.9.0
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
|
||||
@@ -20,15 +20,20 @@ package org.springframework.data.gemfire.config.annotation;
|
||||
import static java.util.Arrays.stream;
|
||||
import static org.springframework.data.gemfire.util.ArrayUtils.defaultIfEmpty;
|
||||
import static org.springframework.data.gemfire.util.ArrayUtils.nullSafeArray;
|
||||
import static org.springframework.data.gemfire.util.CollectionUtils.nullSafeMap;
|
||||
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalArgumentException;
|
||||
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalStateException;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.apache.geode.cache.client.ClientRegionShortcut;
|
||||
@@ -37,6 +42,8 @@ import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
@@ -82,7 +89,9 @@ import org.springframework.util.StringUtils;
|
||||
* based on the application persistent entity classes.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.lang.ClassLoader
|
||||
* @see java.lang.annotation.Annotation
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.springframework.beans.factory.BeanClassLoaderAware
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see org.springframework.beans.factory.BeanFactoryAware
|
||||
@@ -106,7 +115,6 @@ import org.springframework.util.StringUtils;
|
||||
* @see org.springframework.data.gemfire.mapping.annotation.PartitionRegion
|
||||
* @see org.springframework.data.gemfire.mapping.annotation.ReplicateRegion
|
||||
* @see org.springframework.data.gemfire.mapping.annotation.Region
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @since 1.9.0
|
||||
*/
|
||||
public class EntityDefinedRegionsConfiguration
|
||||
@@ -133,6 +141,9 @@ public class EntityDefinedRegionsConfiguration
|
||||
|
||||
private GemfireMappingContext mappingContext;
|
||||
|
||||
@Autowired(required = false)
|
||||
private List<RegionConfigurer> regionConfigurers = Collections.emptyList();
|
||||
|
||||
/**
|
||||
* Returns the {@link Annotation} {@link Class type} that configures and creates {@link Region Regions}
|
||||
* for application persistent entities.
|
||||
@@ -230,9 +241,9 @@ public class EntityDefinedRegionsConfiguration
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected GemfirePersistentEntity<?> getPersistentEntity(Class<?> persistentEntityType) {
|
||||
|
||||
return resolveMappingContext().getPersistentEntity(persistentEntityType).orElseThrow(
|
||||
() -> new IllegalStateException(String.format("PersistentEntity for type [%s] not found",
|
||||
persistentEntityType)));
|
||||
() -> newIllegalStateException("PersistentEntity for type [%s] not found", persistentEntityType));
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@@ -254,19 +265,21 @@ public class EntityDefinedRegionsConfiguration
|
||||
*/
|
||||
@Override
|
||||
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
|
||||
|
||||
if (isAnnotationPresent(importingClassMetadata)) {
|
||||
|
||||
AnnotationAttributes enableEntityDefinedRegionsAttributes = getAnnotationAttributes(importingClassMetadata);
|
||||
|
||||
boolean strict = enableEntityDefinedRegionsAttributes.getBoolean("strict");
|
||||
|
||||
for (Class<?> persistentEntityClass : newGemFireComponentClassTypeScanner(
|
||||
importingClassMetadata, enableEntityDefinedRegionsAttributes).scan()) {
|
||||
newGemFireComponentClassTypeScanner(importingClassMetadata, enableEntityDefinedRegionsAttributes).scan()
|
||||
.forEach(persistentEntityClass -> {
|
||||
|
||||
GemfirePersistentEntity persistentEntity = getPersistentEntity(persistentEntityClass);
|
||||
GemfirePersistentEntity persistentEntity = getPersistentEntity(persistentEntityClass);
|
||||
|
||||
registerRegionBeanDefinition(persistentEntity, strict, registry);
|
||||
postProcess(importingClassMetadata, registry, persistentEntity);
|
||||
}
|
||||
registerRegionBeanDefinition(persistentEntity, strict, registry);
|
||||
postProcess(importingClassMetadata, registry, persistentEntity);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -274,8 +287,8 @@ public class EntityDefinedRegionsConfiguration
|
||||
protected GemFireComponentClassTypeScanner newGemFireComponentClassTypeScanner(
|
||||
AnnotationMetadata importingClassMetadata, AnnotationAttributes enableEntityDefinedRegionsAttributes) {
|
||||
|
||||
Set<String> resolvedBasePackages = resolveBasePackages(importingClassMetadata,
|
||||
enableEntityDefinedRegionsAttributes);
|
||||
Set<String> resolvedBasePackages =
|
||||
resolveBasePackages(importingClassMetadata, enableEntityDefinedRegionsAttributes);
|
||||
|
||||
return GemFireComponentClassTypeScanner.from(resolvedBasePackages).with(resolveBeanClassLoader())
|
||||
.withExcludes(resolveExcludes(enableEntityDefinedRegionsAttributes))
|
||||
@@ -323,6 +336,7 @@ public class EntityDefinedRegionsConfiguration
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private Iterable<TypeFilter> parseFilters(AnnotationAttributes[] componentScanFilterAttributes) {
|
||||
|
||||
Set<TypeFilter> typeFilters = new HashSet<>();
|
||||
|
||||
stream(nullSafeArray(componentScanFilterAttributes, AnnotationAttributes.class))
|
||||
@@ -334,43 +348,45 @@ public class EntityDefinedRegionsConfiguration
|
||||
/* (non-Javadoc) */
|
||||
@SuppressWarnings("unchecked")
|
||||
private Iterable<TypeFilter> typeFiltersFor(AnnotationAttributes filterAttributes) {
|
||||
|
||||
Set<TypeFilter> typeFilters = new HashSet<>();
|
||||
FilterType filterType = filterAttributes.getEnum("type");
|
||||
|
||||
for (Class<?> filterClass : nullSafeArray(filterAttributes.getClassArray("value"), Class.class)) {
|
||||
switch (filterType) {
|
||||
case ANNOTATION:
|
||||
Assert.isAssignable(Annotation.class, filterClass,
|
||||
String.format("@ComponentScan.Filter class [%s] must be an Annotation", filterClass));
|
||||
typeFilters.add(new AnnotationTypeFilter((Class<Annotation>) filterClass));
|
||||
break;
|
||||
case ASSIGNABLE_TYPE:
|
||||
typeFilters.add(new AssignableTypeFilter(filterClass));
|
||||
break;
|
||||
case CUSTOM:
|
||||
Assert.isAssignable(TypeFilter.class, filterClass,
|
||||
String.format("@ComponentScan.Filter class [%s] must be a TypeFilter", filterClass));
|
||||
typeFilters.add(BeanUtils.instantiateClass(filterClass, TypeFilter.class));
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"Illegal filter type [%s] when 'value' or 'classes' are specified", filterType));
|
||||
}
|
||||
|
||||
for (String pattern : nullSafeGetPatterns(filterAttributes)) {
|
||||
stream(nullSafeArray(filterAttributes.getClassArray("value"), Class.class))
|
||||
.forEach(filterClass -> {
|
||||
switch (filterType) {
|
||||
case ASPECTJ:
|
||||
typeFilters.add(new AspectJTypeFilter(pattern, resolveBeanClassLoader()));
|
||||
case ANNOTATION:
|
||||
Assert.isAssignable(Annotation.class, filterClass,
|
||||
String.format("@ComponentScan.Filter class [%s] must be an Annotation", filterClass));
|
||||
typeFilters.add(new AnnotationTypeFilter((Class<Annotation>) filterClass));
|
||||
break;
|
||||
case REGEX:
|
||||
typeFilters.add(new RegexPatternTypeFilter(Pattern.compile(pattern)));
|
||||
case ASSIGNABLE_TYPE:
|
||||
typeFilters.add(new AssignableTypeFilter(filterClass));
|
||||
break;
|
||||
case CUSTOM:
|
||||
Assert.isAssignable(TypeFilter.class, filterClass,
|
||||
String.format("@ComponentScan.Filter class [%s] must be a TypeFilter", filterClass));
|
||||
typeFilters.add(BeanUtils.instantiateClass(filterClass, TypeFilter.class));
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"Illegal filter type [%s] when 'patterns' are specified", filterType));
|
||||
throw newIllegalArgumentException(
|
||||
"Illegal filter type [%s] when 'value' or 'classes' are specified", filterType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (String pattern : nullSafeGetPatterns(filterAttributes)) {
|
||||
switch (filterType) {
|
||||
case ASPECTJ:
|
||||
typeFilters.add(new AspectJTypeFilter(pattern, resolveBeanClassLoader()));
|
||||
break;
|
||||
case REGEX:
|
||||
typeFilters.add(new RegexPatternTypeFilter(Pattern.compile(pattern)));
|
||||
break;
|
||||
default:
|
||||
throw newIllegalArgumentException(
|
||||
"Illegal filter type [%s] when 'patterns' are specified", filterType);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return typeFilters;
|
||||
}
|
||||
@@ -394,6 +410,7 @@ public class EntityDefinedRegionsConfiguration
|
||||
/* (non-Javadoc) */
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Iterable<TypeFilter> regionAnnotatedPersistentEntityTypeFilters() {
|
||||
|
||||
Set<TypeFilter> regionAnnotatedPersistentEntityTypeFilters = new HashSet<>();
|
||||
|
||||
org.springframework.data.gemfire.mapping.annotation.Region.REGION_ANNOTATION_TYPES.forEach(
|
||||
@@ -409,6 +426,7 @@ public class EntityDefinedRegionsConfiguration
|
||||
BeanDefinitionBuilder regionFactoryBeanBuilder =
|
||||
BeanDefinitionBuilder.genericBeanDefinition(resolveRegionFactoryBeanClass(persistentEntity))
|
||||
.addPropertyReference("cache", GemfireConstants.DEFAULT_GEMFIRE_CACHE_NAME)
|
||||
.addPropertyValue("regionConfigurers", resolveRegionConfigurers())
|
||||
.addPropertyValue("close", false);
|
||||
|
||||
setRegionAttributes(persistentEntity, regionFactoryBeanBuilder, strict);
|
||||
@@ -417,6 +435,24 @@ public class EntityDefinedRegionsConfiguration
|
||||
regionFactoryBeanBuilder.getBeanDefinition());
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private List<RegionConfigurer> resolveRegionConfigurers() {
|
||||
|
||||
return Optional.ofNullable(this.regionConfigurers)
|
||||
.filter(regionConfigurers -> !regionConfigurers.isEmpty())
|
||||
.orElseGet(() ->
|
||||
Optional.ofNullable(this.beanFactory)
|
||||
.filter(beanFactory -> beanFactory instanceof ListableBeanFactory)
|
||||
.map(beanFactory -> {
|
||||
Map<String, RegionConfigurer> beansOfType = ((ListableBeanFactory) beanFactory)
|
||||
.getBeansOfType(RegionConfigurer.class, true, true);
|
||||
|
||||
return nullSafeMap(beansOfType).values().stream().collect(Collectors.toList());
|
||||
})
|
||||
.orElseGet(Collections::emptyList)
|
||||
);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Class<? extends RegionLookupFactoryBean> resolveRegionFactoryBeanClass(
|
||||
@@ -492,9 +528,10 @@ public class EntityDefinedRegionsConfiguration
|
||||
/* (non-Javadoc) */
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Class<?> resolveIdType(GemfirePersistentEntity persistentEntity) {
|
||||
|
||||
return (Class<?>) persistentEntity.getIdProperty()
|
||||
.map(idProperty -> ((GemfirePersistentProperty) idProperty).getActualType())
|
||||
.orElse(Object.class);
|
||||
.orElse(Object.class);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@@ -570,6 +607,7 @@ public class EntityDefinedRegionsConfiguration
|
||||
"fixedPartitions", PartitionRegion.FixedPartition.class), PartitionRegion.FixedPartition.class);
|
||||
|
||||
if (!ObjectUtils.isEmpty(fixedPartitions)) {
|
||||
|
||||
ManagedList<BeanDefinition> fixedPartitionAttributesFactoryBeans =
|
||||
new ManagedList<BeanDefinition>(fixedPartitions.length);
|
||||
|
||||
|
||||
@@ -18,17 +18,24 @@
|
||||
package org.springframework.data.gemfire.config.annotation;
|
||||
|
||||
import static org.springframework.data.gemfire.config.annotation.EnableEviction.EvictionPolicy;
|
||||
import static org.springframework.data.gemfire.util.ArrayUtils.nullSafeArray;
|
||||
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.lang.annotation.Annotation;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.geode.cache.EvictionAttributes;
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.apache.geode.cache.util.ObjectSizer;
|
||||
import org.apache.shiro.util.Assert;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
@@ -44,14 +51,11 @@ import org.springframework.data.gemfire.client.ClientRegionFactoryBean;
|
||||
import org.springframework.data.gemfire.eviction.EvictionActionType;
|
||||
import org.springframework.data.gemfire.eviction.EvictionAttributesFactoryBean;
|
||||
import org.springframework.data.gemfire.eviction.EvictionPolicyType;
|
||||
import org.springframework.data.gemfire.util.ArrayUtils;
|
||||
import org.springframework.data.gemfire.util.CollectionUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* The {@link EvictionConfiguration} class is a Spring {@link Configuration @Configuration} annotated class to enable
|
||||
* Eviction policy configuration on GemFire/Geode {@link Region Regions}.
|
||||
* Eviction policy configuration on cache {@link Region Regions}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.beans.factory.config.BeanPostProcessor
|
||||
@@ -76,19 +80,6 @@ public class EvictionConfiguration implements ApplicationContextAware, ImportAwa
|
||||
|
||||
private EvictionPolicyConfigurer evictionPolicyConfigurer;
|
||||
|
||||
/**
|
||||
* Determines whether the Spring bean is an instance of {@link RegionFactoryBean}
|
||||
* or {@link ClientRegionFactoryBean}.
|
||||
*
|
||||
* @param bean Spring bean to evaluate.
|
||||
* @return a boolean value indicating whether the Spring bean is an instance of {@link RegionFactoryBean}.
|
||||
* @see org.springframework.data.gemfire.RegionFactoryBean
|
||||
* @see org.springframework.data.gemfire.client.ClientRegionFactoryBean
|
||||
*/
|
||||
protected static boolean isRegionFactoryBean(Object bean) {
|
||||
return (bean instanceof RegionFactoryBean || bean instanceof ClientRegionFactoryBean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Annotation} {@link Class type} that enables and configures Eviction.
|
||||
*
|
||||
@@ -124,34 +115,52 @@ public class EvictionConfiguration implements ApplicationContextAware, ImportAwa
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* Sets a reference to the Spring {@link ApplicationContext}.
|
||||
*
|
||||
* @param applicationContext Spring {@link ApplicationContext} in use.
|
||||
* @throws BeansException if an error occurs while storing a reference to the Spring {@link ApplicationContext}.
|
||||
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(ApplicationContext)
|
||||
* @see org.springframework.context.ApplicationContext
|
||||
*/
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the Spring bean is an instance of {@link RegionFactoryBean}
|
||||
* or {@link ClientRegionFactoryBean}.
|
||||
*
|
||||
* @param bean Spring bean to evaluate.
|
||||
* @return a boolean value indicating whether the Spring bean is an instance of {@link RegionFactoryBean}
|
||||
* or the {@link ClientRegionFactoryBean}.
|
||||
* @see org.springframework.data.gemfire.RegionFactoryBean
|
||||
* @see org.springframework.data.gemfire.client.ClientRegionFactoryBean
|
||||
*/
|
||||
protected static boolean isRegionFactoryBean(Object bean) {
|
||||
return (bean instanceof RegionFactoryBean || bean instanceof ClientRegionFactoryBean);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void setImportMetadata(AnnotationMetadata importMetadata) {
|
||||
|
||||
if (importMetadata.hasAnnotation(getAnnotationTypeName())) {
|
||||
Map<String, Object> enableEvictionAttributes =
|
||||
importMetadata.getAnnotationAttributes(getAnnotationTypeName());
|
||||
|
||||
AnnotationAttributes[] policies = (AnnotationAttributes[]) enableEvictionAttributes.get("policies");
|
||||
|
||||
for (AnnotationAttributes evictionPolicyAttributes
|
||||
: ArrayUtils.nullSafeArray(policies, AnnotationAttributes.class)) {
|
||||
|
||||
for (AnnotationAttributes evictionPolicyAttributes : nullSafeArray(policies, AnnotationAttributes.class)) {
|
||||
this.evictionPolicyConfigurer = ComposableEvictionPolicyConfigurer.compose(
|
||||
this.evictionPolicyConfigurer, EvictionPolicyMetaData.from(evictionPolicyAttributes,
|
||||
this.applicationContext));
|
||||
}
|
||||
|
||||
this.evictionPolicyConfigurer = (this.evictionPolicyConfigurer != null ? this.evictionPolicyConfigurer
|
||||
: EvictionPolicyMetaData.fromDefaults());
|
||||
this.evictionPolicyConfigurer = Optional.ofNullable(this.evictionPolicyConfigurer)
|
||||
.orElseGet(EvictionPolicyMetaData::fromDefaults);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,16 +172,16 @@ public class EvictionConfiguration implements ApplicationContextAware, ImportAwa
|
||||
* @see org.springframework.data.gemfire.config.annotation.EvictionConfiguration.EvictionPolicyConfigurer
|
||||
*/
|
||||
protected EvictionPolicyConfigurer getEvictionPolicyConfigurer() {
|
||||
Assert.state(this.evictionPolicyConfigurer != null,
|
||||
"EvictionPolicyConfigurer was not properly configured and initialized");
|
||||
|
||||
return this.evictionPolicyConfigurer;
|
||||
return Optional.ofNullable(this.evictionPolicyConfigurer).orElseThrow(() ->
|
||||
newIllegalStateException("EvictionPolicyConfigurer was not properly configured and initialized"));
|
||||
}
|
||||
|
||||
@Bean
|
||||
@SuppressWarnings("unused")
|
||||
public BeanPostProcessor evictionBeanPostProcessor() {
|
||||
|
||||
return new BeanPostProcessor() {
|
||||
|
||||
@Override
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
return (isRegionFactoryBean(bean) ? getEvictionPolicyConfigurer().configure(bean) : bean);
|
||||
@@ -228,7 +237,7 @@ public class EvictionConfiguration implements ApplicationContextAware, ImportAwa
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
protected static EvictionPolicyConfigurer compose(EvictionPolicyConfigurer[] array) {
|
||||
return compose(Arrays.asList(ArrayUtils.nullSafeArray(array, EvictionPolicyConfigurer.class)));
|
||||
return compose(Arrays.asList(nullSafeArray(array, EvictionPolicyConfigurer.class)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -242,9 +251,10 @@ public class EvictionConfiguration implements ApplicationContextAware, ImportAwa
|
||||
* @see #compose(EvictionPolicyConfigurer, EvictionPolicyConfigurer)
|
||||
*/
|
||||
protected static EvictionPolicyConfigurer compose(Iterable<EvictionPolicyConfigurer> iterable) {
|
||||
|
||||
EvictionPolicyConfigurer current = null;
|
||||
|
||||
for (EvictionPolicyConfigurer evictionPolicyConfigurer : CollectionUtils.nullSafeIterable(iterable)) {
|
||||
for (EvictionPolicyConfigurer evictionPolicyConfigurer : nullSafeIterable(iterable)) {
|
||||
current = compose(current, evictionPolicyConfigurer);
|
||||
}
|
||||
|
||||
@@ -291,26 +301,28 @@ public class EvictionConfiguration implements ApplicationContextAware, ImportAwa
|
||||
|
||||
private final EvictionAttributes evictionAttributes;
|
||||
|
||||
private final Set<String> regionNames = new HashSet<String>();
|
||||
private final Set<String> regionNames = new HashSet<>();
|
||||
|
||||
protected static EvictionPolicyMetaData from(AnnotationAttributes evictionPolicyAttributes,
|
||||
ApplicationContext applicationContext) {
|
||||
|
||||
return from((Integer) evictionPolicyAttributes.get("maximum"),
|
||||
evictionPolicyAttributes.<EvictionPolicyType>getEnum("type"),
|
||||
evictionPolicyAttributes.<EvictionActionType>getEnum("action"),
|
||||
resolveObjectSizer(evictionPolicyAttributes.getString("objectSizerName"), applicationContext),
|
||||
evictionPolicyAttributes.getStringArray("regionNames"));
|
||||
Assert.isAssignable(EvictionPolicy.class, evictionPolicyAttributes.annotationType());
|
||||
|
||||
return from(evictionPolicyAttributes.getEnum("type"),
|
||||
(Integer) evictionPolicyAttributes.get("maximum"),
|
||||
evictionPolicyAttributes.getEnum("action"),
|
||||
resolveObjectSizer(evictionPolicyAttributes.getString("objectSizerName"), applicationContext),
|
||||
evictionPolicyAttributes.getStringArray("regionNames"));
|
||||
}
|
||||
|
||||
protected static EvictionPolicyMetaData from(EvictionPolicy evictionPolicy,
|
||||
ApplicationContext applicationContext) {
|
||||
|
||||
return from(evictionPolicy.maximum(), evictionPolicy.type(), evictionPolicy.action(),
|
||||
return from(evictionPolicy.type(), evictionPolicy.maximum(), evictionPolicy.action(),
|
||||
resolveObjectSizer(evictionPolicy.objectSizerName(), applicationContext), evictionPolicy.regionNames());
|
||||
}
|
||||
|
||||
protected static EvictionPolicyMetaData from(int maximum, EvictionPolicyType type, EvictionActionType action,
|
||||
protected static EvictionPolicyMetaData from(EvictionPolicyType type, int maximum, EvictionActionType action,
|
||||
ObjectSizer objectSizer, String... regionNames) {
|
||||
|
||||
EvictionAttributesFactoryBean factoryBean = new EvictionAttributesFactoryBean();
|
||||
@@ -329,6 +341,7 @@ public class EvictionConfiguration implements ApplicationContextAware, ImportAwa
|
||||
}
|
||||
|
||||
protected static ObjectSizer resolveObjectSizer(String objectSizerName, ApplicationContext applicationContext) {
|
||||
|
||||
boolean resolvable = StringUtils.hasText(objectSizerName)
|
||||
&& applicationContext.containsBean(objectSizerName);
|
||||
|
||||
@@ -374,10 +387,11 @@ public class EvictionConfiguration implements ApplicationContextAware, ImportAwa
|
||||
* @see org.apache.geode.cache.EvictionAttributes
|
||||
*/
|
||||
protected EvictionPolicyMetaData(EvictionAttributes evictionAttributes, String[] regionNames) {
|
||||
Assert.notNull(evictionAttributes, "EvictionAttributes must not be null");
|
||||
|
||||
this.evictionAttributes = evictionAttributes;
|
||||
Collections.addAll(this.regionNames, ArrayUtils.nullSafeArray(regionNames, String.class));
|
||||
this.evictionAttributes = Optional.ofNullable(evictionAttributes)
|
||||
.orElseThrow(() -> newIllegalArgumentException("EvictionAttributes are required"));
|
||||
|
||||
Collections.addAll(this.regionNames, nullSafeArray(regionNames, String.class));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -390,10 +404,8 @@ public class EvictionConfiguration implements ApplicationContextAware, ImportAwa
|
||||
* @see org.apache.geode.cache.EvictionAttributes
|
||||
*/
|
||||
protected EvictionAttributes getEvictionAttributes() {
|
||||
Assert.state(this.evictionAttributes != null,
|
||||
"EvictionAttributes was not properly configured and initialized");
|
||||
|
||||
return this.evictionAttributes;
|
||||
return Optional.ofNullable(this.evictionAttributes).orElseThrow(() ->
|
||||
newIllegalStateException("EvictionAttributes was not properly configured and initialized"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -403,10 +415,10 @@ public class EvictionConfiguration implements ApplicationContextAware, ImportAwa
|
||||
* @return a boolean value indicating whether the {@link Object} is accepted for Eviction policy configuration.
|
||||
* @see #isRegionFactoryBean(Object)
|
||||
* @see #resolveRegionName(Object)
|
||||
* @see #accepts(String)
|
||||
* @see #accepts(Supplier)
|
||||
*/
|
||||
protected boolean accepts(Object regionFactoryBean) {
|
||||
return (isRegionFactoryBean(regionFactoryBean) && accepts(resolveRegionName(regionFactoryBean)));
|
||||
return (isRegionFactoryBean(regionFactoryBean) && accepts(() -> resolveRegionName(regionFactoryBean)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -415,8 +427,8 @@ public class EvictionConfiguration implements ApplicationContextAware, ImportAwa
|
||||
* @param regionName name of the {@link Region} targeted for Eviction policy configuration.
|
||||
* @return a boolean value if the named {@link Region} is accepted for Eviction policy configuration.
|
||||
*/
|
||||
protected boolean accepts(String regionName) {
|
||||
return (this.regionNames.isEmpty() || this.regionNames.contains(regionName));
|
||||
protected boolean accepts(Supplier<String> regionName) {
|
||||
return (this.regionNames.isEmpty() || this.regionNames.contains(regionName.get()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -444,6 +456,7 @@ public class EvictionConfiguration implements ApplicationContextAware, ImportAwa
|
||||
* @see #getEvictionAttributes()
|
||||
*/
|
||||
protected Object setEvictionAttributes(Object regionFactoryBean) {
|
||||
|
||||
if (regionFactoryBean instanceof RegionFactoryBean) {
|
||||
((RegionFactoryBean) regionFactoryBean).setEvictionAttributes(getEvictionAttributes());
|
||||
}
|
||||
|
||||
@@ -19,11 +19,15 @@ package org.springframework.data.gemfire.config.annotation;
|
||||
|
||||
import static org.springframework.data.gemfire.config.annotation.EnableExpiration.ExpirationPolicy;
|
||||
import static org.springframework.data.gemfire.config.annotation.EnableExpiration.ExpirationType;
|
||||
import static org.springframework.data.gemfire.util.ArrayUtils.nullSafeArray;
|
||||
import static org.springframework.data.gemfire.util.CollectionUtils.nullSafeIterable;
|
||||
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalStateException;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.geode.cache.AttributesMutator;
|
||||
@@ -39,9 +43,7 @@ import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.data.gemfire.expiration.AnnotationBasedExpiration;
|
||||
import org.springframework.data.gemfire.expiration.ExpirationActionType;
|
||||
import org.springframework.data.gemfire.util.ArrayUtils;
|
||||
import org.springframework.data.gemfire.util.CollectionUtils;
|
||||
import org.springframework.data.gemfire.util.SpringUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -70,7 +72,7 @@ public class ExpirationConfiguration implements ImportAware {
|
||||
/**
|
||||
* Returns the {@link Annotation} {@link Class type} that enables and configures Expiration.
|
||||
*
|
||||
* @return {@link Annotation} {@link Class type} that enables and configures Expiration.
|
||||
* @return the {@link Annotation} {@link Class type} that enables and configures Expiration.
|
||||
* @see java.lang.annotation.Annotation
|
||||
* @see java.lang.Class
|
||||
*/
|
||||
@@ -106,22 +108,22 @@ public class ExpirationConfiguration implements ImportAware {
|
||||
*/
|
||||
@Override
|
||||
public void setImportMetadata(AnnotationMetadata importMetadata) {
|
||||
|
||||
if (importMetadata.hasAnnotation(getAnnotationTypeName())) {
|
||||
Map<String, Object> enableExpirationAttributes =
|
||||
importMetadata.getAnnotationAttributes(getAnnotationTypeName());
|
||||
|
||||
AnnotationAttributes[] policies =
|
||||
(AnnotationAttributes[]) enableExpirationAttributes.get("policies");
|
||||
AnnotationAttributes[] policies = (AnnotationAttributes[]) enableExpirationAttributes.get("policies");
|
||||
|
||||
for (AnnotationAttributes expirationPolicyAttributes :
|
||||
ArrayUtils.nullSafeArray(policies, AnnotationAttributes.class)) {
|
||||
nullSafeArray(policies, AnnotationAttributes.class)) {
|
||||
|
||||
this.expirationPolicyConfigurer = ComposableExpirationPolicyConfigurer.compose(
|
||||
this.expirationPolicyConfigurer, ExpirationPolicyMetaData.from(expirationPolicyAttributes));
|
||||
}
|
||||
|
||||
this.expirationPolicyConfigurer = (this.expirationPolicyConfigurer != null ? this.expirationPolicyConfigurer
|
||||
: ExpirationPolicyMetaData.fromDefaults());
|
||||
this.expirationPolicyConfigurer = Optional.ofNullable(this.expirationPolicyConfigurer)
|
||||
.orElseGet(ExpirationPolicyMetaData::fromDefaults);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,16 +139,16 @@ public class ExpirationConfiguration implements ImportAware {
|
||||
}
|
||||
|
||||
protected ExpirationPolicyConfigurer getExpirationPolicyConfigurer() {
|
||||
Assert.state(this.expirationPolicyConfigurer != null,
|
||||
"ExpirationPolicyConfigurer was not properly configured and initialized");
|
||||
|
||||
return expirationPolicyConfigurer;
|
||||
return Optional.ofNullable(this.expirationPolicyConfigurer).orElseThrow(() ->
|
||||
newIllegalStateException("ExpirationPolicyConfigurer was not properly configured and initialized"));
|
||||
}
|
||||
|
||||
@Bean
|
||||
@SuppressWarnings("unused")
|
||||
public BeanPostProcessor expirationBeanPostProcessor() {
|
||||
|
||||
return new BeanPostProcessor() {
|
||||
|
||||
@Override
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
return bean;
|
||||
@@ -158,7 +160,6 @@ public class ExpirationConfiguration implements ImportAware {
|
||||
return (isRegion(bean) ? getExpirationPolicyConfigurer().configure((Region<Object, Object>) bean)
|
||||
: bean);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@@ -170,13 +171,11 @@ public class ExpirationConfiguration implements ImportAware {
|
||||
/**
|
||||
* Configures the expiration policy for the given {@link Region}.
|
||||
*
|
||||
* @param <K> {@link Class type} of the {@link Region} keys.
|
||||
* @param <V> {@link Class type} of the {@link Region} values.
|
||||
* @param region {@link Region} who's expiration policy will be configured.
|
||||
* @return the given {@link Region}.
|
||||
* @param region {@link Region} object who's expiration policy will be configured.
|
||||
* @return the given {@link Region} object.
|
||||
* @see org.apache.geode.cache.Region
|
||||
*/
|
||||
<K, V> Region<K, V> configure(Region<K, V> region);
|
||||
Object configure(Object region);
|
||||
|
||||
}
|
||||
|
||||
@@ -202,7 +201,7 @@ public class ExpirationConfiguration implements ImportAware {
|
||||
* @see #compose(Iterable)
|
||||
*/
|
||||
protected static ExpirationPolicyConfigurer compose(ExpirationPolicyConfigurer[] array) {
|
||||
return compose(Arrays.asList(ArrayUtils.nullSafeArray(array, ExpirationPolicyConfigurer.class)));
|
||||
return compose(Arrays.asList(nullSafeArray(array, ExpirationPolicyConfigurer.class)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -214,9 +213,10 @@ public class ExpirationConfiguration implements ImportAware {
|
||||
* @see #compose(ExpirationPolicyConfigurer, ExpirationPolicyConfigurer)
|
||||
*/
|
||||
protected static ExpirationPolicyConfigurer compose(Iterable<ExpirationPolicyConfigurer> iterable) {
|
||||
|
||||
ExpirationPolicyConfigurer current = null;
|
||||
|
||||
for (ExpirationPolicyConfigurer configurer : CollectionUtils.nullSafeIterable(iterable)) {
|
||||
for (ExpirationPolicyConfigurer configurer : nullSafeIterable(iterable)) {
|
||||
current = compose(current, configurer);
|
||||
}
|
||||
|
||||
@@ -255,7 +255,7 @@ public class ExpirationConfiguration implements ImportAware {
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public <K, V> Region<K, V> configure(Region<K, V> region) {
|
||||
public Object configure(Object region) {
|
||||
return this.two.configure(this.one.configure(region));
|
||||
}
|
||||
}
|
||||
@@ -276,9 +276,9 @@ public class ExpirationConfiguration implements ImportAware {
|
||||
|
||||
private final ExpirationAttributes defaultExpirationAttributes;
|
||||
|
||||
private final Set<String> regionNames = new HashSet<String>();
|
||||
private final Set<String> regionNames = new HashSet<>();
|
||||
|
||||
private final Set<ExpirationType> types = new HashSet<ExpirationType>();
|
||||
private final Set<ExpirationType> types = new HashSet<>();
|
||||
|
||||
/**
|
||||
* Factory method to construct an instance of {@link ExpirationPolicyMetaData} initialized with
|
||||
@@ -294,12 +294,13 @@ public class ExpirationConfiguration implements ImportAware {
|
||||
* @see org.springframework.core.annotation.AnnotationAttributes
|
||||
*/
|
||||
protected static ExpirationPolicyMetaData from(AnnotationAttributes expirationPolicyAttributes) {
|
||||
|
||||
Assert.isAssignable(ExpirationPolicy.class, expirationPolicyAttributes.annotationType());
|
||||
|
||||
return newExpirationPolicyMetaData((Integer) expirationPolicyAttributes.get("timeout"),
|
||||
expirationPolicyAttributes.<ExpirationActionType>getEnum("action"),
|
||||
expirationPolicyAttributes.getStringArray("regionNames"),
|
||||
(ExpirationType[]) expirationPolicyAttributes.get("types"));
|
||||
expirationPolicyAttributes.getEnum("action"),
|
||||
expirationPolicyAttributes.getStringArray("regionNames"),
|
||||
(ExpirationType[]) expirationPolicyAttributes.get("types"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -378,8 +379,8 @@ public class ExpirationConfiguration implements ImportAware {
|
||||
String[] regionNames, ExpirationType[] types) {
|
||||
|
||||
return new ExpirationPolicyMetaData(newExpirationAttributes(timeout, action),
|
||||
CollectionUtils.asSet(ArrayUtils.nullSafeArray(regionNames, String.class)),
|
||||
CollectionUtils.asSet(ArrayUtils.nullSafeArray(types, ExpirationType.class)));
|
||||
CollectionUtils.asSet(nullSafeArray(regionNames, String.class)),
|
||||
CollectionUtils.asSet(nullSafeArray(types, ExpirationType.class)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -391,7 +392,7 @@ public class ExpirationConfiguration implements ImportAware {
|
||||
* @see org.springframework.data.gemfire.ExpirationActionType
|
||||
*/
|
||||
protected static ExpirationActionType resolveAction(ExpirationActionType action) {
|
||||
return SpringUtils.defaultIfNull(action, DEFAULT_ACTION);
|
||||
return Optional.ofNullable(action).orElse(DEFAULT_ACTION);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -421,6 +422,7 @@ public class ExpirationConfiguration implements ImportAware {
|
||||
* @see #resolveAction(ExpirationActionType)
|
||||
* @see #resolveTimeout(int)
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
protected ExpirationPolicyMetaData(int timeout, ExpirationActionType action, Set<String> regionNames,
|
||||
Set<ExpirationType> types) {
|
||||
|
||||
@@ -442,7 +444,7 @@ public class ExpirationConfiguration implements ImportAware {
|
||||
protected ExpirationPolicyMetaData(ExpirationAttributes expirationAttributes, Set<String> regionNames,
|
||||
Set<ExpirationType> types) {
|
||||
|
||||
Assert.notEmpty(types, "At least one ExpirationPolicy type [TTI, TTL] must be specified");
|
||||
Assert.notEmpty(types, "At least one ExpirationPolicy type [TTI, TTL] is required");
|
||||
|
||||
this.defaultExpirationAttributes = expirationAttributes;
|
||||
this.regionNames.addAll(CollectionUtils.nullSafeSet(regionNames));
|
||||
@@ -457,8 +459,8 @@ public class ExpirationConfiguration implements ImportAware {
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see #accepts(String)
|
||||
*/
|
||||
protected boolean accepts(Region region) {
|
||||
return (region != null && accepts(region.getName()));
|
||||
protected boolean accepts(Object region) {
|
||||
return (region instanceof Region && accepts(((Region) region).getName()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -496,24 +498,27 @@ public class ExpirationConfiguration implements ImportAware {
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public <K, V> Region<K, V> configure(Region<K, V> region) {
|
||||
if (accepts(region)) {
|
||||
AttributesMutator<K, V> regionAttributesMutator = region.getAttributesMutator();
|
||||
public Object configure(Object regionObject) {
|
||||
|
||||
if (accepts(regionObject)) {
|
||||
Region<?, ?> region = (Region<?, ?>) regionObject;
|
||||
|
||||
AttributesMutator<?, ?> regionAttributesMutator = region.getAttributesMutator();
|
||||
|
||||
ExpirationAttributes defaultExpirationAttributes = defaultExpirationAttributes();
|
||||
|
||||
if (isIdleTimeout()) {
|
||||
regionAttributesMutator.setCustomEntryIdleTimeout(
|
||||
AnnotationBasedExpiration.<K, V>forIdleTimeout(defaultExpirationAttributes));
|
||||
AnnotationBasedExpiration.forIdleTimeout(defaultExpirationAttributes));
|
||||
}
|
||||
|
||||
if (isTimeToLive()) {
|
||||
regionAttributesMutator.setCustomEntryTimeToLive(
|
||||
AnnotationBasedExpiration.<K, V>forTimeToLive(defaultExpirationAttributes));
|
||||
AnnotationBasedExpiration.forTimeToLive(defaultExpirationAttributes));
|
||||
}
|
||||
}
|
||||
|
||||
return region;
|
||||
return regionObject;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,12 +17,20 @@
|
||||
|
||||
package org.springframework.data.gemfire.config.annotation;
|
||||
|
||||
import static org.springframework.data.gemfire.util.CollectionUtils.nullSafeMap;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.apache.geode.cache.lucene.LuceneIndex;
|
||||
import org.apache.geode.cache.query.Index;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
@@ -48,23 +56,29 @@ import org.springframework.util.StringUtils;
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.lang.annotation.Annotation
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.apache.geode.cache.lucene.LuceneIndex
|
||||
* @see org.apache.geode.cache.query.Index
|
||||
* @see org.springframework.beans.factory.support.BeanDefinitionBuilder
|
||||
* @see org.springframework.beans.factory.support.BeanDefinitionRegistry
|
||||
* @see org.springframework.core.type.AnnotationMetadata
|
||||
* @see org.springframework.data.annotation.Id
|
||||
* @see org.springframework.data.gemfire.IndexFactoryBean
|
||||
* @see org.springframework.data.gemfire.IndexType
|
||||
* @see org.springframework.data.gemfire.search.lucene.LuceneIndexFactoryBean
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableIndexing
|
||||
* @see org.springframework.data.gemfire.config.annotation.EntityDefinedRegionsConfiguration
|
||||
* @see org.springframework.data.gemfire.mapping.GemfirePersistentEntity
|
||||
* @see org.springframework.data.gemfire.mapping.GemfirePersistentProperty
|
||||
* @see org.springframework.data.gemfire.mapping.annotation.Indexed
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.apache.geode.cache.lucene.LuceneIndex
|
||||
* @see org.apache.geode.cache.query.Index
|
||||
* @see org.springframework.data.gemfire.mapping.annotation.LuceneIndexed
|
||||
* @see org.springframework.data.gemfire.search.lucene.LuceneIndexFactoryBean
|
||||
* @since 1.9.0
|
||||
*/
|
||||
public class IndexConfiguration extends EntityDefinedRegionsConfiguration {
|
||||
|
||||
@Autowired(required = false)
|
||||
private List<IndexConfigurer> indexConfigurers = Collections.emptyList();
|
||||
|
||||
/**
|
||||
* Returns the {@link Annotation} {@link Class type} that configures and creates {@link Region} Indexes
|
||||
* from application persistent entity properties.
|
||||
@@ -117,6 +131,7 @@ public class IndexConfiguration extends EntityDefinedRegionsConfiguration {
|
||||
super.postProcess(importingClassMetadata, registry, persistentEntity);
|
||||
|
||||
if (isAnnotationPresent(importingClassMetadata, getEnableIndexingAnnotationTypeName())) {
|
||||
|
||||
AnnotationAttributes enableIndexingAttributes =
|
||||
getAnnotationAttributes(importingClassMetadata, getEnableIndexingAnnotationTypeName());
|
||||
|
||||
@@ -162,6 +177,7 @@ public class IndexConfiguration extends EntityDefinedRegionsConfiguration {
|
||||
IndexType indexType, Annotation indexAnnotation, BeanDefinitionRegistry registry) {
|
||||
|
||||
Optional.ofNullable(indexAnnotation).ifPresent(localIndexAnnotation -> {
|
||||
|
||||
AnnotationAttributes indexedAttributes = getAnnotationAttributes(localIndexAnnotation);
|
||||
|
||||
BeanDefinitionBuilder indexFactoryBeanBuilder =
|
||||
@@ -179,6 +195,8 @@ public class IndexConfiguration extends EntityDefinedRegionsConfiguration {
|
||||
indexFactoryBeanBuilder.addPropertyValue("from",
|
||||
resolveFrom(persistentEntity, persistentProperty, indexedAttributes));
|
||||
|
||||
indexFactoryBeanBuilder.addPropertyValue("indexConfigurers", resolveIndexConfigurers());
|
||||
|
||||
indexFactoryBeanBuilder.addPropertyValue("name", indexName);
|
||||
|
||||
indexFactoryBeanBuilder.addPropertyValue("override",
|
||||
@@ -215,6 +233,7 @@ public class IndexConfiguration extends EntityDefinedRegionsConfiguration {
|
||||
Annotation luceneIndexAnnotation, BeanDefinitionRegistry registry) {
|
||||
|
||||
Optional.ofNullable(luceneIndexAnnotation).ifPresent(localLuceneIndexAnnotation -> {
|
||||
|
||||
AnnotationAttributes luceneIndexAttributes =
|
||||
AnnotationAttributes.fromMap(AnnotationUtils.getAnnotationAttributes(localLuceneIndexAnnotation));
|
||||
|
||||
@@ -230,6 +249,8 @@ public class IndexConfiguration extends EntityDefinedRegionsConfiguration {
|
||||
|
||||
luceneIndexFactoryBeanBuilder.addPropertyValue("fields", persistentProperty.getName());
|
||||
|
||||
luceneIndexFactoryBeanBuilder.addPropertyValue("indexConfigurers", resolveIndexConfigurers());
|
||||
|
||||
luceneIndexFactoryBeanBuilder.addPropertyValue("indexName", indexName);
|
||||
|
||||
luceneIndexFactoryBeanBuilder.addPropertyValue("regionPath", persistentEntity.getRegionName());
|
||||
@@ -238,6 +259,24 @@ public class IndexConfiguration extends EntityDefinedRegionsConfiguration {
|
||||
});
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private List<IndexConfigurer> resolveIndexConfigurers() {
|
||||
|
||||
return Optional.ofNullable(this.indexConfigurers)
|
||||
.filter(indexConfigurers -> !indexConfigurers.isEmpty())
|
||||
.orElseGet(() ->
|
||||
Optional.of(getBeanFactory())
|
||||
.filter(beanFactory -> beanFactory instanceof ListableBeanFactory)
|
||||
.map(beanFactory -> {
|
||||
Map<String, IndexConfigurer> beansOfType = ((ListableBeanFactory) beanFactory)
|
||||
.getBeansOfType(IndexConfigurer.class, true, true);
|
||||
|
||||
return nullSafeMap(beansOfType).values().stream().collect(Collectors.toList());
|
||||
})
|
||||
.orElseGet(Collections::emptyList)
|
||||
);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private boolean resolveDefine(AnnotationAttributes enableIndexingAttributes) {
|
||||
return (enableIndexingAttributes.containsKey("define")
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.gemfire.config.annotation;
|
||||
|
||||
import org.apache.geode.cache.lucene.LuceneIndex;
|
||||
import org.apache.geode.cache.query.Index;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.gemfire.IndexFactoryBean;
|
||||
import org.springframework.data.gemfire.search.lucene.LuceneIndexFactoryBean;
|
||||
|
||||
/**
|
||||
* The {@link IndexConfigurer} interface defines a contract for implementations to customize the configuration
|
||||
* of Entity-defined {@link Index Indexes} when a user annotates her Spring application {@link Configuration}
|
||||
* class with {@link EnableIndexing}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.lucene.LuceneIndex
|
||||
* @see org.apache.geode.cache.query.Index
|
||||
* @see org.springframework.data.gemfire.IndexFactoryBean
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableIndexing
|
||||
* @see org.springframework.data.gemfire.config.annotation.IndexConfiguration
|
||||
* @see org.springframework.data.gemfire.search.lucene.LuceneIndexFactoryBean
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public interface IndexConfigurer {
|
||||
|
||||
/**
|
||||
* Configuration callback method providing a reference to a {@link IndexFactoryBean} used to construct, configure
|
||||
* and initialize an instance of a peer {@link Index}.
|
||||
*
|
||||
* @param beanName name of {@link Index} bean declared in the Spring application context.
|
||||
* @param bean reference to the {@link IndexFactoryBean}.
|
||||
* @see org.springframework.data.gemfire.IndexFactoryBean
|
||||
*/
|
||||
default void configure(String beanName, IndexFactoryBean bean) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration callback method providing a reference to a {@link LuceneIndexFactoryBean} used to construct,
|
||||
* configure and initialize an instance of a peer {@link LuceneIndex}.
|
||||
*
|
||||
* @param beanName name of {@link LuceneIndex} bean declared in the Spring application context.
|
||||
* @param bean reference to the {@link LuceneIndexFactoryBean}.
|
||||
* @see org.springframework.data.gemfire.search.lucene.LuceneIndexFactoryBean
|
||||
*/
|
||||
default void configure(String beanName, LuceneIndexFactoryBean bean) {
|
||||
}
|
||||
}
|
||||
@@ -50,7 +50,7 @@ public class LocatorConfiguration extends EmbeddedServiceConfigurationSupport {
|
||||
String host = resolveHost((String) annotationAttributes.get("host"));
|
||||
int port = resolvePort((Integer) annotationAttributes.get("port"), DEFAULT_LOCATOR_PORT);
|
||||
|
||||
return new PropertiesBuilder()
|
||||
return PropertiesBuilder.create()
|
||||
.setProperty(START_LOCATOR_GEMFIRE_SYSTEM_PROPERTY_NAME, String.format("%s[%d]", host, port))
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ public class ManagerConfiguration extends EmbeddedServiceConfigurationSupport {
|
||||
|
||||
@Override
|
||||
protected Properties toGemFireProperties(Map<String, Object> annotationAttributes) {
|
||||
PropertiesBuilder gemfireProperties = new PropertiesBuilder();
|
||||
PropertiesBuilder gemfireProperties = PropertiesBuilder.create();
|
||||
|
||||
gemfireProperties.setProperty("jmx-manager", Boolean.TRUE.toString());
|
||||
gemfireProperties.setProperty("jmx-manager-access-file", annotationAttributes.get("accessFile"));
|
||||
|
||||
@@ -44,8 +44,9 @@ public class MemcachedServerConfiguration extends EmbeddedServiceConfigurationSu
|
||||
|
||||
@Override
|
||||
protected Properties toGemFireProperties(Map<String, Object> annotationAttributes) {
|
||||
return new PropertiesBuilder()
|
||||
.setProperty("memcached-port", resolvePort((Integer) annotationAttributes.get("port"), DEFAULT_MEMCACHED_SERVER_PORT))
|
||||
return PropertiesBuilder.create()
|
||||
.setProperty("memcached-port", resolvePort((Integer) annotationAttributes.get("port"),
|
||||
DEFAULT_MEMCACHED_SERVER_PORT))
|
||||
.setProperty("memcached-protocol", annotationAttributes.get("protocol"))
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -17,22 +17,31 @@
|
||||
|
||||
package org.springframework.data.gemfire.config.annotation;
|
||||
|
||||
import java.util.Map;
|
||||
import static org.springframework.data.gemfire.util.CollectionUtils.nullSafeMap;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.geode.cache.Cache;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.data.gemfire.CacheFactoryBean;
|
||||
|
||||
/**
|
||||
* Spring {@link Configuration} class used to configure, construct and initialize
|
||||
* a GemFire peer {@link org.apache.geode.cache.Cache} instance in a Spring application context.
|
||||
* Spring {@link Configuration} class used to construct, configure and initialize a peer {@link Cache} instance
|
||||
* in a Spring application context.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see org.springframework.context.annotation.Bean
|
||||
* @see org.springframework.context.annotation.Configuration
|
||||
* @see org.springframework.data.gemfire.config.annotation.AbstractCacheConfiguration
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @since 1.9.0
|
||||
*/
|
||||
@Configuration
|
||||
@@ -52,14 +61,28 @@ public class PeerCacheConfiguration extends AbstractCacheConfiguration {
|
||||
private Integer messageSyncInterval;
|
||||
private Integer searchTimeout;
|
||||
|
||||
@Autowired(required = false)
|
||||
private List<PeerCacheConfigurer> peerCacheConfigurers = Collections.emptyList();
|
||||
|
||||
/**
|
||||
* Bean declaration for a single, peer {@link Cache} instance.
|
||||
*
|
||||
* @return a new instance of a peer {@link Cache}.
|
||||
* @see org.springframework.data.gemfire.CacheFactoryBean
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see #constructCacheFactoryBean()
|
||||
*/
|
||||
@Bean
|
||||
public CacheFactoryBean gemfireCache() {
|
||||
|
||||
CacheFactoryBean gemfireCache = constructCacheFactoryBean();
|
||||
|
||||
gemfireCache.setEnableAutoReconnect(enableAutoReconnect());
|
||||
gemfireCache.setLockLease(lockLease());
|
||||
gemfireCache.setLockTimeout(lockTimeout());
|
||||
gemfireCache.setMessageSyncInterval(messageSyncInterval());
|
||||
gemfireCache.setPeerCacheConfigurers(resolvePeerCacheConfigurers());
|
||||
gemfireCache.setSearchTimeout(searchTimeout());
|
||||
gemfireCache.setUseBeanFactoryLocator(useBeanFactoryLocator());
|
||||
gemfireCache.setUseClusterConfiguration(useClusterConfiguration());
|
||||
@@ -67,8 +90,30 @@ public class PeerCacheConfiguration extends AbstractCacheConfiguration {
|
||||
return gemfireCache;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private List<PeerCacheConfigurer> resolvePeerCacheConfigurers() {
|
||||
|
||||
return Optional.ofNullable(this.peerCacheConfigurers)
|
||||
.filter(peerCacheConfigurers -> !peerCacheConfigurers.isEmpty())
|
||||
.orElseGet(() ->
|
||||
Optional.of(this.beanFactory())
|
||||
.filter(beanFactory -> beanFactory instanceof ListableBeanFactory)
|
||||
.map(beanFactory -> {
|
||||
Map<String, PeerCacheConfigurer> beansOfType = ((ListableBeanFactory) beanFactory)
|
||||
.getBeansOfType(PeerCacheConfigurer.class, true, true);
|
||||
|
||||
return nullSafeMap(beansOfType).values().stream().collect(Collectors.toList());
|
||||
})
|
||||
.orElseGet(Collections::emptyList)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* Constructs a new instance of {@link CacheFactoryBean} used to create a peer {@link Cache}.
|
||||
*
|
||||
* @param <T> {@link Class} sub-type of {@link CacheFactoryBean}.
|
||||
* @return a new instance of {@link CacheFactoryBean}.
|
||||
* @see org.springframework.data.gemfire.CacheFactoryBean
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -77,18 +122,20 @@ public class PeerCacheConfiguration extends AbstractCacheConfiguration {
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures GemFire peer {@link org.apache.geode.cache.Cache} specific settings.
|
||||
* Configures peer {@link Cache} specific settings.
|
||||
*
|
||||
* @param importMetadata {@link AnnotationMetadata} containing peer cache meta-data used to configure
|
||||
* the GemFire peer {@link org.apache.geode.cache.Cache}.
|
||||
* @param importMetadata {@link AnnotationMetadata} containing peer cache meta-data used to
|
||||
* configure the peer {@link Cache}.
|
||||
* @see org.springframework.core.type.AnnotationMetadata
|
||||
* @see #isCacheServerOrPeerCacheApplication(AnnotationMetadata)
|
||||
*/
|
||||
@Override
|
||||
protected void configureCache(AnnotationMetadata importMetadata) {
|
||||
|
||||
super.configureCache(importMetadata);
|
||||
|
||||
if (isCacheServerOrPeerCacheApplication(importMetadata)) {
|
||||
|
||||
Map<String, Object> peerCacheApplicationAttributes =
|
||||
importMetadata.getAnnotationAttributes(getAnnotationTypeName());
|
||||
|
||||
@@ -99,11 +146,9 @@ public class PeerCacheConfiguration extends AbstractCacheConfiguration {
|
||||
setSearchTimeout((Integer) peerCacheApplicationAttributes.get("searchTimeout"));
|
||||
setUseClusterConfiguration(Boolean.TRUE.equals(peerCacheApplicationAttributes.get("useClusterConfiguration")));
|
||||
|
||||
String locators = (String) peerCacheApplicationAttributes.get("locators");
|
||||
|
||||
if (hasValue(locators)) {
|
||||
setLocators(locators);
|
||||
}
|
||||
Optional.ofNullable((String) peerCacheApplicationAttributes.get("locators"))
|
||||
.filter(PeerCacheConfiguration::hasValue)
|
||||
.ifPresent(this::setLocators);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.springframework.data.gemfire.config.annotation;
|
||||
|
||||
import org.apache.geode.cache.Cache;
|
||||
import org.springframework.data.gemfire.CacheFactoryBean;
|
||||
|
||||
/**
|
||||
* The {@link PeerCacheConfigurer} interface defines a contract for implementations to customize the configuration
|
||||
* of a {@link CacheFactoryBean} used to construct, configure and initialize an instance of a peer {@link Cache}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see org.springframework.data.gemfire.CacheFactoryBean
|
||||
* @see org.springframework.data.gemfire.config.annotation.PeerCacheApplication
|
||||
* @since 1.9.0
|
||||
*/
|
||||
public interface PeerCacheConfigurer {
|
||||
|
||||
/**
|
||||
* Configuration callback method providing a reference to a {@link CacheFactoryBean} used to construct,
|
||||
* configure and initialize an instance of a peer {@link Cache}.
|
||||
*
|
||||
* @param beanName name of peer {@link Cache} bean declared in the Spring application context.
|
||||
* @param bean reference to the {@link CacheFactoryBean}.
|
||||
* @see org.springframework.data.gemfire.CacheFactoryBean
|
||||
*/
|
||||
void configure(String beanName, CacheFactoryBean bean);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.gemfire.config.annotation;
|
||||
|
||||
import org.apache.geode.cache.client.Pool;
|
||||
import org.springframework.data.gemfire.client.PoolFactoryBean;
|
||||
|
||||
/**
|
||||
* The {@link PoolConfigurer} interface defines a contract for implementations to customize the configuration
|
||||
* of a {@link PoolFactoryBean} used to construct, configure and initialize a {@link Pool}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.client.Pool
|
||||
* @see org.springframework.data.gemfire.client.PoolFactoryBean
|
||||
* @see org.springframework.data.gemfire.config.annotation.AddPoolConfiguration
|
||||
* @see org.springframework.data.gemfire.config.annotation.AddPoolsConfiguration
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnablePool
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnablePools
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public interface PoolConfigurer {
|
||||
|
||||
/**
|
||||
* Configuration callback method providing a reference to a {@link PoolFactoryBean} used to construct,
|
||||
* configure and initialize an instance of a {@link Pool}.
|
||||
*
|
||||
* @param beanName name of the {@link Pool} bean declared in the Spring application context.
|
||||
* @param bean reference to the {@link PoolFactoryBean}.
|
||||
* @see org.springframework.data.gemfire.client.PoolFactoryBean
|
||||
*/
|
||||
void configure(String beanName, PoolFactoryBean bean);
|
||||
|
||||
}
|
||||
@@ -44,7 +44,7 @@ public class RedisServerConfiguration extends EmbeddedServiceConfigurationSuppor
|
||||
|
||||
@Override
|
||||
protected Properties toGemFireProperties(Map<String, Object> annotationAttributes) {
|
||||
return new PropertiesBuilder()
|
||||
return PropertiesBuilder.create()
|
||||
.setProperty("redis-bind-address", annotationAttributes.get("bindAddress"))
|
||||
.setProperty("redis-port", resolvePort((Integer)annotationAttributes.get("port"), DEFAULT_REDIS_PORT))
|
||||
.build();
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.gemfire.config.annotation;
|
||||
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.gemfire.RegionFactoryBean;
|
||||
import org.springframework.data.gemfire.client.ClientRegionFactoryBean;
|
||||
|
||||
/**
|
||||
* The {@link RegionConfigurer} interface defines a contract for implementations to customize the configuration
|
||||
* of Entity-defined {@link Region Regions} when a user annotates her Spring application {@link Configuration}
|
||||
* class with {@link EnableEntityDefinedRegions}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.springframework.data.gemfire.RegionFactoryBean
|
||||
* @see org.springframework.data.gemfire.client.ClientRegionFactoryBean
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableEntityDefinedRegions
|
||||
* @see org.springframework.data.gemfire.config.annotation.support.GemFireCacheTypeAwareRegionFactoryBean
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public interface RegionConfigurer {
|
||||
|
||||
/**
|
||||
* Configuration callback method providing a reference to a {@link RegionFactoryBean} used to construct, configure
|
||||
* and initialize an instance of a peer {@link Region}.
|
||||
*
|
||||
* @param beanName name of {@link Region} bean declared in the Spring application context.
|
||||
* @param bean reference to the {@link RegionFactoryBean}.
|
||||
* @see org.springframework.data.gemfire.RegionFactoryBean
|
||||
*/
|
||||
default void configure(String beanName, RegionFactoryBean<?, ?> bean) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration callback method providing a reference to a {@link ClientRegionFactoryBean} used to construct,
|
||||
* configure and initialize an instance of a client {@link Region}.
|
||||
*
|
||||
* @param beanName name of {@link Region} bean declared in the Spring application context.
|
||||
* @param bean reference to the {@link ClientRegionFactoryBean}.
|
||||
* @see org.springframework.data.gemfire.client.ClientRegionFactoryBean
|
||||
*/
|
||||
default void configure(String beanName, ClientRegionFactoryBean<?, ?> bean) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,249 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.springframework.data.gemfire.config.annotation.support;
|
||||
|
||||
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalStateException;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.context.expression.BeanFactoryAccessor;
|
||||
import org.springframework.context.expression.EnvironmentAccessor;
|
||||
import org.springframework.context.expression.MapAccessor;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.expression.spel.support.StandardTypeConverter;
|
||||
import org.springframework.expression.spel.support.StandardTypeLocator;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* The {@link AbstractAnnotationConfigSupport} class is an abstract base class encapsulating functionality
|
||||
* common to all Annotations and configuration classes used to configure Pivotal GemFire/Apache Geode objects
|
||||
* with Spring Data GemFire or Spring Data Geode.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.lang.ClassLoader
|
||||
* @see org.springframework.beans.factory.BeanClassLoaderAware
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see org.springframework.beans.factory.BeanFactoryAware
|
||||
* @see org.springframework.beans.factory.InitializingBean
|
||||
* @see org.springframework.beans.factory.config.ConfigurableBeanFactory
|
||||
* @see org.springframework.beans.factory.support.AbstractBeanDefinition
|
||||
* @see org.springframework.beans.factory.support.BeanDefinitionRegistry
|
||||
* @see org.springframework.expression.EvaluationContext
|
||||
* @since 1.9.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public abstract class AbstractAnnotationConfigSupport
|
||||
implements BeanClassLoaderAware, BeanFactoryAware, InitializingBean {
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
private ClassLoader beanClassLoader;
|
||||
|
||||
private EvaluationContext evaluationContext;
|
||||
|
||||
/**
|
||||
* Determines whether the given {@link Object} has value. The {@link Object} is valuable
|
||||
* if it is not {@literal null}.
|
||||
*
|
||||
* @param value {@link Object} to evaluate.
|
||||
* @return a boolean value indicating whether the given {@link Object} has value.
|
||||
*/
|
||||
protected static boolean hasValue(Object value) {
|
||||
return Optional.ofNullable(value).isPresent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the given {@link Number} has value. The {@link Number} is valuable
|
||||
* if it is not {@literal null} and is not equal to 0.0d.
|
||||
*
|
||||
* @param value {@link Number} to evaluate.
|
||||
* @return a boolean value indicating whether the given {@link Number} has value.
|
||||
*/
|
||||
protected static boolean hasValue(Number value) {
|
||||
return Optional.ofNullable(value).filter(it -> it.doubleValue() != 0.0d).isPresent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the given {@link String} has value. The {@link String} is valuable
|
||||
* if it is not {@literal null} or empty.
|
||||
*
|
||||
* @param value {@link String} to evaluate.
|
||||
* @return a boolean value indicating whether the given {@link String} is valuable.
|
||||
*/
|
||||
protected static boolean hasValue(String value) {
|
||||
return StringUtils.hasText(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
this.evaluationContext = newEvaluationContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs, configures and initializes a new instance of an {@link EvaluationContext}.
|
||||
*
|
||||
* @return a new {@link EvaluationContext}.
|
||||
* @see org.springframework.expression.EvaluationContext
|
||||
* @see #beanFactory()
|
||||
*/
|
||||
protected EvaluationContext newEvaluationContext() {
|
||||
StandardEvaluationContext evaluationContext = new StandardEvaluationContext();
|
||||
|
||||
evaluationContext.addPropertyAccessor(new BeanFactoryAccessor());
|
||||
evaluationContext.addPropertyAccessor(new EnvironmentAccessor());
|
||||
evaluationContext.addPropertyAccessor(new MapAccessor());
|
||||
evaluationContext.setTypeLocator(new StandardTypeLocator(beanClassLoader()));
|
||||
|
||||
Optional.ofNullable(beanFactory())
|
||||
.filter(beanFactory -> beanFactory instanceof ConfigurableBeanFactory)
|
||||
.map(beanFactory -> ((ConfigurableBeanFactory) beanFactory).getConversionService())
|
||||
.ifPresent(conversionService ->
|
||||
evaluationContext.setTypeConverter(new StandardTypeConverter(conversionService)));
|
||||
|
||||
return evaluationContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cache application {@link java.lang.annotation.Annotation} type pertaining to this configuration.
|
||||
*
|
||||
* @return the cache application {@link java.lang.annotation.Annotation} type used by this application.
|
||||
*/
|
||||
protected abstract Class getAnnotationType();
|
||||
|
||||
/**
|
||||
* Returns the fully-qualified {@link Class#getName() class name} of the cache application
|
||||
* {@link java.lang.annotation.Annotation} type.
|
||||
*
|
||||
* @return the fully-qualified {@link Class#getName() class name} of the cache application
|
||||
* {@link java.lang.annotation.Annotation} type.
|
||||
* @see java.lang.Class#getName()
|
||||
* @see #getAnnotationType()
|
||||
*/
|
||||
protected String getAnnotationTypeName() {
|
||||
return getAnnotationType().getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the simple {@link Class#getName() class name} of the cache application
|
||||
* {@link java.lang.annotation.Annotation} type.
|
||||
*
|
||||
* @return the simple {@link Class#getName() class name} of the cache application
|
||||
* {@link java.lang.annotation.Annotation} type.
|
||||
* @see java.lang.Class#getSimpleName()
|
||||
* @see #getAnnotationType()
|
||||
*/
|
||||
protected String getAnnotationTypeSimpleName() {
|
||||
return getAnnotationType().getSimpleName();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setBeanClassLoader(ClassLoader beanClassLoader) {
|
||||
this.beanClassLoader = beanClassLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the {@link ClassLoader} use by the Spring {@link BeanFactory} to load classes
|
||||
* for bean definitions.
|
||||
*
|
||||
* @return the {@link ClassLoader} used by the Spring {@link BeanFactory} to load classes for bean definitions.
|
||||
* @see #setBeanClassLoader(ClassLoader)
|
||||
*/
|
||||
protected ClassLoader beanClassLoader() {
|
||||
return this.beanClassLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the Spring {@link BeanFactory} in the current application context.
|
||||
*
|
||||
* @return a reference to the Spring {@link BeanFactory}.
|
||||
* @throws IllegalStateException if the Spring {@link BeanFactory} was not properly configured.
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
*/
|
||||
protected BeanFactory beanFactory() {
|
||||
return Optional.ofNullable(this.beanFactory)
|
||||
.orElseThrow(() -> newIllegalStateException("BeanFactory is required"));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected EvaluationContext evaluationContext() {
|
||||
return this.evaluationContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the {@link AbstractBeanDefinition} with the {@link BeanDefinitionRegistry} using a generated bean name.
|
||||
*
|
||||
* @param beanDefinition {@link AbstractBeanDefinition} to register.
|
||||
* @return the given {@link AbstractBeanDefinition}.
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see org.springframework.beans.factory.support.AbstractBeanDefinition
|
||||
* @see org.springframework.beans.factory.support.BeanDefinitionRegistry
|
||||
* @see org.springframework.beans.factory.support.BeanDefinitionReaderUtils#registerWithGeneratedName(AbstractBeanDefinition, BeanDefinitionRegistry)
|
||||
* @see #beanFactory()
|
||||
*/
|
||||
protected AbstractBeanDefinition register(AbstractBeanDefinition beanDefinition) {
|
||||
|
||||
BeanFactory beanFactory = beanFactory();
|
||||
|
||||
return (beanFactory instanceof BeanDefinitionRegistry
|
||||
? register(beanDefinition, (BeanDefinitionRegistry) beanFactory)
|
||||
: beanDefinition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the {@link AbstractBeanDefinition} with the {@link BeanDefinitionRegistry} using a generated bean name.
|
||||
*
|
||||
* @param beanDefinition {@link AbstractBeanDefinition} to register.
|
||||
* @param registry {@link BeanDefinitionRegistry} used to register the {@link AbstractBeanDefinition}.
|
||||
* @return the given {@link AbstractBeanDefinition}.
|
||||
* @see org.springframework.beans.factory.support.AbstractBeanDefinition
|
||||
* @see org.springframework.beans.factory.support.BeanDefinitionRegistry
|
||||
* @see org.springframework.beans.factory.support.BeanDefinitionReaderUtils#registerWithGeneratedName(AbstractBeanDefinition, BeanDefinitionRegistry)
|
||||
*/
|
||||
protected AbstractBeanDefinition register(AbstractBeanDefinition beanDefinition, BeanDefinitionRegistry registry) {
|
||||
|
||||
Optional.ofNullable(registry).ifPresent(it ->
|
||||
BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, it)
|
||||
);
|
||||
|
||||
return beanDefinition;
|
||||
}
|
||||
}
|
||||
@@ -17,12 +17,14 @@
|
||||
|
||||
package org.springframework.data.gemfire.config.annotation.support;
|
||||
|
||||
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalStateException;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
@@ -39,18 +41,25 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* The {@link EmbeddedServiceConfigurationSupport} class is an abstract base class supporting the configuration
|
||||
* of Pivotal GemFire and Apache Geode embedded services.
|
||||
* The {@link EmbeddedServiceConfigurationSupport} class is an abstract base class supporting
|
||||
* the configuration of Pivotal GemFire and Apache Geode embedded services.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.util.Properties
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see org.springframework.beans.factory.BeanFactoryAware
|
||||
* @see org.springframework.beans.factory.config.AutowireCapableBeanFactory
|
||||
* @see org.springframework.beans.factory.config.BeanDefinitionHolder
|
||||
* @see org.springframework.beans.factory.support.BeanDefinitionBuilder
|
||||
* @see org.springframework.beans.factory.support.BeanDefinitionRegistry
|
||||
* @see org.springframework.context.annotation.ImportBeanDefinitionRegistrar
|
||||
* @see org.springframework.core.type.AnnotationMetadata
|
||||
* @see org.springframework.data.gemfire.config.annotation.AbstractCacheConfiguration
|
||||
* @see org.springframework.data.gemfire.config.annotation.support.AbstractAnnotationConfigSupport
|
||||
* @since 1.9.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public abstract class EmbeddedServiceConfigurationSupport implements ImportBeanDefinitionRegistrar, BeanFactoryAware {
|
||||
public abstract class EmbeddedServiceConfigurationSupport extends AbstractAnnotationConfigSupport
|
||||
implements ImportBeanDefinitionRegistrar {
|
||||
|
||||
public static final Integer DEFAULT_PORT = 0;
|
||||
public static final String DEFAULT_HOST = "localhost";
|
||||
@@ -59,8 +68,6 @@ public abstract class EmbeddedServiceConfigurationSupport implements ImportBeanD
|
||||
@SuppressWarnings("all")
|
||||
private AbstractCacheConfiguration cacheConfiguration;
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
/**
|
||||
* Returns a reference to an instance of the {@link AbstractCacheConfiguration} class used to configure
|
||||
* a GemFire (Singleton, client or peer) cache instance along with it's associated, embedded services.
|
||||
@@ -72,59 +79,8 @@ public abstract class EmbeddedServiceConfigurationSupport implements ImportBeanD
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T extends AbstractCacheConfiguration> T cacheConfiguration() {
|
||||
Assert.state(cacheConfiguration != null, "AbstractCacheConfiguration was not properly initialized");
|
||||
return (T) this.cacheConfiguration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the configured GemFire cache application annotation type
|
||||
* (e.g. {@link org.springframework.data.gemfire.config.annotation.ClientCacheApplication}
|
||||
* or {@link org.springframework.data.gemfire.config.annotation.PeerCacheApplication}.
|
||||
*
|
||||
* @return an {@link Class annotation} defining the GemFire cache application type.
|
||||
*/
|
||||
protected abstract Class getAnnotationType();
|
||||
|
||||
/**
|
||||
* Returns the fully-qualified class name of the GemFire cache application annotation type.
|
||||
*
|
||||
* @return a fully-qualified class name of the GemFire cache application annotation type.
|
||||
* @see java.lang.Class#getName()
|
||||
* @see #getAnnotationType()
|
||||
*/
|
||||
protected String getAnnotationTypeName() {
|
||||
return getAnnotationType().getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the simple class name of the GemFire cache application annotation type.
|
||||
*
|
||||
* @return the simple class name of the GemFire cache application annotation type.
|
||||
* @see java.lang.Class#getSimpleName()
|
||||
* @see #getAnnotationType()
|
||||
*/
|
||||
protected String getAnnotationTypeSimpleName() {
|
||||
return getAnnotationType().getSimpleName();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the Spring {@link BeanFactory}.
|
||||
*
|
||||
* @return a reference to the Spring {@link BeanFactory}.
|
||||
* @throws IllegalStateException if the Spring {@link BeanFactory} was not properly initialized.
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
*/
|
||||
protected BeanFactory getBeanFactory() {
|
||||
Assert.state(this.beanFactory != null, "BeanFactory was not properly initialized");
|
||||
return this.beanFactory;
|
||||
return Optional.ofNullable((T) this.cacheConfiguration)
|
||||
.orElseThrow(() -> newIllegalStateException("AbstractCacheConfiguration is required"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -132,7 +88,7 @@ public abstract class EmbeddedServiceConfigurationSupport implements ImportBeanD
|
||||
*/
|
||||
@Override
|
||||
public final void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
|
||||
BeanDefinitionRegistry registry) {
|
||||
BeanDefinitionRegistry registry) {
|
||||
|
||||
if (isAnnotationPresent(importingClassMetadata)) {
|
||||
Map<String, Object> annotationAttributes = getAnnotationAttributes(importingClassMetadata);
|
||||
@@ -144,12 +100,12 @@ public abstract class EmbeddedServiceConfigurationSupport implements ImportBeanD
|
||||
/* (non-Javadoc) */
|
||||
@SuppressWarnings("unused")
|
||||
protected void registerBeanDefinitions(AnnotationMetadata importingClassMetaData,
|
||||
Map<String, Object> annotationAttributes, BeanDefinitionRegistry registry) {
|
||||
Map<String, Object> annotationAttributes, BeanDefinitionRegistry registry) {
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected void setGemFireProperties(AnnotationMetadata importingClassMetadata,
|
||||
Map<String, Object> annotationAttributes, BeanDefinitionRegistry registry) {
|
||||
Map<String, Object> annotationAttributes, BeanDefinitionRegistry registry) {
|
||||
|
||||
Properties gemfireProperties = toGemFireProperties(annotationAttributes);
|
||||
|
||||
@@ -183,10 +139,10 @@ public abstract class EmbeddedServiceConfigurationSupport implements ImportBeanD
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected void registerGemFirePropertiesBeanPostProcessor(BeanDefinitionRegistry registry,
|
||||
Properties customGemFireProperties) {
|
||||
Properties customGemFireProperties) {
|
||||
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
GemFirePropertiesBeanPostProcessor.class);
|
||||
BeanDefinitionBuilder builder =
|
||||
BeanDefinitionBuilder.genericBeanDefinition(GemFirePropertiesBeanPostProcessor.class);
|
||||
|
||||
builder.addConstructorArgValue(customGemFireProperties);
|
||||
|
||||
@@ -200,7 +156,7 @@ public abstract class EmbeddedServiceConfigurationSupport implements ImportBeanD
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected String generateBeanName() {
|
||||
return generateBeanName(getAnnotationTypeSimpleName());
|
||||
return generateBeanName(getAnnotationType());
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@@ -228,11 +184,12 @@ public abstract class EmbeddedServiceConfigurationSupport implements ImportBeanD
|
||||
* @return a Spring managed bean instance for the given, required {@link Class} type, or {@literal null}
|
||||
* if no bean instance of the given, required {@link Class} type could be found.
|
||||
* @throws BeansException if the Spring manage bean of the required {@link Class} type could not be resolved.
|
||||
* @see #getBeanFactory()
|
||||
* @see #beanFactory()
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T> T resolveBean(Class<T> beanType) {
|
||||
BeanFactory beanFactory = getBeanFactory();
|
||||
|
||||
BeanFactory beanFactory = beanFactory();
|
||||
|
||||
if (beanFactory instanceof AutowireCapableBeanFactory) {
|
||||
AutowireCapableBeanFactory autowiringBeanFactory = (AutowireCapableBeanFactory) beanFactory;
|
||||
@@ -252,7 +209,7 @@ public abstract class EmbeddedServiceConfigurationSupport implements ImportBeanD
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected String resolveHost(String hostname, String defaultHostname) {
|
||||
return (StringUtils.hasText(hostname) ? hostname : defaultHostname);
|
||||
return Optional.ofNullable(hostname).filter(StringUtils::hasText).orElse(defaultHostname);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@@ -262,12 +219,12 @@ public abstract class EmbeddedServiceConfigurationSupport implements ImportBeanD
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected Integer resolvePort(Integer port, Integer defaultPort) {
|
||||
return (port != null ? port : defaultPort);
|
||||
return Optional.ofNullable(port).orElse(defaultPort);
|
||||
}
|
||||
|
||||
/**
|
||||
* Spring {@link BeanPostProcessor} used to process GemFire System properties defined as a Spring bean
|
||||
* in the Spring application context before initialization.
|
||||
* Spring {@link BeanPostProcessor} used to process before initialization Pivotal GemFire or Apache Geode
|
||||
* {@link Properties} defined as a bean in the Spring application context.
|
||||
*
|
||||
* @see org.springframework.beans.factory.config.BeanPostProcessor
|
||||
*/
|
||||
@@ -278,15 +235,15 @@ public abstract class EmbeddedServiceConfigurationSupport implements ImportBeanD
|
||||
private final Properties gemfireProperties;
|
||||
|
||||
/**
|
||||
* Construct an instance of the {@link GemFirePropertiesBeanPostProcessor} initialized with
|
||||
* the given GemFire {@link Properties}.
|
||||
* Constructs a new instance of the {@link GemFirePropertiesBeanPostProcessor} initialized with
|
||||
* the given GemFire/Geode {@link Properties}.
|
||||
*
|
||||
* @param gemfireProperties {@link Properties} used to configure GemFire.
|
||||
* @throws IllegalArgumentException if the {@link Properties} are null or empty.
|
||||
* @param gemfireProperties {@link Properties} used to configure Pivotal GemFire or Apache Geode.
|
||||
* @throws IllegalArgumentException if {@link Properties} are {@literal null} or empty.
|
||||
* @see java.util.Properties
|
||||
*/
|
||||
protected GemFirePropertiesBeanPostProcessor(Properties gemfireProperties) {
|
||||
Assert.notEmpty(gemfireProperties, "GemFire Properties must not be null or empty");
|
||||
Assert.notEmpty(gemfireProperties, "GemFire Properties are required");
|
||||
this.gemfireProperties = gemfireProperties;
|
||||
}
|
||||
|
||||
@@ -295,6 +252,7 @@ public abstract class EmbeddedServiceConfigurationSupport implements ImportBeanD
|
||||
*/
|
||||
@Override
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
|
||||
if (bean instanceof Properties && GEMFIRE_PROPERTIES_BEAN_NAME.equals(beanName)) {
|
||||
Properties gemfirePropertiesBean = (Properties) bean;
|
||||
gemfirePropertiesBean.putAll(gemfireProperties);
|
||||
@@ -302,13 +260,5 @@ public abstract class EmbeddedServiceConfigurationSupport implements ImportBeanD
|
||||
|
||||
return bean;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||
return bean;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,12 @@
|
||||
|
||||
package org.springframework.data.gemfire.config.annotation.support;
|
||||
|
||||
import static org.apache.geode.internal.lang.ObjectUtils.defaultIfNull;
|
||||
import static org.springframework.data.gemfire.util.SpringUtils.defaultIfEmpty;
|
||||
import static org.springframework.data.gemfire.util.ArrayUtils.nullSafeArray;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.geode.cache.DataPolicy;
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
@@ -26,16 +30,14 @@ import org.apache.geode.cache.Region;
|
||||
import org.apache.geode.cache.RegionAttributes;
|
||||
import org.apache.geode.cache.RegionShortcut;
|
||||
import org.apache.geode.cache.client.ClientRegionShortcut;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.data.gemfire.GemfireUtils;
|
||||
import org.springframework.data.gemfire.GenericRegionFactoryBean;
|
||||
import org.springframework.data.gemfire.RegionLookupFactoryBean;
|
||||
import org.springframework.data.gemfire.client.ClientRegionFactoryBean;
|
||||
import org.springframework.data.gemfire.config.annotation.RegionConfigurer;
|
||||
import org.springframework.data.gemfire.config.xml.GemfireConstants;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* The {@link GemFireCacheTypeAwareRegionFactoryBean} class is a smart Spring {@link FactoryBean} that knows how to
|
||||
@@ -43,22 +45,21 @@ import org.springframework.util.Assert;
|
||||
* a {@link org.apache.geode.cache.client.ClientCache} or a peer {@link org.apache.geode.cache.Cache}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see org.springframework.beans.factory.BeanFactoryAware
|
||||
* @see org.springframework.beans.factory.FactoryBean
|
||||
* @see org.springframework.data.gemfire.RegionLookupFactoryBean
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.springframework.beans.factory.FactoryBean
|
||||
* @see org.springframework.data.gemfire.GenericRegionFactoryBean
|
||||
* @see org.springframework.data.gemfire.RegionLookupFactoryBean
|
||||
* @see org.springframework.data.gemfire.RegionFactoryBean
|
||||
* @see org.springframework.data.gemfire.client.ClientRegionFactoryBean
|
||||
* @see org.springframework.data.gemfire.config.annotation.RegionConfigurer
|
||||
* @since 1.9.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class GemFireCacheTypeAwareRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
|
||||
implements BeanFactoryAware {
|
||||
public class GemFireCacheTypeAwareRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> {
|
||||
|
||||
private GemFireCache gemfireCache;
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
private Boolean close = false;
|
||||
|
||||
private Class<K> keyConstraint;
|
||||
@@ -68,6 +69,8 @@ public class GemFireCacheTypeAwareRegionFactoryBean<K, V> extends RegionLookupFa
|
||||
|
||||
private DataPolicy dataPolicy = DataPolicy.DEFAULT;
|
||||
|
||||
private List<RegionConfigurer> regionConfigurers = Collections.emptyList();
|
||||
|
||||
private RegionAttributes<K, V> regionAttributes;
|
||||
|
||||
private RegionShortcut serverRegionShortcut;
|
||||
@@ -79,7 +82,8 @@ public class GemFireCacheTypeAwareRegionFactoryBean<K, V> extends RegionLookupFa
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public Region<K, V> lookupRegion(GemFireCache gemfireCache, String regionName) throws Exception {
|
||||
public Region<K, V> createRegion(GemFireCache gemfireCache, String regionName) throws Exception {
|
||||
|
||||
return (GemfireUtils.isClient(gemfireCache) ? newClientRegion(gemfireCache, regionName)
|
||||
: newServerRegion(gemfireCache, regionName));
|
||||
}
|
||||
@@ -97,20 +101,23 @@ public class GemFireCacheTypeAwareRegionFactoryBean<K, V> extends RegionLookupFa
|
||||
* @see org.apache.geode.cache.Region
|
||||
*/
|
||||
protected Region<K, V> newClientRegion(GemFireCache gemfireCache, String regionName) throws Exception {
|
||||
ClientRegionFactoryBean<K, V> clientRegion = new ClientRegionFactoryBean<K, V>();
|
||||
|
||||
clientRegion.setAttributes(getRegionAttributes());
|
||||
clientRegion.setBeanFactory(getBeanFactory());
|
||||
clientRegion.setCache(gemfireCache);
|
||||
clientRegion.setClose(isClose());
|
||||
clientRegion.setKeyConstraint(getKeyConstraint());
|
||||
clientRegion.setPoolName(getPoolName());
|
||||
clientRegion.setRegionName(regionName);
|
||||
clientRegion.setShortcut(getClientRegionShortcut());
|
||||
clientRegion.setValueConstraint(getValueConstraint());
|
||||
clientRegion.afterPropertiesSet();
|
||||
ClientRegionFactoryBean<K, V> clientRegionFactory = new ClientRegionFactoryBean<>();
|
||||
|
||||
return clientRegion.getObject();
|
||||
clientRegionFactory.setAttributes(getRegionAttributes());
|
||||
clientRegionFactory.setBeanFactory(getBeanFactory());
|
||||
clientRegionFactory.setCache(gemfireCache);
|
||||
clientRegionFactory.setClose(isClose());
|
||||
clientRegionFactory.setKeyConstraint(getKeyConstraint());
|
||||
clientRegionFactory.setPoolName(getPoolName());
|
||||
clientRegionFactory.setRegionConfigurers(this.regionConfigurers);
|
||||
clientRegionFactory.setRegionName(regionName);
|
||||
clientRegionFactory.setShortcut(getClientRegionShortcut());
|
||||
clientRegionFactory.setValueConstraint(getValueConstraint());
|
||||
|
||||
clientRegionFactory.afterPropertiesSet();
|
||||
|
||||
return clientRegionFactory.getObject();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -126,19 +133,22 @@ public class GemFireCacheTypeAwareRegionFactoryBean<K, V> extends RegionLookupFa
|
||||
* @see org.apache.geode.cache.Region
|
||||
*/
|
||||
protected Region<K, V> newServerRegion(GemFireCache gemfireCache, String regionName) throws Exception {
|
||||
GenericRegionFactoryBean<K, V> serverRegion = new GenericRegionFactoryBean<K, V>();
|
||||
|
||||
serverRegion.setAttributes(getRegionAttributes());
|
||||
serverRegion.setCache(gemfireCache);
|
||||
serverRegion.setClose(isClose());
|
||||
serverRegion.setDataPolicy(getDataPolicy());
|
||||
serverRegion.setKeyConstraint(getKeyConstraint());
|
||||
serverRegion.setRegionName(regionName);
|
||||
serverRegion.setShortcut(getServerRegionShortcut());
|
||||
serverRegion.setValueConstraint(getValueConstraint());
|
||||
serverRegion.afterPropertiesSet();
|
||||
GenericRegionFactoryBean<K, V> serverRegionFactory = new GenericRegionFactoryBean<>();
|
||||
|
||||
return serverRegion.getObject();
|
||||
serverRegionFactory.setAttributes(getRegionAttributes());
|
||||
serverRegionFactory.setCache(gemfireCache);
|
||||
serverRegionFactory.setClose(isClose());
|
||||
serverRegionFactory.setDataPolicy(getDataPolicy());
|
||||
serverRegionFactory.setKeyConstraint(getKeyConstraint());
|
||||
serverRegionFactory.setRegionConfigurers(this.regionConfigurers);
|
||||
serverRegionFactory.setRegionName(regionName);
|
||||
serverRegionFactory.setShortcut(getServerRegionShortcut());
|
||||
serverRegionFactory.setValueConstraint(getValueConstraint());
|
||||
|
||||
serverRegionFactory.afterPropertiesSet();
|
||||
|
||||
return serverRegionFactory.getObject();
|
||||
}
|
||||
|
||||
public void setAttributes(RegionAttributes<K, V> regionAttributes) {
|
||||
@@ -149,25 +159,12 @@ public class GemFireCacheTypeAwareRegionFactoryBean<K, V> extends RegionLookupFa
|
||||
return this.regionAttributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
protected BeanFactory getBeanFactory() {
|
||||
Assert.state(this.beanFactory != null, "BeanFactory was not properly initialized");
|
||||
return this.beanFactory;
|
||||
}
|
||||
|
||||
public void setClientRegionShortcut(ClientRegionShortcut clientRegionShortcut) {
|
||||
this.clientRegionShortcut = clientRegionShortcut;
|
||||
}
|
||||
|
||||
protected ClientRegionShortcut getClientRegionShortcut() {
|
||||
return defaultIfNull(this.clientRegionShortcut, ClientRegionShortcut.PROXY);
|
||||
return Optional.ofNullable(this.clientRegionShortcut).orElse(ClientRegionShortcut.PROXY);
|
||||
}
|
||||
|
||||
public void setClose(Boolean close) {
|
||||
@@ -187,7 +184,7 @@ public class GemFireCacheTypeAwareRegionFactoryBean<K, V> extends RegionLookupFa
|
||||
}
|
||||
|
||||
protected DataPolicy getDataPolicy() {
|
||||
return defaultIfNull(this.dataPolicy, DataPolicy.DEFAULT);
|
||||
return Optional.ofNullable(this.dataPolicy).orElse(DataPolicy.DEFAULT);
|
||||
}
|
||||
|
||||
public void setKeyConstraint(Class<K> keyConstraint) {
|
||||
@@ -203,7 +200,33 @@ public class GemFireCacheTypeAwareRegionFactoryBean<K, V> extends RegionLookupFa
|
||||
}
|
||||
|
||||
protected String getPoolName() {
|
||||
return defaultIfEmpty(this.poolName, GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME);
|
||||
return Optional.ofNullable(this.poolName).filter(StringUtils::hasText)
|
||||
.orElse(GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe operation used to set an array of {@link RegionConfigurer RegionConfigurers} used to apply
|
||||
* additional configuration to this {@link RegionLookupFactoryBean} when using Annotation-based configuration.
|
||||
*
|
||||
* @param regionConfigurers array of {@link RegionConfigurer RegionConfigurers} used to apply
|
||||
* additional configuration to this {@link RegionLookupFactoryBean}.
|
||||
* @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 used to set an {@link Iterable} of {@link RegionConfigurer RegionConfigurers} used to apply
|
||||
* additional configuration to this {@link RegionLookupFactoryBean} when using Annotation-based configuration.
|
||||
*
|
||||
* @param regionConfigurers {@link Iterable} of {@link RegionConfigurer RegionConfigurers} used to apply
|
||||
* additional configuration to this {@link RegionLookupFactoryBean}.
|
||||
* @see org.springframework.data.gemfire.config.annotation.RegionConfigurer
|
||||
*/
|
||||
public void setRegionConfigurers(List<RegionConfigurer> regionConfigurers) {
|
||||
this.regionConfigurers = Optional.ofNullable(regionConfigurers).orElseGet(Collections::emptyList);
|
||||
}
|
||||
|
||||
public void setServerRegionShortcut(RegionShortcut shortcut) {
|
||||
|
||||
@@ -17,7 +17,10 @@
|
||||
|
||||
package org.springframework.data.gemfire.search.lucene;
|
||||
|
||||
import static java.util.stream.StreamSupport.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.CollectionUtils.nullSafeList;
|
||||
import static org.springframework.data.gemfire.util.CollectionUtils.nullSafeMap;
|
||||
import static org.springframework.util.CollectionUtils.isEmpty;
|
||||
@@ -27,6 +30,7 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.cache.Region;
|
||||
@@ -35,43 +39,53 @@ import org.apache.geode.cache.lucene.LuceneService;
|
||||
import org.apache.geode.cache.lucene.LuceneServiceProvider;
|
||||
import org.apache.lucene.analysis.Analyzer;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.data.gemfire.config.annotation.IndexConfigurer;
|
||||
import org.springframework.data.gemfire.support.AbstractFactoryBeanSupport;
|
||||
import org.springframework.data.gemfire.util.CacheUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Spring {@link FactoryBean} used to construct {@link LuceneIndex Lucene Indexes} on application domain object fields.
|
||||
* Spring {@link FactoryBean} used to construct, configure and initialize {@link LuceneIndex Lucene Indexes}
|
||||
* on application domain object fields.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.beans.factory.BeanNameAware
|
||||
* @see org.springframework.beans.factory.DisposableBean
|
||||
* @see org.springframework.beans.factory.FactoryBean
|
||||
* @see org.springframework.beans.factory.InitializingBean
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.apache.geode.cache.lucene.LuceneIndex
|
||||
* @see org.apache.geode.cache.lucene.LuceneService
|
||||
* @see org.apache.geode.cache.lucene.LuceneServiceProvider
|
||||
* @see org.apache.lucene.analysis.Analyzer
|
||||
* @see org.springframework.beans.factory.DisposableBean
|
||||
* @see org.springframework.beans.factory.FactoryBean
|
||||
* @see org.springframework.beans.factory.InitializingBean
|
||||
* @see org.springframework.data.gemfire.config.annotation.IndexConfigurer
|
||||
* @see org.springframework.data.gemfire.support.AbstractFactoryBeanSupport
|
||||
* @since 1.1.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class LuceneIndexFactoryBean implements FactoryBean<LuceneIndex>,
|
||||
BeanFactoryAware, BeanNameAware, InitializingBean, DisposableBean {
|
||||
public class LuceneIndexFactoryBean extends AbstractFactoryBeanSupport<LuceneIndex>
|
||||
implements DisposableBean, InitializingBean {
|
||||
|
||||
protected static final boolean DEFAULT_DESTROY = false;
|
||||
|
||||
private boolean destroy = DEFAULT_DESTROY;
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
private GemFireCache gemfireCache;
|
||||
|
||||
private List<IndexConfigurer> indexConfigurers = Collections.emptyList();
|
||||
|
||||
private IndexConfigurer compositeIndexConfigurer = new IndexConfigurer() {
|
||||
|
||||
@Override
|
||||
public void configure(String beanName, LuceneIndexFactoryBean bean) {
|
||||
nullSafeCollection(indexConfigurers).forEach(indexConfigurer -> indexConfigurer.configure(beanName, bean));
|
||||
}
|
||||
};
|
||||
|
||||
private List<String> fields;
|
||||
|
||||
private LuceneIndex luceneIndex;
|
||||
@@ -90,13 +104,72 @@ public class LuceneIndexFactoryBean implements FactoryBean<LuceneIndex>,
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
|
||||
String indexName = getIndexName();
|
||||
|
||||
applyIndexConfigurers(indexName);
|
||||
|
||||
this.gemfireCache = resolveCache();
|
||||
this.luceneService = resolveLuceneService();
|
||||
this.regionPath = resolveRegionPath();
|
||||
|
||||
setLuceneIndex(createIndex(indexName, getRegionPath()));
|
||||
setLuceneIndex(resolveLuceneIndex(indexName, getRegionPath()));
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private void applyIndexConfigurers(String indexName) {
|
||||
applyIndexConfigurers(indexName, getCompositeRegionConfigurer());
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe operation to apply the given array of {@link IndexConfigurer IndexConfigurers}
|
||||
* to this {@link LuceneIndexFactoryBean}.
|
||||
*
|
||||
* @param indexName {@link String} containing the name of the {@link LuceneIndex}.
|
||||
* @param indexConfigurers array of {@link IndexConfigurer IndexConfigurers} applied
|
||||
* to this {@link LuceneIndexFactoryBean}.
|
||||
* @see org.springframework.data.gemfire.config.annotation.RegionConfigurer
|
||||
* @see #applyIndexConfigurers(String, Iterable)
|
||||
*/
|
||||
protected void applyIndexConfigurers(String indexName, IndexConfigurer... indexConfigurers) {
|
||||
applyIndexConfigurers(indexName, Arrays.asList(nullSafeArray(indexConfigurers, IndexConfigurer.class)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe operation to apply the given {@link Iterable} of {@link IndexConfigurer IndexConfigurers}
|
||||
* to this {@link LuceneIndexFactoryBean}.
|
||||
*
|
||||
* @param indexName {@link String} containing the name of the {@link LuceneIndex}.
|
||||
* @param indexConfigurers {@link Iterable} of {@link IndexConfigurer IndexConfigurers} applied
|
||||
* to this {@link LuceneIndexFactoryBean}.
|
||||
* @see org.springframework.data.gemfire.config.annotation.RegionConfigurer
|
||||
*/
|
||||
protected void applyIndexConfigurers(String indexName, Iterable<IndexConfigurer> indexConfigurers) {
|
||||
stream(nullSafeIterable(indexConfigurers).spliterator(), false)
|
||||
.forEach(indexConfigurer -> indexConfigurer.configure(indexName, this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to resolve a {@link LuceneIndex} by the given {@link String indexName} first then attempts to create
|
||||
* the {@link LuceneIndex} with the given {@link Region#getFullPath() Region path}.
|
||||
*
|
||||
* @param indexName {@link String name} of the {@link LuceneIndex} to resolve.
|
||||
* @param regionPath {@link Region#getFullPath() Region path} on which the {@link LuceneIndex} is applied.
|
||||
* @return the resolved {@link LuceneIndex} by the given {@link String indexName} or the created {@link LuceneIndex}
|
||||
* with the given {@link Region#getFullPath() Region path} if the {@link LuceneIndex} could not be resolved by
|
||||
* {@link String indexName}.
|
||||
* @see org.apache.geode.cache.lucene.LuceneService#getIndex(String, String)
|
||||
* @see #createLuceneIndex(String, String)
|
||||
* @see #getLuceneIndex()
|
||||
*/
|
||||
protected LuceneIndex resolveLuceneIndex(String indexName, String regionPath) {
|
||||
|
||||
Supplier<LuceneIndex> luceneIndexSupplier = () ->
|
||||
Optional.ofNullable(resolveLuceneService())
|
||||
.map(luceneService -> luceneService.getIndex(indexName, regionPath))
|
||||
.orElseGet(() -> createLuceneIndex(indexName, regionPath));
|
||||
|
||||
return getLuceneIndex().orElseGet(luceneIndexSupplier);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -115,7 +188,8 @@ public class LuceneIndexFactoryBean implements FactoryBean<LuceneIndex>,
|
||||
* @see #getFields()
|
||||
* @see #resolveFields(List)
|
||||
*/
|
||||
protected LuceneIndex createIndex(String indexName, String regionPath) {
|
||||
protected LuceneIndex createLuceneIndex(String indexName, String regionPath) {
|
||||
|
||||
LuceneService luceneService = resolveLuceneService();
|
||||
|
||||
Map<String, Analyzer> fieldAnalyzers = getFieldAnalyzers();
|
||||
@@ -147,6 +221,7 @@ public class LuceneIndexFactoryBean implements FactoryBean<LuceneIndex>,
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public void destroy() throws Exception {
|
||||
|
||||
LuceneIndex luceneIndex = getObject();
|
||||
|
||||
if (isLuceneIndexDestroyable(luceneIndex)) {
|
||||
@@ -172,6 +247,7 @@ public class LuceneIndexFactoryBean implements FactoryBean<LuceneIndex>,
|
||||
*/
|
||||
@Override
|
||||
public LuceneIndex getObject() throws Exception {
|
||||
|
||||
if (this.luceneIndex == null) {
|
||||
setLuceneIndex(Optional.ofNullable(resolveLuceneService())
|
||||
.map((luceneService) -> luceneService.getIndex(getIndexName(), resolveRegionPath()))
|
||||
@@ -189,14 +265,6 @@ public class LuceneIndexFactoryBean implements FactoryBean<LuceneIndex>,
|
||||
return Optional.ofNullable(this.luceneIndex).<Class<?>>map(LuceneIndex::getClass).orElse(LuceneIndex.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a reference to the {@link GemFireCache}.
|
||||
*
|
||||
@@ -231,6 +299,7 @@ public class LuceneIndexFactoryBean implements FactoryBean<LuceneIndex>,
|
||||
* @see #resolveLuceneService(GemFireCache)
|
||||
*/
|
||||
protected LuceneService resolveLuceneService() {
|
||||
|
||||
return Optional.ofNullable(getLuceneService()).orElseGet(() ->
|
||||
Optional.ofNullable(getBeanFactory()).map(beanFactory -> {
|
||||
try {
|
||||
@@ -267,6 +336,7 @@ public class LuceneIndexFactoryBean implements FactoryBean<LuceneIndex>,
|
||||
* @see #getRegionPath()
|
||||
*/
|
||||
protected Region<?, ?> resolveRegion() {
|
||||
|
||||
return Optional.ofNullable(getRegion()).orElseGet(() -> {
|
||||
GemFireCache cache = resolveCache();
|
||||
String regionPath = getRegionPath();
|
||||
@@ -286,6 +356,7 @@ public class LuceneIndexFactoryBean implements FactoryBean<LuceneIndex>,
|
||||
* @see #getRegionPath()
|
||||
*/
|
||||
protected String resolveRegionPath() {
|
||||
|
||||
String regionPath = Optional.ofNullable(resolveRegion())
|
||||
.map(Region::getFullPath).orElseGet(this::getRegionPath);
|
||||
|
||||
@@ -294,29 +365,12 @@ public class LuceneIndexFactoryBean implements FactoryBean<LuceneIndex>,
|
||||
return regionPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the containing Spring {@link BeanFactory} if set.
|
||||
*
|
||||
* @return a reference to the containing Spring {@link BeanFactory} if set.
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
*/
|
||||
protected BeanFactory getBeanFactory() {
|
||||
return this.beanFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void setBeanName(String name) {
|
||||
super.setBeanName(name);
|
||||
setIndexName(name);
|
||||
}
|
||||
|
||||
@@ -341,6 +395,17 @@ public class LuceneIndexFactoryBean implements FactoryBean<LuceneIndex>,
|
||||
return this.gemfireCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the Composite {@link IndexConfigurer} used to apply additional configuration
|
||||
* to this {@link LuceneIndexFactoryBean} on Spring container initialization.
|
||||
*
|
||||
* @return the Composite {@link IndexConfigurer}.
|
||||
* @see org.springframework.data.gemfire.config.annotation.IndexConfigurer
|
||||
*/
|
||||
protected IndexConfigurer getCompositeRegionConfigurer() {
|
||||
return this.compositeIndexConfigurer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether to destroy the {@link LuceneIndex} on shutdown.
|
||||
*
|
||||
@@ -415,6 +480,31 @@ public class LuceneIndexFactoryBean implements FactoryBean<LuceneIndex>,
|
||||
return nullSafeList(this.fields);
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe operation to set an array of {@link IndexConfigurer IndexConfigurers} used to apply
|
||||
* additional configuration to this {@link LuceneIndexFactoryBean} when using Annotation-based configuration.
|
||||
*
|
||||
* @param indexConfigurers array of {@link IndexConfigurer IndexConfigurers} used to apply
|
||||
* additional configuration to this {@link LuceneIndexFactoryBean}.
|
||||
* @see org.springframework.data.gemfire.config.annotation.IndexConfigurer
|
||||
* @see #setIndexConfigurers(List)
|
||||
*/
|
||||
public void setIndexConfigurers(IndexConfigurer... indexConfigurers) {
|
||||
setIndexConfigurers(Arrays.asList(nullSafeArray(indexConfigurers, IndexConfigurer.class)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe operation to set an {@link Iterable} of {@link IndexConfigurer IndexConfigurers} used to apply
|
||||
* additional configuration to this {@link LuceneIndexFactoryBean} when using Annotation-based configuration.
|
||||
*
|
||||
* @param indexConfigurers {@link Iterable } of {@link IndexConfigurer IndexConfigurers} used to apply
|
||||
* additional configuration to this {@link LuceneIndexFactoryBean}.
|
||||
* @see org.springframework.data.gemfire.config.annotation.IndexConfigurer
|
||||
*/
|
||||
public void setIndexConfigurers(List<IndexConfigurer> indexConfigurers) {
|
||||
this.indexConfigurers = Optional.ofNullable(indexConfigurers).orElseGet(Collections::emptyList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the {@link LuceneIndex} as identified in the {@link GemFireCache}.
|
||||
*
|
||||
@@ -437,16 +527,27 @@ public class LuceneIndexFactoryBean implements FactoryBean<LuceneIndex>,
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link LuceneIndex} as the index created by this {@link FactoryBean}.
|
||||
* Returns an {@link Optional} reference to the {@link LuceneIndex} created by this {@link LuceneIndexFactoryBean}.
|
||||
*
|
||||
* This method is for testing purposes only!
|
||||
* @return an {@link Optional} reference to the {@link LuceneIndex} created by this {@link LuceneIndexFactoryBean}.
|
||||
* @see org.apache.geode.cache.lucene.LuceneIndex
|
||||
* @see java.util.Optional
|
||||
*/
|
||||
public Optional<LuceneIndex> getLuceneIndex() {
|
||||
return Optional.ofNullable(this.luceneIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the given {@link LuceneIndex} as the index created by this {@link FactoryBean}.
|
||||
*
|
||||
* This method is generally used for testing purposes only.
|
||||
*
|
||||
* @param luceneIndex {@link LuceneIndex} created by this {@link FactoryBean}.
|
||||
* @return this {@link LuceneIndexFactoryBean}.
|
||||
* @see org.springframework.data.gemfire.search.lucene.LuceneIndexFactoryBean
|
||||
* @see org.apache.geode.cache.lucene.LuceneIndex
|
||||
*/
|
||||
protected LuceneIndexFactoryBean setLuceneIndex(LuceneIndex luceneIndex) {
|
||||
public LuceneIndexFactoryBean setLuceneIndex(LuceneIndex luceneIndex) {
|
||||
this.luceneIndex = luceneIndex;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -15,12 +15,22 @@
|
||||
*/
|
||||
package org.springframework.data.gemfire.server;
|
||||
|
||||
import static java.util.stream.StreamSupport.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.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.geode.cache.Cache;
|
||||
import org.apache.geode.cache.InterestRegistrationListener;
|
||||
import org.apache.geode.cache.client.ClientCache;
|
||||
import org.apache.geode.cache.server.CacheServer;
|
||||
import org.apache.geode.cache.server.ClientSubscriptionConfig;
|
||||
import org.apache.geode.cache.server.ServerLoadProbe;
|
||||
@@ -29,18 +39,28 @@ import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.context.SmartLifecycle;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.data.gemfire.config.annotation.CacheServerConfigurer;
|
||||
import org.springframework.data.gemfire.support.AbstractFactoryBeanSupport;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* FactoryBean for easy creation and configuration of GemFire {@link CacheServer} instances.
|
||||
* Spring {@link FactoryBean} used to construct, configure and initialize a {@link CacheServer}.
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @see org.apache.geode.cache.server.CacheServer
|
||||
* @see org.springframework.beans.factory.DisposableBean
|
||||
* @see org.springframework.beans.factory.FactoryBean
|
||||
* @see org.springframework.beans.factory.InitializingBean
|
||||
* @see org.springframework.context.SmartLifecycle
|
||||
* @see org.springframework.data.gemfire.config.annotation.CacheServerConfigurer
|
||||
* @see org.springframework.data.gemfire.support.AbstractFactoryBeanSupport
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class CacheServerFactoryBean implements FactoryBean<CacheServer>,
|
||||
InitializingBean, DisposableBean, SmartLifecycle {
|
||||
public class CacheServerFactoryBean extends AbstractFactoryBeanSupport<CacheServer>
|
||||
implements DisposableBean, InitializingBean, SmartLifecycle {
|
||||
|
||||
private boolean autoStartup = true;
|
||||
private boolean notifyBySubscription = CacheServer.DEFAULT_NOTIFY_BY_SUBSCRIPTION;
|
||||
@@ -60,6 +80,12 @@ public class CacheServerFactoryBean implements FactoryBean<CacheServer>,
|
||||
|
||||
private CacheServer cacheServer;
|
||||
|
||||
private List<CacheServerConfigurer> cacheServerConfigurers = Collections.emptyList();
|
||||
|
||||
private CacheServerConfigurer compositeCacheServerConfigurer = (beanName, bean) ->
|
||||
nullSafeCollection(cacheServerConfigurers).forEach(cacheServerConfigurer ->
|
||||
cacheServerConfigurer.configure(beanName, bean));
|
||||
|
||||
private ServerLoadProbe serverLoadProbe = CacheServer.DEFAULT_LOAD_PROBE;
|
||||
|
||||
private Set<InterestRegistrationListener> listeners = Collections.emptySet();
|
||||
@@ -75,68 +101,149 @@ public class CacheServerFactoryBean implements FactoryBean<CacheServer>,
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public void afterPropertiesSet() throws IOException {
|
||||
Assert.notNull(cache, "A GemFire Cache is required.");
|
||||
|
||||
cacheServer = cache.addCacheServer();
|
||||
cacheServer.setBindAddress(bindAddress);
|
||||
cacheServer.setGroups(serverGroups);
|
||||
cacheServer.setHostnameForClients(hostNameForClients);
|
||||
cacheServer.setLoadPollInterval(loadPollInterval);
|
||||
cacheServer.setLoadProbe(serverLoadProbe);
|
||||
cacheServer.setMaxConnections(maxConnections);
|
||||
cacheServer.setMaximumMessageCount(maxMessageCount);
|
||||
cacheServer.setMaximumTimeBetweenPings(maxTimeBetweenPings);
|
||||
cacheServer.setMaxThreads(maxThreads);
|
||||
cacheServer.setMessageTimeToLive(messageTimeToLive);
|
||||
cacheServer.setNotifyBySubscription(notifyBySubscription);
|
||||
cacheServer.setPort(port);
|
||||
cacheServer.setSocketBufferSize(socketBufferSize);
|
||||
applyCacheServerConfigurers();
|
||||
|
||||
for (InterestRegistrationListener listener : listeners) {
|
||||
cacheServer.registerInterestRegistrationListener(listener);
|
||||
}
|
||||
Cache cache = resolveCache();
|
||||
|
||||
ClientSubscriptionConfig config = cacheServer.getClientSubscriptionConfig();
|
||||
this.cacheServer = postProcess(configure(addCacheServer(cache)));
|
||||
}
|
||||
|
||||
config.setCapacity(subscriptionCapacity);
|
||||
getSubscriptionEvictionPolicy().setEvictionPolicy(config);
|
||||
|
||||
if (StringUtils.hasText(subscriptionDiskStore)) {
|
||||
config.setDiskStoreName(subscriptionDiskStore);
|
||||
}
|
||||
/* (non-Javadoc) */
|
||||
private void applyCacheServerConfigurers() {
|
||||
applyCacheServerConfigurers(getCompositeCacheServerConfigurer());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* Null-safe operation to apply the given array of {@link CacheServerConfigurer CacheServerConfigurers}
|
||||
* to this {@link CacheServerFactoryBean}.
|
||||
*
|
||||
* @param cacheServerConfigurers array of {@link CacheServerConfigurer CacheServerConfigurers} applied to
|
||||
* this {@link CacheServerFactoryBean}.
|
||||
* @see org.springframework.data.gemfire.config.annotation.CacheServerConfigurer
|
||||
* @see #applyCacheServerConfigurers(Iterable)
|
||||
*/
|
||||
public CacheServer getObject() {
|
||||
protected void applyCacheServerConfigurers(CacheServerConfigurer... cacheServerConfigurers) {
|
||||
applyCacheServerConfigurers(Arrays.asList(nullSafeArray(cacheServerConfigurers, CacheServerConfigurer.class)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe operation to apply the given {@link Iterable} of {@link CacheServerConfigurer CacheServerConfigurers}
|
||||
* to this {@link CacheServerFactoryBean}.
|
||||
*
|
||||
* @param cacheServerConfigurers {@link Iterable} of {@link CacheServerConfigurer CacheServerConfigurers} applied to
|
||||
* this {@link CacheServerFactoryBean}.
|
||||
* @see org.springframework.data.gemfire.config.annotation.CacheServerConfigurer
|
||||
*/
|
||||
protected void applyCacheServerConfigurers(Iterable<CacheServerConfigurer> cacheServerConfigurers) {
|
||||
stream(nullSafeIterable(cacheServerConfigurers).spliterator(), false)
|
||||
.forEach(cacheServerConfigurer -> cacheServerConfigurer.configure(getBeanName(), this));
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private Cache resolveCache() {
|
||||
return Optional.ofNullable(this.cache)
|
||||
.orElseThrow(() -> newIllegalArgumentException("Cache is required"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a {@link CacheServer} to the given {@link Cache} for server {@link ClientCache cache clients}.
|
||||
*
|
||||
* @param cache {@link Cache} used to add a {@link CacheServer}.
|
||||
* @return the newly added {@link CacheServer}.
|
||||
* @see org.apache.geode.cache.Cache#addCacheServer()
|
||||
* @see org.apache.geode.cache.server.CacheServer
|
||||
*/
|
||||
protected CacheServer addCacheServer(Cache cache) {
|
||||
return cache.addCacheServer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the provided {@link CacheServer} with any custom, application-specific configuration.
|
||||
*
|
||||
* @param cacheServer {@link CacheServer} to configure.
|
||||
* @return the given {@link CacheServer}.
|
||||
* @see org.apache.geode.cache.server.CacheServer
|
||||
*/
|
||||
protected CacheServer configure(CacheServer cacheServer) {
|
||||
|
||||
cacheServer.setBindAddress(this.bindAddress);
|
||||
cacheServer.setGroups(this.serverGroups);
|
||||
cacheServer.setHostnameForClients(this.hostNameForClients);
|
||||
cacheServer.setLoadPollInterval(this.loadPollInterval);
|
||||
cacheServer.setLoadProbe(this.serverLoadProbe);
|
||||
cacheServer.setMaxConnections(this.maxConnections);
|
||||
cacheServer.setMaximumMessageCount(this.maxMessageCount);
|
||||
cacheServer.setMaximumTimeBetweenPings(this.maxTimeBetweenPings);
|
||||
cacheServer.setMaxThreads(this.maxThreads);
|
||||
cacheServer.setMessageTimeToLive(this.messageTimeToLive);
|
||||
cacheServer.setNotifyBySubscription(this.notifyBySubscription);
|
||||
cacheServer.setPort(this.port);
|
||||
cacheServer.setSocketBufferSize(this.socketBufferSize);
|
||||
|
||||
nullSafeCollection(this.listeners).forEach(cacheServer::registerInterestRegistrationListener);
|
||||
|
||||
ClientSubscriptionConfig config = cacheServer.getClientSubscriptionConfig();
|
||||
|
||||
config.setCapacity(this.subscriptionCapacity);
|
||||
getSubscriptionEvictionPolicy().setEvictionPolicy(config);
|
||||
|
||||
Optional.ofNullable(this.subscriptionDiskStore).filter(StringUtils::hasText)
|
||||
.ifPresent(config::setDiskStoreName);
|
||||
|
||||
return cacheServer;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* Post-process the {@link CacheServer} with any necessary follow-up actions.
|
||||
*
|
||||
* @param cacheServer {@link CacheServer} to process.
|
||||
* @return the given {@link CacheServer}.
|
||||
* @see org.apache.geode.cache.server.CacheServer
|
||||
*/
|
||||
public Class<?> getObjectType() {
|
||||
return (this.cacheServer != null ? cacheServer.getClass() : CacheServer.class);
|
||||
protected CacheServer postProcess(CacheServer cacheServer) {
|
||||
return cacheServer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the Composite {@link CacheServerConfigurer} used to apply additional configuration
|
||||
* to this {@link CacheServerFactoryBean} on Spring container initialization.
|
||||
*
|
||||
* @return the Composite {@link CacheServerConfigurer}.
|
||||
* @see org.springframework.data.gemfire.config.annotation.CacheServerConfigurer
|
||||
*/
|
||||
protected CacheServerConfigurer getCompositeCacheServerConfigurer() {
|
||||
return this.compositeCacheServerConfigurer;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
@Override
|
||||
public CacheServer getObject() {
|
||||
return this.cacheServer;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Class<?> getObjectType() {
|
||||
return Optional.ofNullable(this.cacheServer).map(CacheServer::getClass).orElse((Class) CacheServer.class);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
public boolean isRunning() {
|
||||
return (cacheServer != null && cacheServer.isRunning());
|
||||
return Optional.ofNullable(this.cacheServer).map(CacheServer::isRunning).orElse(false);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
public boolean isAutoStartup() {
|
||||
return autoStartup;
|
||||
return this.autoStartup;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -149,10 +256,11 @@ public class CacheServerFactoryBean implements FactoryBean<CacheServer>,
|
||||
/* (non-Javadoc) */
|
||||
public void destroy() {
|
||||
stop();
|
||||
cacheServer = null;
|
||||
this.cacheServer = null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@Override
|
||||
public void start() {
|
||||
try {
|
||||
cacheServer.start();
|
||||
@@ -163,16 +271,15 @@ public class CacheServerFactoryBean implements FactoryBean<CacheServer>,
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
public void stop(final Runnable callback) {
|
||||
@Override
|
||||
public void stop(Runnable callback) {
|
||||
stop();
|
||||
callback.run();
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
public void stop() {
|
||||
if (cacheServer != null) {
|
||||
cacheServer.stop();
|
||||
}
|
||||
Optional.ofNullable(this.cacheServer).ifPresent(CacheServer::stop);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@@ -198,6 +305,32 @@ public class CacheServerFactoryBean implements FactoryBean<CacheServer>,
|
||||
this.cacheServer = cacheServer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe operation to set an array of {@link CacheServerConfigurer CacheServerConfigurers} used to apply
|
||||
* additional configuration to this {@link CacheServerFactoryBean} when using Annotation-based configuration.
|
||||
*
|
||||
* @param cacheServerConfigurers array of {@link CacheServerConfigurer CacheServerConfigurers} used to apply
|
||||
* additional configuration to this {@link CacheServerFactoryBean}.
|
||||
* @see org.springframework.data.gemfire.config.annotation.PeerCacheConfigurer
|
||||
* @see #setCacheServerConfigurers(List)
|
||||
*/
|
||||
public void setCacheServerConfigurers(CacheServerConfigurer... cacheServerConfigurers) {
|
||||
setCacheServerConfigurers(Arrays.asList(nullSafeArray(cacheServerConfigurers, CacheServerConfigurer.class)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe operation to set an {@link Iterable} of {@link CacheServerConfigurer CacheServerConfigurers}
|
||||
* used to apply additional configuration to this {@link CacheServerFactoryBean} when using
|
||||
* Annotation-based configuration.
|
||||
*
|
||||
* @param cacheServerConfigurers {@literal Iterable} of {@link CacheServerConfigurer CacheServerConfigurers}
|
||||
* used to apply additional configuration to this {@link CacheServerFactoryBean}.
|
||||
* @see org.springframework.data.gemfire.config.annotation.PeerCacheConfigurer
|
||||
*/
|
||||
public void setCacheServerConfigurers(List<CacheServerConfigurer> cacheServerConfigurers) {
|
||||
this.cacheServerConfigurers = Optional.ofNullable(cacheServerConfigurers).orElseGet(Collections::emptyList);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
public void setHostNameForClients(String hostNameForClients) {
|
||||
this.hostNameForClients = hostNameForClients;
|
||||
@@ -275,7 +408,7 @@ public class CacheServerFactoryBean implements FactoryBean<CacheServer>,
|
||||
|
||||
/* (non-Javadoc) */
|
||||
SubscriptionEvictionPolicy getSubscriptionEvictionPolicy() {
|
||||
return (subscriptionEvictionPolicy != null ? subscriptionEvictionPolicy : SubscriptionEvictionPolicy.DEFAULT);
|
||||
return Optional.ofNullable(this.subscriptionEvictionPolicy).orElse(SubscriptionEvictionPolicy.DEFAULT);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
|
||||
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* Copyright 2017 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.support;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
|
||||
/**
|
||||
* The {@link AbstractFactoryBeanSupport} class is an abstract Spring {@link FactoryBean} base class implementation
|
||||
* encapsulating operations common to SDG's {@link FactoryBean} implementations.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.beans.factory.BeanClassLoaderAware
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see org.springframework.beans.factory.BeanFactoryAware
|
||||
* @see org.springframework.beans.factory.BeanNameAware
|
||||
* @see org.springframework.beans.factory.FactoryBean
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public abstract class AbstractFactoryBeanSupport<T> implements FactoryBean<T>,
|
||||
BeanClassLoaderAware, BeanFactoryAware, BeanNameAware {
|
||||
|
||||
protected static final boolean DEFAULT_SINGLETON = true;
|
||||
|
||||
private ClassLoader beanClassLoader;
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
private final Log log = newLog();
|
||||
|
||||
private String beanName;
|
||||
|
||||
/**
|
||||
* Constructs a new instance of {@link Log} to log statements printed by Spring Data GemFire/Geode.
|
||||
*
|
||||
* @return a new instance of {@link Log}.
|
||||
* @see org.apache.commons.logging.LogFactory#getLog(Class)
|
||||
* @see org.apache.commons.logging.Log
|
||||
*/
|
||||
protected Log newLog() {
|
||||
return LogFactory.getLog(getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a reference to the {@link ClassLoader} used by the Spring container to load and create bean classes.
|
||||
*
|
||||
* @param classLoader {@link ClassLoader} used by the Spring container to load and create bean classes.
|
||||
* @see org.springframework.beans.factory.BeanClassLoaderAware#setBeanClassLoader(ClassLoader)
|
||||
* @see java.lang.ClassLoader
|
||||
*/
|
||||
@Override
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
this.beanClassLoader = classLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the {@link ClassLoader} used by the Spring container to load and create bean classes.
|
||||
*
|
||||
* @return the {@link ClassLoader} used by the Spring container to load and create bean classes.
|
||||
* @see org.springframework.beans.factory.BeanClassLoaderAware#setBeanClassLoader(ClassLoader)
|
||||
* @see java.lang.ClassLoader
|
||||
*/
|
||||
public ClassLoader getBeanClassLoader() {
|
||||
return this.beanClassLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a reference to the Spring {@link BeanFactory} in which this {@link FactoryBean} was declared.
|
||||
*
|
||||
* @param beanFactory reference to the declaring Spring {@link BeanFactory}.
|
||||
* @see org.springframework.beans.factory.BeanFactoryAware#setBeanFactory(BeanFactory)
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
*/
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the Spring {@link BeanFactory} in which this {@link FactoryBean} was declared.
|
||||
*
|
||||
* @return a reference to the declaring Spring {@link BeanFactory}.
|
||||
* @see org.springframework.beans.factory.BeanFactoryAware#setBeanFactory(BeanFactory)
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
*/
|
||||
public BeanFactory getBeanFactory() {
|
||||
return this.beanFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link String bean name} assigned to this {@link FactoryBean} as declared in the Spring container.
|
||||
*
|
||||
* @param name {@link String bean name} assigned to this {@link FactoryBean} as declared in the Spring container.
|
||||
* @see org.springframework.beans.factory.BeanNameAware#setBeanName(String)
|
||||
* @see java.lang.String
|
||||
*/
|
||||
@Override
|
||||
public void setBeanName(String name) {
|
||||
this.beanName = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link String bean name} assigned to this {@link FactoryBean} as declared in the Spring container.
|
||||
*
|
||||
* @return the {@link String bean name} assigned to this {@link FactoryBean} as declared in the Spring container.
|
||||
* @see org.springframework.beans.factory.BeanNameAware#setBeanName(String)
|
||||
* @see java.lang.String
|
||||
*/
|
||||
public String getBeanName() {
|
||||
return this.beanName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the {@link Log} used by this {@link FactoryBean} to log {@link String messages}.
|
||||
*
|
||||
* @return a reference to the {@link Log} used by this {@link FactoryBean} to log {@link String messages}.
|
||||
* @see org.apache.commons.logging.Log
|
||||
*/
|
||||
protected Log getLog() {
|
||||
return this.log;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates that this {@link FactoryBean} produces a single bean instance.
|
||||
*
|
||||
* @return {@literal true} by default.
|
||||
* @see org.springframework.beans.factory.FactoryBean#isSingleton()
|
||||
*/
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return DEFAULT_SINGLETON;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the {@link String message} formatted with the array of {@link Object arguments} at debug level.
|
||||
*
|
||||
* @param message {@link String} containing the message to log.
|
||||
* @param args array of {@link Object arguments} used to format the {@code message}.
|
||||
* @see #logDebug(Supplier)
|
||||
*/
|
||||
protected void logDebug(String message, Object... args) {
|
||||
logDebug(() -> String.format(message, args));
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the {@link String message} supplied by the given {@link Supplier} at debug level.
|
||||
*
|
||||
* @param message {@link Supplier} containing the {@link String message} and arguments to log.
|
||||
* @see org.apache.commons.logging.Log#isDebugEnabled()
|
||||
* @see org.apache.commons.logging.Log#debug(Object)
|
||||
* @see #getLog()
|
||||
*/
|
||||
protected void logDebug(Supplier<String> message) {
|
||||
Optional.ofNullable(getLog())
|
||||
.filter(Log::isDebugEnabled)
|
||||
.ifPresent(log -> log.debug(message.get()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the {@link String message} formatted with the array of {@link Object arguments} at info level.
|
||||
*
|
||||
* @param message {@link String} containing the message to log.
|
||||
* @param args array of {@link Object arguments} used to format the {@code message}.
|
||||
* @see #logInfo(Supplier)
|
||||
*/
|
||||
protected void logInfo(String message, Object... args) {
|
||||
logInfo(() -> String.format(message, args));
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the {@link String message} supplied by the given {@link Supplier} at info level.
|
||||
*
|
||||
* @param message {@link Supplier} containing the {@link String message} and arguments to log.
|
||||
* @see org.apache.commons.logging.Log#isInfoEnabled()
|
||||
* @see org.apache.commons.logging.Log#info(Object)
|
||||
* @see #getLog()
|
||||
*/
|
||||
protected void logInfo(Supplier<String> message) {
|
||||
Optional.ofNullable(getLog())
|
||||
.filter(Log::isInfoEnabled)
|
||||
.ifPresent(log -> log.info(message.get()));
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,8 @@
|
||||
|
||||
package org.springframework.data.gemfire.util;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.geode.cache.Cache;
|
||||
import org.apache.geode.cache.CacheClosedException;
|
||||
import org.apache.geode.cache.CacheFactory;
|
||||
@@ -29,11 +31,10 @@ import org.apache.geode.internal.cache.GemFireCacheImpl;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* CacheUtils is an abstract utility class encapsulating common operations for working with GemFire Cache
|
||||
* and ClientCache instances.
|
||||
* {@link CacheUtils} is an abstract utility class encapsulating common operations for working with
|
||||
* {@link Cache} and {@link ClientCache} instances.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.data.gemfire.util.DistributedSystemUtils
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see org.apache.geode.cache.CacheFactory
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
@@ -42,6 +43,7 @@ import org.springframework.util.StringUtils;
|
||||
* @see org.apache.geode.cache.client.ClientCacheFactory
|
||||
* @see org.apache.geode.distributed.DistributedSystem
|
||||
* @see org.apache.geode.internal.cache.GemFireCacheImpl
|
||||
* @see org.springframework.data.gemfire.util.DistributedSystemUtils
|
||||
* @since 1.8.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
@@ -52,6 +54,7 @@ public abstract class CacheUtils extends DistributedSystemUtils {
|
||||
/* (non-Javadoc) */
|
||||
@SuppressWarnings("all")
|
||||
public static boolean isClient(GemFireCache cache) {
|
||||
|
||||
boolean client = (cache instanceof ClientCache);
|
||||
|
||||
if (cache instanceof GemFireCacheImpl) {
|
||||
@@ -63,6 +66,7 @@ public abstract class CacheUtils extends DistributedSystemUtils {
|
||||
|
||||
/* (non-Javadoc) */
|
||||
public static boolean isDurable(ClientCache clientCache) {
|
||||
|
||||
DistributedSystem distributedSystem = getDistributedSystem(clientCache);
|
||||
|
||||
// NOTE technically the following code snippet would be more useful/valuable but is not "testable"!
|
||||
@@ -75,6 +79,7 @@ public abstract class CacheUtils extends DistributedSystemUtils {
|
||||
/* (non-Javadoc) */
|
||||
@SuppressWarnings("all")
|
||||
public static boolean isPeer(GemFireCache cache) {
|
||||
|
||||
boolean peer = (cache instanceof Cache);
|
||||
|
||||
if (cache instanceof GemFireCacheImpl) {
|
||||
@@ -128,7 +133,7 @@ public abstract class CacheUtils extends DistributedSystemUtils {
|
||||
|
||||
/* (non-Javadoc) */
|
||||
public static GemFireCache resolveGemFireCache() {
|
||||
return defaultIfNull(getCache(), CacheUtils::getClientCache);
|
||||
return Optional.<GemFireCache>ofNullable(getCache()).orElseGet(CacheUtils::getClientCache);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
|
||||
@@ -16,12 +16,10 @@
|
||||
|
||||
package org.springframework.data.gemfire;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.hamcrest.Matchers.sameInstance;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
@@ -58,11 +56,13 @@ import org.apache.geode.cache.control.ResourceManager;
|
||||
import org.apache.geode.cache.util.GatewayConflictResolver;
|
||||
import org.apache.geode.distributed.DistributedMember;
|
||||
import org.apache.geode.distributed.DistributedSystem;
|
||||
import org.apache.geode.distributed.Role;
|
||||
import org.apache.geode.pdx.PdxSerializer;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.data.gemfire.support.GemfireBeanFactoryLocator;
|
||||
@@ -74,13 +74,27 @@ import org.springframework.data.util.ReflectionUtils;
|
||||
* @author John Blum
|
||||
* @see org.junit.Rule
|
||||
* @see org.junit.Test
|
||||
* @see org.junit.runner.RunWith
|
||||
* @see org.mockito.Mock
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.springframework.data.gemfire.CacheFactoryBean
|
||||
* @see org.mockito.junit.MockitoJUnitRunner
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see org.apache.geode.cache.CacheFactory
|
||||
* @see org.apache.geode.cache.CacheTransactionManager
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.distributed.DistributedMember
|
||||
* @see org.apache.geode.distributed.DistributedSystem
|
||||
* @see org.apache.geode.pdx.PdxSerializer
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see org.springframework.data.gemfire.CacheFactoryBean
|
||||
* @since 1.7.0
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class CacheFactoryBeanTest {
|
||||
|
||||
@Mock
|
||||
private Cache mockCache;
|
||||
|
||||
@Rule
|
||||
public ExpectedException exception = ExpectedException.none();
|
||||
|
||||
@@ -90,7 +104,9 @@ public class CacheFactoryBeanTest {
|
||||
final Properties gemfireProperties = new Properties();
|
||||
|
||||
CacheFactoryBean cacheFactoryBean = new CacheFactoryBean() {
|
||||
@Override protected void postProcessBeforeCacheInitialization(Properties actualGemfireProperties) {
|
||||
|
||||
@Override
|
||||
protected void postProcessBeforeCacheInitialization(Properties actualGemfireProperties) {
|
||||
assertThat(actualGemfireProperties, is(sameInstance(gemfireProperties)));
|
||||
postProcessBeforeCacheInitializationCalled.set(true);
|
||||
}
|
||||
@@ -178,7 +194,7 @@ public class CacheFactoryBeanTest {
|
||||
final AtomicBoolean initCalled = new AtomicBoolean(false);
|
||||
|
||||
CacheFactoryBean cacheFactoryBean = new CacheFactoryBean() {
|
||||
@Override Cache init() throws Exception {
|
||||
@Override Cache init() {
|
||||
initCalled.set(true);
|
||||
return mockCache;
|
||||
}
|
||||
@@ -203,6 +219,7 @@ public class CacheFactoryBeanTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation")
|
||||
public void init() throws Exception {
|
||||
BeanFactory mockBeanFactory = mock(BeanFactory.class);
|
||||
Cache mockCache = mock(Cache.class);
|
||||
@@ -227,8 +244,8 @@ public class CacheFactoryBeanTest {
|
||||
when(mockDistributedSystem.getDistributedMember()).thenReturn(mockDistributedMember);
|
||||
when(mockDistributedSystem.getName()).thenReturn("MockDistributedSystem");
|
||||
when(mockDistributedMember.getId()).thenReturn("MockDistributedMember");
|
||||
when(mockDistributedMember.getGroups()).thenReturn(Collections.<String>emptyList());
|
||||
when(mockDistributedMember.getRoles()).thenReturn(Collections.<Role>emptySet());
|
||||
when(mockDistributedMember.getGroups()).thenReturn(Collections.emptyList());
|
||||
when(mockDistributedMember.getRoles()).thenReturn(Collections.emptySet());
|
||||
when(mockDistributedMember.getHost()).thenReturn("skullbox");
|
||||
when(mockDistributedMember.getProcessId()).thenReturn(12345);
|
||||
|
||||
@@ -401,8 +418,7 @@ public class CacheFactoryBeanTest {
|
||||
public void prepareFactoryWithUnspecifiedPdxOptions() {
|
||||
CacheFactory mockCacheFactory = mock(CacheFactory.class);
|
||||
|
||||
assertThat((CacheFactory) new CacheFactoryBean().prepareFactory(mockCacheFactory),
|
||||
is(sameInstance(mockCacheFactory)));
|
||||
assertThat(new CacheFactoryBean().prepareFactory(mockCacheFactory), is(sameInstance(mockCacheFactory)));
|
||||
|
||||
verify(mockCacheFactory, never()).setPdxDiskStore(any(String.class));
|
||||
verify(mockCacheFactory, never()).setPdxIgnoreUnreadFields(any(Boolean.class));
|
||||
@@ -421,8 +437,7 @@ public class CacheFactoryBeanTest {
|
||||
|
||||
CacheFactory mockCacheFactory = mock(CacheFactory.class);
|
||||
|
||||
assertThat((CacheFactory) cacheFactoryBean.prepareFactory(mockCacheFactory),
|
||||
is(sameInstance(mockCacheFactory)));
|
||||
assertThat(cacheFactoryBean.prepareFactory(mockCacheFactory), is(sameInstance(mockCacheFactory)));
|
||||
|
||||
verify(mockCacheFactory, never()).setPdxDiskStore(any(String.class));
|
||||
verify(mockCacheFactory, times(1)).setPdxIgnoreUnreadFields(eq(false));
|
||||
@@ -443,8 +458,7 @@ public class CacheFactoryBeanTest {
|
||||
|
||||
CacheFactory mockCacheFactory = mock(CacheFactory.class);
|
||||
|
||||
assertThat((CacheFactory) cacheFactoryBean.prepareFactory(mockCacheFactory),
|
||||
is(sameInstance(mockCacheFactory)));
|
||||
assertThat(cacheFactoryBean.prepareFactory(mockCacheFactory), is(sameInstance(mockCacheFactory)));
|
||||
|
||||
verify(mockCacheFactory, times(1)).setPdxDiskStore(eq("testPdxDiskStoreName"));
|
||||
verify(mockCacheFactory, times(1)).setPdxIgnoreUnreadFields(eq(false));
|
||||
@@ -453,52 +467,25 @@ public class CacheFactoryBeanTest {
|
||||
verify(mockCacheFactory, times(1)).setPdxSerializer(any(PdxSerializer.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void prepareFactoryWithInvalidTypeForPdxSerializer() {
|
||||
CacheFactory mockCacheFactory = mock(CacheFactory.class);
|
||||
|
||||
Object pdxSerializer = new Object();
|
||||
|
||||
try {
|
||||
CacheFactoryBean cacheFactoryBean = new CacheFactoryBean();
|
||||
|
||||
cacheFactoryBean.setPdxSerializer(pdxSerializer);
|
||||
cacheFactoryBean.setPdxIgnoreUnreadFields(false);
|
||||
cacheFactoryBean.setPdxReadSerialized(true);
|
||||
|
||||
exception.expect(IllegalArgumentException.class);
|
||||
exception.expectCause(is(nullValue(Throwable.class)));
|
||||
exception.expectMessage(containsString(String.format(
|
||||
"[%1$s] of type [java.lang.Object] is not a PdxSerializer", pdxSerializer)));
|
||||
|
||||
cacheFactoryBean.prepareFactory(mockCacheFactory);
|
||||
}
|
||||
finally {
|
||||
verify(mockCacheFactory, never()).setPdxSerializer(any(PdxSerializer.class));
|
||||
verify(mockCacheFactory, never()).setPdxDiskStore(any(String.class));
|
||||
verify(mockCacheFactory, never()).setPdxIgnoreUnreadFields(any(Boolean.class));
|
||||
verify(mockCacheFactory, never()).setPdxPersistent(any(Boolean.class));
|
||||
verify(mockCacheFactory, never()).setPdxReadSerialized(any(Boolean.class));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createCacheWithExistingCache() throws Exception {
|
||||
Cache mockCache = mock(Cache.class);
|
||||
CacheFactory mockCacheFactory = mock(CacheFactory.class);
|
||||
CacheFactoryBean cacheFactoryBean = new CacheFactoryBean();
|
||||
|
||||
cacheFactoryBean.setCache(mockCache);
|
||||
|
||||
Cache actualCache = cacheFactoryBean.createCache(null);
|
||||
assertThat(cacheFactoryBean.getCache(), is(sameInstance(mockCache)));
|
||||
|
||||
Cache actualCache = cacheFactoryBean.createCache(mockCacheFactory);
|
||||
|
||||
assertThat(actualCache, is(sameInstance(mockCache)));
|
||||
|
||||
verify(mockCacheFactory, never()).create();
|
||||
verifyZeroInteractions(mockCache);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createCacheWithNoExistingCache() {
|
||||
Cache mockCache = mock(Cache.class);
|
||||
CacheFactory mockCacheFactory = mock(CacheFactory.class);
|
||||
|
||||
when(mockCacheFactory.create()).thenReturn(mockCache);
|
||||
@@ -519,13 +506,17 @@ public class CacheFactoryBeanTest {
|
||||
CacheFactoryBean cacheFactoryBean = new CacheFactoryBean();
|
||||
|
||||
cacheFactoryBean.setCriticalHeapPercentage(200.0f);
|
||||
cacheFactoryBean.postProcess(null);
|
||||
cacheFactoryBean.postProcess(mockCache);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
assertEquals("'criticalHeapPercentage' (200.0) is invalid; must be > 0.0 and <= 100.0",
|
||||
assertEquals("criticalHeapPercentage [200.0] is not valid; must be > 0.0 and <= 100.0",
|
||||
expected.getMessage());
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verifyZeroInteractions(mockCache);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@@ -534,19 +525,23 @@ public class CacheFactoryBeanTest {
|
||||
CacheFactoryBean cacheFactoryBean = new CacheFactoryBean();
|
||||
|
||||
cacheFactoryBean.setEvictionHeapPercentage(-75.0f);
|
||||
cacheFactoryBean.postProcess(null);
|
||||
cacheFactoryBean.postProcess(mockCache);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
assertEquals("'evictionHeapPercentage' (-75.0) is invalid; must be > 0.0 and <= 100.0",
|
||||
assertEquals("evictionHeapPercentage [-75.0] is not valid; must be > 0.0 and <= 100.0",
|
||||
expected.getMessage());
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verifyZeroInteractions(mockCache);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void getObjectType() {
|
||||
assertThat((Class<Cache>) new CacheFactoryBean().getObjectType(), is(equalTo(Cache.class)));
|
||||
assertThat(new CacheFactoryBean().getObjectType(), is(equalTo(Cache.class)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -695,10 +690,10 @@ public class CacheFactoryBeanTest {
|
||||
assertTrue(Boolean.FALSE.equals(TestUtils.readField("useBeanFactoryLocator", cacheFactoryBean)));
|
||||
assertTrue(Boolean.FALSE.equals(TestUtils.readField("close", cacheFactoryBean)));
|
||||
assertTrue(cacheFactoryBean.getCopyOnRead());
|
||||
assertEquals(0.95f, cacheFactoryBean.getCriticalHeapPercentage().floatValue(), 0.0f);
|
||||
assertEquals(0.95f, cacheFactoryBean.getCriticalHeapPercentage(), 0.0f);
|
||||
assertNotNull(cacheFactoryBean.getDynamicRegionSupport());
|
||||
assertTrue(cacheFactoryBean.getEnableAutoReconnect());
|
||||
assertEquals(0.70f, cacheFactoryBean.getEvictionHeapPercentage().floatValue(), 0.0f);
|
||||
assertEquals(0.70f, cacheFactoryBean.getEvictionHeapPercentage(), 0.0f);
|
||||
assertSame(mockGatewayConflictResolver, cacheFactoryBean.getGatewayConflictResolver());
|
||||
assertNotNull(cacheFactoryBean.getJndiDataSources());
|
||||
assertEquals(1, cacheFactoryBean.getJndiDataSources().size());
|
||||
|
||||
@@ -22,11 +22,11 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* The DiskStoreFactoryBeanTest class is a test suite of test cases testing the contract and functionality of the
|
||||
* DiskStoreFactoryBean class.
|
||||
* Unit tests for {@link DiskStoreFactoryBean}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.apache.geode.cache.DiskStore
|
||||
* @see org.springframework.data.gemfire.DiskStoreFactoryBean
|
||||
* @since 1.3.4
|
||||
*/
|
||||
@@ -58,7 +58,7 @@ public class DiskStoreFactoryBeanTest {
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
assertEquals(String.format("The DiskStore's (%1$s) compaction threshold (%2$d) must be an integer value between 0 and 100 inclusive.",
|
||||
factoryBean.getName(), -1), expected.getMessage());
|
||||
factoryBean.resolveDiskStoreName(), -1), expected.getMessage());
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
@@ -70,7 +70,7 @@ public class DiskStoreFactoryBeanTest {
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
assertEquals(String.format("The DiskStore's (%1$s) compaction threshold (%2$d) must be an integer value between 0 and 100 inclusive.",
|
||||
factoryBean.getName(), 101), expected.getMessage());
|
||||
factoryBean.resolveDiskStoreName(), 101), expected.getMessage());
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
@@ -88,7 +88,7 @@ public class DiskStoreFactoryBeanTest {
|
||||
catch (IllegalArgumentException expected) {
|
||||
assertEquals(String.format(
|
||||
"The DiskStore's (%1$s) compaction threshold (%2$d) must be an integer value between 0 and 100 inclusive.",
|
||||
factoryBean.getName(), 200), expected.getMessage());
|
||||
factoryBean.resolveDiskStoreName(), 200), expected.getMessage());
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
@@ -99,9 +99,8 @@ public class DiskStoreFactoryBeanTest {
|
||||
factoryBean.afterPropertiesSet();
|
||||
}
|
||||
catch (IllegalStateException expected) {
|
||||
assertEquals("A reference to the GemFire Cache must be set for Disk Store 'testDiskStore'.", expected.getMessage());
|
||||
assertEquals("Cache is required to create DiskStore [testDiskStore]", expected.getMessage());
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,10 +22,24 @@ import static org.hamcrest.CoreMatchers.isA;
|
||||
import static org.hamcrest.CoreMatchers.nullValue;
|
||||
import static org.hamcrest.CoreMatchers.sameInstance;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.same;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -55,16 +69,14 @@ import org.springframework.data.gemfire.config.xml.GemfireConstants;
|
||||
import org.springframework.data.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* The IndexFactoryBeanTest class is a test suite of test cases testing the contract and functionality
|
||||
* of the IndexFactoryBean class.
|
||||
* Unit tests for {@link IndexFactoryBean}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.springframework.data.gemfire.IndexFactoryBean
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @see org.apache.geode.cache.query.Index
|
||||
* @see org.apache.geode.cache.query.QueryService
|
||||
* @see org.springframework.data.gemfire.IndexFactoryBean
|
||||
* @since 1.5.2
|
||||
*/
|
||||
public class IndexFactoryBeanTest {
|
||||
@@ -136,10 +148,12 @@ public class IndexFactoryBeanTest {
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void afterPropertiesSetWithNullCache() throws Exception {
|
||||
try {
|
||||
new IndexFactoryBean().afterPropertiesSet();
|
||||
IndexFactoryBean indexFactoryBean = new IndexFactoryBean();
|
||||
indexFactoryBean.setName("TestIndex");
|
||||
indexFactoryBean.afterPropertiesSet();
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
assertEquals("The GemFire Cache reference must not be null!", expected.getMessage());
|
||||
assertEquals("Cache is required", expected.getMessage());
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
@@ -154,6 +168,7 @@ public class IndexFactoryBeanTest {
|
||||
};
|
||||
|
||||
indexFactoryBean.setCache(mockCache);
|
||||
indexFactoryBean.setName("TestIndex");
|
||||
indexFactoryBean.afterPropertiesSet();
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
@@ -165,10 +180,12 @@ public class IndexFactoryBeanTest {
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void afterPropertiesSetWithUnspecifiedExpression() throws Exception {
|
||||
try {
|
||||
newIndexFactoryBean().afterPropertiesSet();
|
||||
IndexFactoryBean indexFactoryBean = newIndexFactoryBean();
|
||||
indexFactoryBean.setName("TestIndex");
|
||||
indexFactoryBean.afterPropertiesSet();
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
assertEquals("Index 'expression' is required", expected.getMessage());
|
||||
assertEquals("Index expression is required", expected.getMessage());
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
@@ -177,11 +194,12 @@ public class IndexFactoryBeanTest {
|
||||
public void afterPropertiesSetWithUnspecifiedFromClause() throws Exception {
|
||||
expectedException.expect(IllegalArgumentException.class);
|
||||
expectedException.expectCause(is(nullValue(Throwable.class)));
|
||||
expectedException.expectMessage("Index 'from clause' is required");
|
||||
expectedException.expectMessage("Index from clause is required");
|
||||
|
||||
IndexFactoryBean indexFactoryBean = newIndexFactoryBean();
|
||||
|
||||
indexFactoryBean.setExpression("id");
|
||||
indexFactoryBean.setName("TestIndex");
|
||||
indexFactoryBean.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@@ -194,7 +212,7 @@ public class IndexFactoryBeanTest {
|
||||
indexFactoryBean.afterPropertiesSet();
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
assertEquals("Index 'name' is required", expected.getMessage());
|
||||
assertEquals("Index name is required", expected.getMessage());
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
@@ -211,7 +229,7 @@ public class IndexFactoryBeanTest {
|
||||
indexFactoryBean.afterPropertiesSet();
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
assertEquals("'imports' are not supported with a KEY Index", expected.getMessage());
|
||||
assertEquals("imports are not supported with a KEY Index", expected.getMessage());
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
@@ -1076,5 +1094,4 @@ public class IndexFactoryBeanTest {
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -169,7 +169,7 @@ public class PartitionedRegionFactoryBeanTest {
|
||||
factoryBean.resolveDataPolicy(mockRegionFactory, true, "PARTITION");
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
assertEquals("Data Policy 'PARTITION' is invalid when persistent is true.", e.getMessage());
|
||||
assertEquals("Data Policy [PARTITION] is invalid when persistent is true.", e.getMessage());
|
||||
throw e;
|
||||
}
|
||||
finally {
|
||||
@@ -195,7 +195,7 @@ public class PartitionedRegionFactoryBeanTest {
|
||||
factoryBean.resolveDataPolicy(mockRegionFactory, false, "PERSISTENT_PARTITION");
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
assertEquals("Data Policy 'PERSISTENT_PARTITION' is invalid when persistent is false.", e.getMessage());
|
||||
assertEquals("Data Policy [PERSISTENT_PARTITION] is invalid when persistent is false.", e.getMessage());
|
||||
throw e;
|
||||
}
|
||||
finally {
|
||||
@@ -212,5 +212,4 @@ public class PartitionedRegionFactoryBeanTest {
|
||||
factoryBean.resolveDataPolicy(mockRegionFactory, true, "PERSISTENT_PARTITION");
|
||||
verify(mockRegionFactory).setDataPolicy(eq(DataPolicy.PERSISTENT_PARTITION));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -54,12 +54,10 @@ import org.springframework.data.gemfire.test.support.AbstractRegionFactoryBeanTe
|
||||
import org.springframework.data.gemfire.util.ArrayUtils;
|
||||
|
||||
/**
|
||||
* The RegionFactoryBeanTest class is a test suite of test cases testing the contract and functionality of the
|
||||
* RegionFactoryBean class.
|
||||
* Unit tests for {@link RegionFactoryBean}.
|
||||
*
|
||||
* @author David Turanski
|
||||
* @author John Blum
|
||||
* @see org.springframework.data.gemfire.RegionFactoryBean
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see org.apache.geode.cache.DataPolicy
|
||||
* @see org.apache.geode.cache.PartitionAttributes
|
||||
@@ -67,6 +65,8 @@ import org.springframework.data.gemfire.util.ArrayUtils;
|
||||
* @see org.apache.geode.cache.RegionAttributes
|
||||
* @see org.apache.geode.cache.RegionFactory
|
||||
* @see org.apache.geode.cache.RegionShortcut
|
||||
* @see org.springframework.data.gemfire.RegionFactoryBean
|
||||
* @see org.springframework.data.gemfire.test.support.AbstractRegionFactoryBeanTests
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class RegionFactoryBeanTest extends AbstractRegionFactoryBeanTests {
|
||||
@@ -122,7 +122,7 @@ public class RegionFactoryBeanTest extends AbstractRegionFactoryBeanTests {
|
||||
@Override
|
||||
public void verify() {
|
||||
assertNotNull(this.exception);
|
||||
assertEquals("Data Policy 'PERSISTENT_REPLICATE' is invalid when persistent is false.",
|
||||
assertEquals("Data Policy [PERSISTENT_REPLICATE] is invalid when persistent is false.",
|
||||
exception.getMessage());
|
||||
}
|
||||
};
|
||||
@@ -191,7 +191,7 @@ public class RegionFactoryBeanTest extends AbstractRegionFactoryBeanTests {
|
||||
factoryBean.assertDataPolicyAndPersistentAttributesAreCompatible(DataPolicy.REPLICATE);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
assertEquals("Data Policy 'REPLICATE' is invalid when persistent is true.", expected.getMessage());
|
||||
assertEquals("Data Policy [REPLICATE] is invalid when persistent is true.", expected.getMessage());
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
@@ -204,7 +204,7 @@ public class RegionFactoryBeanTest extends AbstractRegionFactoryBeanTests {
|
||||
factoryBean.assertDataPolicyAndPersistentAttributesAreCompatible(DataPolicy.PERSISTENT_PARTITION);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
assertEquals("Data Policy 'PERSISTENT_PARTITION' is invalid when persistent is false.",
|
||||
assertEquals("Data Policy [PERSISTENT_PARTITION] is invalid when persistent is false.",
|
||||
expected.getMessage());
|
||||
throw expected;
|
||||
}
|
||||
@@ -715,7 +715,7 @@ public class RegionFactoryBeanTest extends AbstractRegionFactoryBeanTests {
|
||||
factoryBean.resolveDataPolicy(mockRegionFactory, true, " ");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
assertEquals("Data Policy ' ' is invalid.", expected.getMessage());
|
||||
assertEquals("Data Policy [ ] is invalid.", expected.getMessage());
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
@@ -734,7 +734,7 @@ public class RegionFactoryBeanTest extends AbstractRegionFactoryBeanTests {
|
||||
factoryBean.resolveDataPolicy(mockRegionFactory, true, "");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
assertEquals("Data Policy '' is invalid.", expected.getMessage());
|
||||
assertEquals("Data Policy [] is invalid.", expected.getMessage());
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
@@ -753,7 +753,7 @@ public class RegionFactoryBeanTest extends AbstractRegionFactoryBeanTests {
|
||||
factoryBean.resolveDataPolicy(mockRegionFactory, true, "CSV");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
assertEquals("Data Policy 'CSV' is invalid.", expected.getMessage());
|
||||
assertEquals("Data Policy [CSV] is invalid.", expected.getMessage());
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
@@ -787,7 +787,7 @@ public class RegionFactoryBeanTest extends AbstractRegionFactoryBeanTests {
|
||||
factoryBean.resolveDataPolicy(mockRegionFactory, true, "EMPTY");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
assertEquals("Data Policy 'EMPTY' is invalid when persistent is true.", expected.getMessage());
|
||||
assertEquals("Data Policy [EMPTY] is invalid when persistent is true.", expected.getMessage());
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
@@ -821,7 +821,7 @@ public class RegionFactoryBeanTest extends AbstractRegionFactoryBeanTests {
|
||||
factoryBean.resolveDataPolicy(mockRegionFactory, false, "PERSISTENT_PARTITION");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
assertEquals("Data Policy 'PERSISTENT_PARTITION' is invalid when persistent is false.", expected.getMessage());
|
||||
assertEquals("Data Policy [PERSISTENT_PARTITION] is invalid when persistent is false.", expected.getMessage());
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
@@ -843,7 +843,7 @@ public class RegionFactoryBeanTest extends AbstractRegionFactoryBeanTests {
|
||||
"Setting the 'persistent' attribute to TRUE and 'Data Policy' to PARTITION should have thrown an IllegalArgumentException!");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
assertEquals("Data Policy 'PARTITION' is invalid when persistent is true.", expected.getMessage());
|
||||
assertEquals("Data Policy [PARTITION] is invalid when persistent is true.", expected.getMessage());
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
@@ -913,7 +913,7 @@ public class RegionFactoryBeanTest extends AbstractRegionFactoryBeanTests {
|
||||
factoryBean.resolveDataPolicy(mockRegionFactory, false, (String) null);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
assertEquals("Data Policy 'PERSISTENT_PARTITION' is invalid when persistent is false.", expected.getMessage());
|
||||
assertEquals("Data Policy [PERSISTENT_PARTITION] is invalid when persistent is false.", expected.getMessage());
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
@@ -934,7 +934,7 @@ public class RegionFactoryBeanTest extends AbstractRegionFactoryBeanTests {
|
||||
factoryBean.resolveDataPolicy(mockRegionFactory, true, (String) null);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
assertEquals("Data Policy 'PARTITION' is invalid when persistent is true.", expected.getMessage());
|
||||
assertEquals("Data Policy [PARTITION] is invalid when persistent is true.", expected.getMessage());
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
@@ -996,7 +996,7 @@ public class RegionFactoryBeanTest extends AbstractRegionFactoryBeanTests {
|
||||
fail("Setting the 'persistent' attribute to FALSE and 'Data Policy' to PERSISTENT_REPLICATE should have thrown an IllegalArgumentException!");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
assertEquals("Data Policy 'PERSISTENT_REPLICATE' is invalid when persistent is false.", expected.getMessage());
|
||||
assertEquals("Data Policy [PERSISTENT_REPLICATE] is invalid when persistent is false.", expected.getMessage());
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
@@ -1017,7 +1017,7 @@ public class RegionFactoryBeanTest extends AbstractRegionFactoryBeanTests {
|
||||
fail("Setting the 'persistent' attribute to TRUE and 'Data Policy' to REPLICATE should have thrown an IllegalArgumentException!");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
assertEquals("Data Policy 'REPLICATE' is invalid when persistent is true.", expected.getMessage());
|
||||
assertEquals("Data Policy [REPLICATE] is invalid when persistent is true.", expected.getMessage());
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
|
||||
@@ -168,7 +168,7 @@ public class ReplicatedRegionFactoryBeanTest {
|
||||
factoryBean.resolveDataPolicy(mockRegionFactory, true, "empty");
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
assertEquals("Data Policy 'EMPTY' is invalid when persistent is true.", e.getMessage());
|
||||
assertEquals("Data Policy [EMPTY] is invalid when persistent is true.", e.getMessage());
|
||||
throw e;
|
||||
}
|
||||
finally {
|
||||
@@ -202,7 +202,7 @@ public class ReplicatedRegionFactoryBeanTest {
|
||||
factoryBean.resolveDataPolicy(mockRegionFactory, true, "REPLICATE");
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
assertEquals("Data Policy 'REPLICATE' is invalid when persistent is true.", e.getMessage());
|
||||
assertEquals("Data Policy [REPLICATE] is invalid when persistent is true.", e.getMessage());
|
||||
throw e;
|
||||
}
|
||||
finally {
|
||||
@@ -228,7 +228,7 @@ public class ReplicatedRegionFactoryBeanTest {
|
||||
factoryBean.resolveDataPolicy(mockRegionFactory, false, "PERSISTENT_REPLICATE");
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
assertEquals("Data Policy 'PERSISTENT_REPLICATE' is invalid when persistent is false.", e.getMessage());
|
||||
assertEquals("Data Policy [PERSISTENT_REPLICATE] is invalid when persistent is false.", e.getMessage());
|
||||
throw e;
|
||||
}
|
||||
finally {
|
||||
@@ -245,5 +245,4 @@ public class ReplicatedRegionFactoryBeanTest {
|
||||
factoryBean.resolveDataPolicy(mockRegionFactory, true, "PERSISTENT_REPLICATE");
|
||||
verify(mockRegionFactory).setDataPolicy(eq(DataPolicy.PERSISTENT_REPLICATE));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.data.gemfire.client;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
@@ -42,6 +41,7 @@ import java.net.InetSocketAddress;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
@@ -65,15 +65,21 @@ import org.springframework.data.gemfire.util.ArrayUtils;
|
||||
import org.springframework.data.gemfire.util.DistributedSystemUtils;
|
||||
|
||||
/**
|
||||
* The ClientCacheFactoryBeanTest class is a test suite of test cases testing the contract and functionality
|
||||
* of the SDG ClientCacheFactoryBean class.
|
||||
* Unit tests for {@link ClientCacheFactoryBean}
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.mockito.Mockito
|
||||
* @see java.net.InetSocketAddress
|
||||
* @see org.junit.Rule
|
||||
* @see org.junit.Test
|
||||
* @see org.springframework.data.gemfire.client.ClientCacheFactoryBean
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @see org.apache.geode.cache.client.ClientCacheFactory
|
||||
* @see org.apache.geode.cache.client.Pool
|
||||
* @see org.apache.geode.distributed.DistributedSystem
|
||||
* @see org.apache.geode.pdx.PdxSerializer
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see org.springframework.data.gemfire.client.ClientCacheFactoryBean
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public class ClientCacheFactoryBeanTest {
|
||||
@@ -81,24 +87,25 @@ public class ClientCacheFactoryBeanTest {
|
||||
@Rule
|
||||
public ExpectedException exception = ExpectedException.none();
|
||||
|
||||
protected Properties createProperties(String key, String value) {
|
||||
private Properties createProperties(String key, String value) {
|
||||
return addProperty(null, key, value);
|
||||
}
|
||||
|
||||
protected Properties addProperty(Properties properties, String key, String value) {
|
||||
properties = (properties != null ? properties : new Properties());
|
||||
@SuppressWarnings("all")
|
||||
private Properties addProperty(Properties properties, String key, String value) {
|
||||
properties = Optional.ofNullable(properties).orElseGet(Properties::new);
|
||||
properties.setProperty(key, value);
|
||||
return properties;
|
||||
}
|
||||
|
||||
protected ConnectionEndpoint newConnectionEndpoint(String host, int port) {
|
||||
private ConnectionEndpoint newConnectionEndpoint(String host, int port) {
|
||||
return new ConnectionEndpoint(host, port);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void getObjectType() {
|
||||
assertThat((Class<ClientCache>) new ClientCacheFactoryBean().getObjectType(), is(equalTo(ClientCache.class)));
|
||||
assertThat(new ClientCacheFactoryBean().getObjectType(), is(equalTo(ClientCache.class)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -252,18 +259,21 @@ public class ClientCacheFactoryBeanTest {
|
||||
ClientCacheFactory mockClientCacheFactory = mock(ClientCacheFactory.class);
|
||||
|
||||
ClientCacheFactoryBean clientCacheFactoryBean = new ClientCacheFactoryBean() {
|
||||
@Override ClientCacheFactory initializePdx(final ClientCacheFactory clientCacheFactory) {
|
||||
|
||||
@Override
|
||||
ClientCacheFactory initializePdx(ClientCacheFactory clientCacheFactory) {
|
||||
initializePdxCalled.set(true);
|
||||
return clientCacheFactory;
|
||||
}
|
||||
|
||||
@Override ClientCacheFactory initializePool(final ClientCacheFactory clientCacheFactory) {
|
||||
@Override
|
||||
ClientCacheFactory initializePool(final ClientCacheFactory clientCacheFactory) {
|
||||
initializePoolCalled.set(true);
|
||||
return clientCacheFactory;
|
||||
}
|
||||
};
|
||||
|
||||
assertThat((ClientCacheFactory) clientCacheFactoryBean.prepareFactory(mockClientCacheFactory),
|
||||
assertThat(clientCacheFactoryBean.prepareFactory(mockClientCacheFactory),
|
||||
is(sameInstance(mockClientCacheFactory)));
|
||||
assertThat(initializePdxCalled.get(), is(true));
|
||||
assertThat(initializePoolCalled.get(), is(true));
|
||||
@@ -285,7 +295,7 @@ public class ClientCacheFactoryBeanTest {
|
||||
assertThat(clientCacheFactoryBean.getPdxIgnoreUnreadFields(), is(false));
|
||||
assertThat(clientCacheFactoryBean.getPdxPersistent(), is(true));
|
||||
assertThat(clientCacheFactoryBean.getPdxReadSerialized(), is(false));
|
||||
assertThat((PdxSerializer) clientCacheFactoryBean.getPdxSerializer(), is(sameInstance(mockPdxSerializer)));
|
||||
assertThat(clientCacheFactoryBean.getPdxSerializer(), is(sameInstance(mockPdxSerializer)));
|
||||
|
||||
ClientCacheFactory mockClientCacheFactory = mock(ClientCacheFactory.class);
|
||||
|
||||
@@ -342,51 +352,19 @@ public class ClientCacheFactoryBeanTest {
|
||||
verifyZeroInteractions(mockClientCacheFactory);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void initializePdxUsingIllegalTypeForPdxSerializer() {
|
||||
ClientCacheFactory mockClientCacheFactory = mock(ClientCacheFactory.class);
|
||||
|
||||
try {
|
||||
ClientCacheFactoryBean clientCacheFactoryBean = new ClientCacheFactoryBean();
|
||||
|
||||
Object pdxSerializer = new Object();
|
||||
|
||||
clientCacheFactoryBean.setPdxSerializer(pdxSerializer);
|
||||
clientCacheFactoryBean.setPdxReadSerialized(false);
|
||||
clientCacheFactoryBean.setPdxPersistent(true);
|
||||
clientCacheFactoryBean.setPdxIgnoreUnreadFields(false);
|
||||
clientCacheFactoryBean.setPdxDiskStoreName("test");
|
||||
|
||||
exception.expect(IllegalArgumentException.class);
|
||||
exception.expectCause(is(nullValue(Throwable.class)));
|
||||
exception.expectMessage(containsString(String.format(
|
||||
"[%1$s] of type [java.lang.Object] is not a PdxSerializer", pdxSerializer)));
|
||||
|
||||
assertThat(clientCacheFactoryBean.initializePdx(mockClientCacheFactory),
|
||||
is(sameInstance(mockClientCacheFactory)));
|
||||
}
|
||||
finally {
|
||||
verify(mockClientCacheFactory, never()).setPdxSerializer(any(PdxSerializer.class));
|
||||
verify(mockClientCacheFactory, never()).setPdxDiskStore(any(String.class));
|
||||
verify(mockClientCacheFactory, never()).setPdxIgnoreUnreadFields(any(Boolean.class));
|
||||
verify(mockClientCacheFactory, never()).setPdxPersistent(any(Boolean.class));
|
||||
verify(mockClientCacheFactory, never()).setPdxReadSerialized(any(Boolean.class));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void initializePoolWithPool() {
|
||||
Pool mockPool = mock(Pool.class);
|
||||
|
||||
when(mockPool.getFreeConnectionTimeout()).thenReturn(10000);
|
||||
when(mockPool.getIdleTimeout()).thenReturn(120000l);
|
||||
when(mockPool.getIdleTimeout()).thenReturn(120000L);
|
||||
when(mockPool.getLoadConditioningInterval()).thenReturn(30000);
|
||||
when(mockPool.getLocators()).thenReturn(Collections.<InetSocketAddress>emptyList());
|
||||
when(mockPool.getLocators()).thenReturn(Collections.emptyList());
|
||||
when(mockPool.getMaxConnections()).thenReturn(100);
|
||||
when(mockPool.getMinConnections()).thenReturn(10);
|
||||
when(mockPool.getMultiuserAuthentication()).thenReturn(true);
|
||||
when(mockPool.getPRSingleHopEnabled()).thenReturn(true);
|
||||
when(mockPool.getPingInterval()).thenReturn(15000l);
|
||||
when(mockPool.getPingInterval()).thenReturn(15000L);
|
||||
when(mockPool.getReadTimeout()).thenReturn(20000);
|
||||
when(mockPool.getRetryAttempts()).thenReturn(1);
|
||||
when(mockPool.getServerGroup()).thenReturn("TestGroup");
|
||||
@@ -453,13 +431,13 @@ public class ClientCacheFactoryBeanTest {
|
||||
verify(mockPool, times(1)).getSubscriptionRedundancy();
|
||||
verify(mockPool, times(1)).getThreadLocalConnections();
|
||||
verify(mockClientCacheFactory, times(1)).setPoolFreeConnectionTimeout(eq(10000));
|
||||
verify(mockClientCacheFactory, times(1)).setPoolIdleTimeout(eq(120000l));
|
||||
verify(mockClientCacheFactory, times(1)).setPoolIdleTimeout(eq(120000L));
|
||||
verify(mockClientCacheFactory, times(1)).setPoolLoadConditioningInterval(eq(30000));
|
||||
verify(mockClientCacheFactory, times(1)).setPoolMaxConnections(eq(100));
|
||||
verify(mockClientCacheFactory, times(1)).setPoolMinConnections(eq(10));
|
||||
verify(mockClientCacheFactory, times(1)).setPoolMultiuserAuthentication(eq(true));
|
||||
verify(mockClientCacheFactory, times(1)).setPoolPRSingleHopEnabled(eq(true));
|
||||
verify(mockClientCacheFactory, times(1)).setPoolPingInterval(eq(15000l));
|
||||
verify(mockClientCacheFactory, times(1)).setPoolPingInterval(eq(15000L));
|
||||
verify(mockClientCacheFactory, times(1)).setPoolReadTimeout(eq(20000));
|
||||
verify(mockClientCacheFactory, times(1)).setPoolRetryAttempts(eq(1));
|
||||
verify(mockClientCacheFactory, times(1)).setPoolServerGroup(eq("TestGroup"));
|
||||
@@ -482,12 +460,12 @@ public class ClientCacheFactoryBeanTest {
|
||||
ClientCacheFactoryBean clientCacheFactoryBean = new ClientCacheFactoryBean();
|
||||
|
||||
clientCacheFactoryBean.setFreeConnectionTimeout(5000);
|
||||
clientCacheFactoryBean.setIdleTimeout(300000l);
|
||||
clientCacheFactoryBean.setIdleTimeout(300000L);
|
||||
clientCacheFactoryBean.setLoadConditioningInterval(120000);
|
||||
clientCacheFactoryBean.setMaxConnections(99);
|
||||
clientCacheFactoryBean.setMinConnections(9);
|
||||
clientCacheFactoryBean.setMultiUserAuthentication(true);
|
||||
clientCacheFactoryBean.setPingInterval(15000l);
|
||||
clientCacheFactoryBean.setPingInterval(15000L);
|
||||
clientCacheFactoryBean.setPool(mockPool);
|
||||
clientCacheFactoryBean.setPrSingleHopEnabled(true);
|
||||
clientCacheFactoryBean.setReadTimeout(20000);
|
||||
@@ -504,13 +482,13 @@ public class ClientCacheFactoryBeanTest {
|
||||
newConnectionEndpoint("skullbox", 10334));
|
||||
|
||||
assertThat(clientCacheFactoryBean.getFreeConnectionTimeout(), is(equalTo(5000)));
|
||||
assertThat(clientCacheFactoryBean.getIdleTimeout(), is(equalTo(300000l)));
|
||||
assertThat(clientCacheFactoryBean.getIdleTimeout(), is(equalTo(300000L)));
|
||||
assertThat(clientCacheFactoryBean.getLoadConditioningInterval(), is(equalTo(120000)));
|
||||
assertThat(clientCacheFactoryBean.getLocators().size(), is(equalTo(2)));
|
||||
assertThat(clientCacheFactoryBean.getMaxConnections(), is(equalTo(99)));
|
||||
assertThat(clientCacheFactoryBean.getMinConnections(), is(equalTo(9)));
|
||||
assertThat(clientCacheFactoryBean.getMultiUserAuthentication(), is(equalTo(true)));
|
||||
assertThat(clientCacheFactoryBean.getPingInterval(), is(equalTo(15000l)));
|
||||
assertThat(clientCacheFactoryBean.getPingInterval(), is(equalTo(15000L)));
|
||||
assertThat(clientCacheFactoryBean.getPool(), is(sameInstance(mockPool)));
|
||||
assertThat(clientCacheFactoryBean.getPoolName(), is(nullValue()));
|
||||
assertThat(clientCacheFactoryBean.getPrSingleHopEnabled(), is(equalTo(true)));
|
||||
@@ -533,12 +511,12 @@ public class ClientCacheFactoryBeanTest {
|
||||
|
||||
verifyZeroInteractions(mockPool);
|
||||
verify(mockClientCacheFactory, times(1)).setPoolFreeConnectionTimeout(eq(5000));
|
||||
verify(mockClientCacheFactory, times(1)).setPoolIdleTimeout(eq(300000l));
|
||||
verify(mockClientCacheFactory, times(1)).setPoolIdleTimeout(eq(300000L));
|
||||
verify(mockClientCacheFactory, times(1)).setPoolLoadConditioningInterval(eq(120000));
|
||||
verify(mockClientCacheFactory, times(1)).setPoolMaxConnections(eq(99));
|
||||
verify(mockClientCacheFactory, times(1)).setPoolMinConnections(eq(9));
|
||||
verify(mockClientCacheFactory, times(1)).setPoolMultiuserAuthentication(eq(true));
|
||||
verify(mockClientCacheFactory, times(1)).setPoolPingInterval(eq(15000l));
|
||||
verify(mockClientCacheFactory, times(1)).setPoolPingInterval(eq(15000L));
|
||||
verify(mockClientCacheFactory, times(1)).setPoolPRSingleHopEnabled(eq(true));
|
||||
verify(mockClientCacheFactory, times(1)).setPoolReadTimeout(eq(20000));
|
||||
verify(mockClientCacheFactory, times(1)).setPoolRetryAttempts(eq(2));
|
||||
@@ -560,13 +538,13 @@ public class ClientCacheFactoryBeanTest {
|
||||
Pool mockPool = mock(Pool.class);
|
||||
|
||||
when(mockPool.getFreeConnectionTimeout()).thenReturn(5000);
|
||||
when(mockPool.getIdleTimeout()).thenReturn(120000l);
|
||||
when(mockPool.getIdleTimeout()).thenReturn(120000L);
|
||||
when(mockPool.getLoadConditioningInterval()).thenReturn(300000);
|
||||
when(mockPool.getLocators()).thenReturn(Collections.<InetSocketAddress>emptyList());
|
||||
when(mockPool.getLocators()).thenReturn(Collections.emptyList());
|
||||
when(mockPool.getMaxConnections()).thenReturn(200);
|
||||
when(mockPool.getMinConnections()).thenReturn(10);
|
||||
when(mockPool.getMultiuserAuthentication()).thenReturn(false);
|
||||
when(mockPool.getPingInterval()).thenReturn(15000l);
|
||||
when(mockPool.getPingInterval()).thenReturn(15000L);
|
||||
when(mockPool.getPRSingleHopEnabled()).thenReturn(false);
|
||||
when(mockPool.getReadTimeout()).thenReturn(30000);
|
||||
when(mockPool.getRetryAttempts()).thenReturn(1);
|
||||
@@ -582,7 +560,7 @@ public class ClientCacheFactoryBeanTest {
|
||||
|
||||
ClientCacheFactoryBean clientCacheFactoryBean = new ClientCacheFactoryBean();
|
||||
|
||||
clientCacheFactoryBean.setIdleTimeout(180000l);
|
||||
clientCacheFactoryBean.setIdleTimeout(180000L);
|
||||
clientCacheFactoryBean.setMaxConnections(500);
|
||||
clientCacheFactoryBean.setMinConnections(50);
|
||||
clientCacheFactoryBean.setMultiUserAuthentication(true);
|
||||
@@ -598,7 +576,7 @@ public class ClientCacheFactoryBeanTest {
|
||||
clientCacheFactoryBean.addLocators(newConnectionEndpoint("localhost", 11235));
|
||||
|
||||
assertThat(clientCacheFactoryBean.getFreeConnectionTimeout(), is(nullValue()));
|
||||
assertThat(clientCacheFactoryBean.getIdleTimeout(), is(equalTo(180000l)));
|
||||
assertThat(clientCacheFactoryBean.getIdleTimeout(), is(equalTo(180000L)));
|
||||
assertThat(clientCacheFactoryBean.getLoadConditioningInterval(), is(nullValue()));
|
||||
assertThat(clientCacheFactoryBean.getLocators().size(), is(equalTo(1)));
|
||||
assertThat(clientCacheFactoryBean.getMaxConnections(), is(equalTo(500)));
|
||||
@@ -646,12 +624,12 @@ public class ClientCacheFactoryBeanTest {
|
||||
verify(mockPool, never()).getSubscriptionRedundancy();
|
||||
verify(mockPool, never()).getThreadLocalConnections();
|
||||
verify(mockClientCacheFactory, times(1)).setPoolFreeConnectionTimeout(eq(5000));
|
||||
verify(mockClientCacheFactory, times(1)).setPoolIdleTimeout(eq(180000l));
|
||||
verify(mockClientCacheFactory, times(1)).setPoolIdleTimeout(eq(180000L));
|
||||
verify(mockClientCacheFactory, times(1)).setPoolLoadConditioningInterval(eq(300000));
|
||||
verify(mockClientCacheFactory, times(1)).setPoolMaxConnections(eq(500));
|
||||
verify(mockClientCacheFactory, times(1)).setPoolMinConnections(eq(50));
|
||||
verify(mockClientCacheFactory, times(1)).setPoolMultiuserAuthentication(eq(true));
|
||||
verify(mockClientCacheFactory, times(1)).setPoolPingInterval(eq(15000l));
|
||||
verify(mockClientCacheFactory, times(1)).setPoolPingInterval(eq(15000L));
|
||||
verify(mockClientCacheFactory, times(1)).setPoolPRSingleHopEnabled(eq(true));
|
||||
verify(mockClientCacheFactory, times(1)).setPoolReadTimeout(eq(30000));
|
||||
verify(mockClientCacheFactory, times(1)).setPoolRetryAttempts(eq(1));
|
||||
@@ -724,7 +702,7 @@ public class ClientCacheFactoryBeanTest {
|
||||
public void initializePoolWithPoolServer() {
|
||||
Pool mockPool = mock(Pool.class);
|
||||
|
||||
when(mockPool.getLocators()).thenReturn(Collections.<InetSocketAddress>emptyList());
|
||||
when(mockPool.getLocators()).thenReturn(Collections.emptyList());
|
||||
when(mockPool.getServers()).thenReturn(Collections.singletonList(new InetSocketAddress("boombox", 41414)));
|
||||
|
||||
ClientCacheFactoryBean clientCacheFactoryBean = new ClientCacheFactoryBean();
|
||||
@@ -751,7 +729,7 @@ public class ClientCacheFactoryBeanTest {
|
||||
Pool mockPool = mock(Pool.class);
|
||||
|
||||
when(mockPool.getLocators()).thenReturn(Collections.singletonList(new InetSocketAddress("skullbox", 21668)));
|
||||
when(mockPool.getServers()).thenReturn(Collections.<InetSocketAddress>emptyList());
|
||||
when(mockPool.getServers()).thenReturn(Collections.emptyList());
|
||||
|
||||
ClientCacheFactoryBean clientCacheFactoryBean = new ClientCacheFactoryBean();
|
||||
|
||||
@@ -803,8 +781,7 @@ public class ClientCacheFactoryBeanTest {
|
||||
|
||||
ClientCacheFactoryBean clientCacheFactoryBean = new ClientCacheFactoryBean();
|
||||
|
||||
assertThat((ClientCache) clientCacheFactoryBean.createCache(mockClientCacheFactory),
|
||||
is(sameInstance(mockClientCache)));
|
||||
assertThat(clientCacheFactoryBean.createCache(mockClientCacheFactory), is(sameInstance(mockClientCache)));
|
||||
|
||||
verify(mockClientCacheFactory, times(1)).create();
|
||||
verifyZeroInteractions(mockClientCache);
|
||||
@@ -878,7 +855,7 @@ public class ClientCacheFactoryBeanTest {
|
||||
clientCacheFactoryBean.setBeanFactory(mockBeanFactory);
|
||||
clientCacheFactoryBean.setPoolName("TestPool");
|
||||
|
||||
assertThat((ListableBeanFactory) clientCacheFactoryBean.getBeanFactory(), is(equalTo(mockBeanFactory)));
|
||||
assertThat(clientCacheFactoryBean.getBeanFactory(), is(equalTo(mockBeanFactory)));
|
||||
assertThat(clientCacheFactoryBean.getPool(), is(nullValue()));
|
||||
assertThat(clientCacheFactoryBean.getPoolName(), is(equalTo("TestPool")));
|
||||
assertThat(clientCacheFactoryBean.resolvePool(), is(equalTo(mockPool)));
|
||||
@@ -903,7 +880,7 @@ public class ClientCacheFactoryBeanTest {
|
||||
|
||||
clientCacheFactoryBean.setBeanFactory(mockBeanFactory);
|
||||
|
||||
assertThat((ListableBeanFactory) clientCacheFactoryBean.getBeanFactory(), is(equalTo(mockBeanFactory)));
|
||||
assertThat(clientCacheFactoryBean.getBeanFactory(), is(equalTo(mockBeanFactory)));
|
||||
assertThat(clientCacheFactoryBean.getPool(), is(nullValue()));
|
||||
assertThat(clientCacheFactoryBean.getPoolName(), is(nullValue()));
|
||||
assertThat(clientCacheFactoryBean.resolvePool(), is(equalTo(mockPool)));
|
||||
@@ -925,7 +902,7 @@ public class ClientCacheFactoryBeanTest {
|
||||
|
||||
clientCacheFactoryBean.setBeanFactory(mockBeanFactory);
|
||||
|
||||
assertThat((ListableBeanFactory) clientCacheFactoryBean.getBeanFactory(), is(equalTo(mockBeanFactory)));
|
||||
assertThat(clientCacheFactoryBean.getBeanFactory(), is(equalTo(mockBeanFactory)));
|
||||
assertThat(clientCacheFactoryBean.getPool(), is(nullValue()));
|
||||
assertThat(clientCacheFactoryBean.getPoolName(), is(nullValue()));
|
||||
assertThat(clientCacheFactoryBean.resolvePool(), is(nullValue()));
|
||||
@@ -949,7 +926,7 @@ public class ClientCacheFactoryBeanTest {
|
||||
clientCacheFactoryBean.setBeanFactory(mockBeanFactory);
|
||||
clientCacheFactoryBean.setPoolName("TestPool");
|
||||
|
||||
assertThat((ListableBeanFactory) clientCacheFactoryBean.getBeanFactory(), is(equalTo(mockBeanFactory)));
|
||||
assertThat(clientCacheFactoryBean.getBeanFactory(), is(equalTo(mockBeanFactory)));
|
||||
assertThat(clientCacheFactoryBean.getPool(), is(nullValue()));
|
||||
assertThat(clientCacheFactoryBean.getPoolName(), is(equalTo("TestPool")));
|
||||
assertThat(clientCacheFactoryBean.resolvePool(), is(nullValue()));
|
||||
@@ -1176,12 +1153,12 @@ public class ClientCacheFactoryBeanTest {
|
||||
assertThat(clientCacheFactoryBean.getThreadLocalConnections(), is(nullValue()));
|
||||
|
||||
clientCacheFactoryBean.setFreeConnectionTimeout(5000);
|
||||
clientCacheFactoryBean.setIdleTimeout(120000l);
|
||||
clientCacheFactoryBean.setIdleTimeout(120000L);
|
||||
clientCacheFactoryBean.setLoadConditioningInterval(300000);
|
||||
clientCacheFactoryBean.setMaxConnections(500);
|
||||
clientCacheFactoryBean.setMinConnections(50);
|
||||
clientCacheFactoryBean.setMultiUserAuthentication(true);
|
||||
clientCacheFactoryBean.setPingInterval(15000l);
|
||||
clientCacheFactoryBean.setPingInterval(15000L);
|
||||
clientCacheFactoryBean.setPrSingleHopEnabled(true);
|
||||
clientCacheFactoryBean.setReadTimeout(30000);
|
||||
clientCacheFactoryBean.setRetryAttempts(1);
|
||||
@@ -1195,12 +1172,12 @@ public class ClientCacheFactoryBeanTest {
|
||||
clientCacheFactoryBean.setThreadLocalConnections(false);
|
||||
|
||||
assertThat(clientCacheFactoryBean.getFreeConnectionTimeout(), is(equalTo(5000)));
|
||||
assertThat(clientCacheFactoryBean.getIdleTimeout(), is(equalTo(120000l)));
|
||||
assertThat(clientCacheFactoryBean.getIdleTimeout(), is(equalTo(120000L)));
|
||||
assertThat(clientCacheFactoryBean.getLoadConditioningInterval(), is(equalTo(300000)));
|
||||
assertThat(clientCacheFactoryBean.getMaxConnections(), is(equalTo(500)));
|
||||
assertThat(clientCacheFactoryBean.getMinConnections(), is(equalTo(50)));
|
||||
assertThat(clientCacheFactoryBean.getMultiUserAuthentication(), is(equalTo(true)));
|
||||
assertThat(clientCacheFactoryBean.getPingInterval(), is(equalTo(15000l)));
|
||||
assertThat(clientCacheFactoryBean.getPingInterval(), is(equalTo(15000L)));
|
||||
assertThat(clientCacheFactoryBean.getPrSingleHopEnabled(), is(equalTo(true)));
|
||||
assertThat(clientCacheFactoryBean.getReadTimeout(), is(equalTo(30000)));
|
||||
assertThat(clientCacheFactoryBean.getRetryAttempts(), is(equalTo(1)));
|
||||
@@ -1233,7 +1210,7 @@ public class ClientCacheFactoryBeanTest {
|
||||
assertThat(clientCacheFactoryBean.getReadyForEvents(), is(false));
|
||||
}
|
||||
|
||||
protected ClientCache mockClientCache(String durableClientId) {
|
||||
private ClientCache mockClientCache(String durableClientId) {
|
||||
ClientCache mockClientCache = mock(ClientCache.class);
|
||||
|
||||
DistributedSystem mockDistributedSystem = mock(DistributedSystem.class);
|
||||
@@ -1363,7 +1340,7 @@ public class ClientCacheFactoryBeanTest {
|
||||
assertThat(clientCacheFactoryBean.getLocators().size(), is(equalTo(1)));
|
||||
assertThat(clientCacheFactoryBean.getLocators().findOne("localhost"), is(equalTo(localhost)));
|
||||
|
||||
clientCacheFactoryBean.setLocators(Collections.<ConnectionEndpoint>emptyList());
|
||||
clientCacheFactoryBean.setLocators(Collections.emptyList());
|
||||
|
||||
assertThat(clientCacheFactoryBean.getLocators(), is(notNullValue()));
|
||||
assertThat(clientCacheFactoryBean.getLocators().isEmpty(), is(true));
|
||||
@@ -1398,7 +1375,7 @@ public class ClientCacheFactoryBeanTest {
|
||||
assertThat(clientCacheFactoryBean.getServers().size(), is(equalTo(1)));
|
||||
assertThat(clientCacheFactoryBean.getServers().findOne("localhost"), is(equalTo(localhost)));
|
||||
|
||||
clientCacheFactoryBean.setServers(Collections.<ConnectionEndpoint>emptyList());
|
||||
clientCacheFactoryBean.setServers(Collections.emptyList());
|
||||
|
||||
assertThat(clientCacheFactoryBean.getServers(), is(notNullValue()));
|
||||
assertThat(clientCacheFactoryBean.getServers().isEmpty(), is(true));
|
||||
|
||||
@@ -130,7 +130,7 @@ public class ClientRegionFactoryBeanTest {
|
||||
factoryBean.setSnapshot(mockSnapshot);
|
||||
factoryBean.setShortcut(null);
|
||||
|
||||
Region actualRegion = factoryBean.lookupRegion(mockClientCache, testRegionName);
|
||||
Region actualRegion = factoryBean.createRegion(mockClientCache, testRegionName);
|
||||
|
||||
assertSame(mockRegion, actualRegion);
|
||||
|
||||
@@ -180,7 +180,7 @@ public class ClientRegionFactoryBeanTest {
|
||||
factoryBean.setPoolName("TestPool");
|
||||
factoryBean.setShortcut(null);
|
||||
|
||||
Region<Object, Object> actualRegion = factoryBean.lookupRegion(mockClientCache, "TestRegion");
|
||||
Region<Object, Object> actualRegion = factoryBean.createRegion(mockClientCache, "TestRegion");
|
||||
|
||||
assertSame(mockRegion, actualRegion);
|
||||
|
||||
@@ -208,7 +208,7 @@ public class ClientRegionFactoryBeanTest {
|
||||
factoryBean.setBeanFactory(mockBeanFactory);
|
||||
factoryBean.setShortcut(ClientRegionShortcut.CACHING_PROXY);
|
||||
|
||||
Region<Object, Object> actualRegion = factoryBean.lookupRegion(mockClientCache, "TestRegion");
|
||||
Region<Object, Object> actualRegion = factoryBean.createRegion(mockClientCache, "TestRegion");
|
||||
|
||||
assertSame(mockRegion, actualRegion);
|
||||
|
||||
@@ -235,7 +235,7 @@ public class ClientRegionFactoryBeanTest {
|
||||
factoryBean.setParent(mockRegion);
|
||||
factoryBean.setShortcut(ClientRegionShortcut.PROXY);
|
||||
|
||||
Region<Object, Object> actualRegion = factoryBean.lookupRegion(mockClientCache, "TestSubRegion");
|
||||
Region<Object, Object> actualRegion = factoryBean.createRegion(mockClientCache, "TestSubRegion");
|
||||
|
||||
assertSame(mockSubRegion, actualRegion);
|
||||
|
||||
@@ -260,7 +260,7 @@ public class ClientRegionFactoryBeanTest {
|
||||
factoryBean.setBeanFactory(mockBeanFactory);
|
||||
factoryBean.setShortcut(ClientRegionShortcut.LOCAL_HEAP_LRU);
|
||||
|
||||
Region<Object, Object> actualRegion = factoryBean.lookupRegion(mockClientCache, "TestRegion");
|
||||
Region<Object, Object> actualRegion = factoryBean.createRegion(mockClientCache, "TestRegion");
|
||||
|
||||
assertSame(mockRegion, actualRegion);
|
||||
|
||||
@@ -284,7 +284,7 @@ public class ClientRegionFactoryBeanTest {
|
||||
factoryBean.setDataPolicyName("INVALID");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
assertEquals("Data Policy 'INVALID' is invalid.", expected.getMessage());
|
||||
assertEquals("Data Policy [INVALID] is not valid", expected.getMessage());
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
@@ -429,7 +429,7 @@ public class ClientRegionFactoryBeanTest {
|
||||
factoryBean.resolveClientRegionShortcut();
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
assertEquals("Client Region Shortcut 'CACHING_PROXY' is invalid when persistent is true",
|
||||
assertEquals("Client Region Shortcut [CACHING_PROXY] is not valid when persistent is true",
|
||||
expected.getMessage());
|
||||
throw expected;
|
||||
}
|
||||
@@ -456,7 +456,7 @@ public class ClientRegionFactoryBeanTest {
|
||||
factoryBean.resolveClientRegionShortcut();
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
assertEquals("Client Region Shortcut 'LOCAL_PERSISTENT' is invalid when persistent is false",
|
||||
assertEquals("Client Region Shortcut [LOCAL_PERSISTENT] is not valid when persistent is false",
|
||||
expected.getMessage());
|
||||
throw expected;
|
||||
}
|
||||
@@ -503,7 +503,7 @@ public class ClientRegionFactoryBeanTest {
|
||||
factoryBean.resolveClientRegionShortcut();
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
assertEquals("Data Policy 'NORMAL' is invalid when persistent is true", expected.getMessage());
|
||||
assertEquals("Data Policy [NORMAL] is not valid when persistent is true", expected.getMessage());
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
@@ -529,7 +529,7 @@ public class ClientRegionFactoryBeanTest {
|
||||
factoryBean.resolveClientRegionShortcut();
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
assertEquals("Data Policy 'PERSISTENT_REPLICATE' is invalid when persistent is false", expected.getMessage());
|
||||
assertEquals("Data Policy [PERSISTENT_REPLICATE] is not valid when persistent is false", expected.getMessage());
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,19 +52,15 @@ import org.springframework.data.gemfire.util.ArrayUtils;
|
||||
import org.springframework.data.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* The PoolFactoryBeanTest class is a test suite of test cases testing the contract and functionality
|
||||
* of the PoolFactoryBean class.
|
||||
* Unit tests for {@link PoolFactoryBean}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Rule
|
||||
* @see org.junit.Test
|
||||
* @see org.junit.rules.ExpectedException
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.springframework.data.gemfire.client.PoolFactoryBean
|
||||
* @see org.springframework.data.gemfire.support.ConnectionEndpoint
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.client.Pool
|
||||
* @see org.apache.geode.cache.client.PoolFactory
|
||||
* @see org.springframework.data.gemfire.client.PoolFactoryBean
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public class PoolFactoryBeanTest {
|
||||
@@ -164,7 +160,7 @@ public class PoolFactoryBeanTest {
|
||||
|
||||
exception.expect(IllegalArgumentException.class);
|
||||
exception.expectCause(is(nullValue(Throwable.class)));
|
||||
exception.expectMessage("Pool 'name' is required");
|
||||
exception.expectMessage("Pool name is required");
|
||||
|
||||
poolFactoryBean.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
package org.springframework.data.gemfire.config.annotation;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
@@ -53,9 +54,11 @@ import org.springframework.util.MethodInvoker;
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.junit.runner.RunWith
|
||||
* @see org.mockito.Mock
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.mockito.runners.MockitoJUnitRunner
|
||||
* @see org.mockito.Spy
|
||||
* @see org.mockito.junit.MockitoJUnitRunner
|
||||
* @see org.springframework.data.gemfire.config.annotation.AbstractCacheConfiguration
|
||||
* @since 1.9.0
|
||||
*/
|
||||
@@ -174,7 +177,7 @@ public class AbstractCacheConfigurationUnitTests {
|
||||
MappingPdxSerializer mockPdxSerializer = mock(MappingPdxSerializer.class);
|
||||
|
||||
when(mockBeanFactory.containsBean(anyString())).thenReturn(false);
|
||||
doReturn(mockPdxSerializer).when(cacheConfigurationSpy).newPdxSerializer();
|
||||
doReturn(mockPdxSerializer).when(cacheConfigurationSpy).newPdxSerializer(any(BeanFactory.class));
|
||||
|
||||
cacheConfigurationSpy.setBeanFactory(mockBeanFactory);
|
||||
|
||||
@@ -184,7 +187,7 @@ public class AbstractCacheConfigurationUnitTests {
|
||||
|
||||
verify(mockBeanFactory, times(1)).containsBean(eq("TestPdxSerializer"));
|
||||
verify(mockBeanFactory, never()).getBean(anyString(), eq(PdxSerializer.class));
|
||||
verify(cacheConfigurationSpy, times(1)).newPdxSerializer();
|
||||
verify(cacheConfigurationSpy, times(1)).newPdxSerializer(eq(mockBeanFactory));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.gemfire.config.annotation;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.gemfire.server.CacheServerFactoryBean;
|
||||
import org.springframework.data.gemfire.test.GemfireTestBeanPostProcessor;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link CacheServerConfigurer}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.apache.geode.cache.server.CacheServer
|
||||
* @see org.springframework.context.annotation.Configuration
|
||||
* @see org.springframework.data.gemfire.config.annotation.CacheServerConfigurer
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableCacheServer
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableCacheServers
|
||||
* @see org.springframework.data.gemfire.server.CacheServerFactoryBean
|
||||
* @see org.springframework.test.context.ContextConfiguration
|
||||
* @see org.springframework.test.context.junit4.SpringRunner
|
||||
* @since 1.1.0
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@ContextConfiguration
|
||||
@SuppressWarnings("unused")
|
||||
public class CacheServerConfigurerIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
@Qualifier("configurerOne")
|
||||
private TestCacheServerConfigurer configurerOne;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("configurerTwo")
|
||||
private TestCacheServerConfigurer configurerTwo;
|
||||
|
||||
private void assertCacheServerConfigurerCalled(TestCacheServerConfigurer configurer,
|
||||
String... cacheServerBeanNames) {
|
||||
|
||||
assertThat(configurer).isNotNull();
|
||||
assertThat(configurer).hasSize(cacheServerBeanNames.length);
|
||||
assertThat(configurer).contains(cacheServerBeanNames);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cacheServerConfigurerOneCalledSuccessfully() {
|
||||
assertCacheServerConfigurerCalled(this.configurerOne,
|
||||
"gemfireCacheServer", "marsServer", "saturnServer", "venusServer");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cacheServerConfigurerTwoCalledSuccessfully() {
|
||||
assertCacheServerConfigurerCalled(this.configurerTwo,
|
||||
"gemfireCacheServer", "marsServer", "saturnServer", "venusServer");
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@CacheServerApplication
|
||||
@EnableCacheServers(servers = {
|
||||
@EnableCacheServer(name = "marsServer"),
|
||||
@EnableCacheServer(name = "saturnServer"),
|
||||
@EnableCacheServer(name = "venusServer"),
|
||||
})
|
||||
static class TestConfiguration {
|
||||
|
||||
@Bean
|
||||
GemfireTestBeanPostProcessor testBeanPostProcessor() {
|
||||
return new GemfireTestBeanPostProcessor();
|
||||
}
|
||||
|
||||
@Bean
|
||||
TestCacheServerConfigurer configurerOne() {
|
||||
return new TestCacheServerConfigurer();
|
||||
}
|
||||
|
||||
@Bean
|
||||
TestCacheServerConfigurer configurerTwo() {
|
||||
return new TestCacheServerConfigurer();
|
||||
}
|
||||
|
||||
@Bean
|
||||
Object nonRelevantBean() {
|
||||
return "test";
|
||||
}
|
||||
}
|
||||
|
||||
static class TestCacheServerConfigurer implements CacheServerConfigurer, Iterable<String> {
|
||||
|
||||
private final Set<String> beanNames = new HashSet<>();
|
||||
|
||||
@Override
|
||||
public void configure(String beanName, CacheServerFactoryBean bean) {
|
||||
this.beanNames.add(beanName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<String> iterator() {
|
||||
return Collections.unmodifiableSet(this.beanNames).iterator();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.gemfire.config.annotation;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.geode.cache.client.ClientCache;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.data.gemfire.client.ClientCacheFactoryBean;
|
||||
import org.springframework.data.gemfire.test.GemfireTestBeanPostProcessor;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link ClientCacheConfigurer}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.junit.runner.RunWith
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @see org.springframework.data.gemfire.client.ClientCacheFactoryBean
|
||||
* @see org.springframework.data.gemfire.config.annotation.ClientCacheApplication
|
||||
* @see org.springframework.data.gemfire.config.annotation.ClientCacheConfigurer
|
||||
* @see org.springframework.data.gemfire.test.GemfireTestBeanPostProcessor
|
||||
* @see org.springframework.test.context.junit4.SpringRunner
|
||||
* @since 1.1.0
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SuppressWarnings("unused")
|
||||
public class ClientCacheConfigurerIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
private ClientCache clientCache;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("testClientCacheConfigurerOne")
|
||||
private TestClientCacheConfigurer configurerOne;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("testClientCacheConfigurerTwo")
|
||||
private TestClientCacheConfigurer configurerTwo;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
assertThat(this.clientCache).isNotNull();
|
||||
}
|
||||
|
||||
private void assertClientCacheConfigurerInvokedSuccessfully(TestClientCacheConfigurer clientCacheConfigurer,
|
||||
String... beanNames) {
|
||||
|
||||
assertThat(clientCacheConfigurer).isNotNull();
|
||||
assertThat(clientCacheConfigurer).hasSize(beanNames.length);
|
||||
assertThat(clientCacheConfigurer).contains(beanNames);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clientCacheConfigurerOneCalledSuccessfully() {
|
||||
assertClientCacheConfigurerInvokedSuccessfully(this.configurerOne, "gemfireCache");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clientCacheConfigurerTwoCalledSuccessfully() {
|
||||
assertClientCacheConfigurerInvokedSuccessfully(this.configurerTwo, "gemfireCache");
|
||||
}
|
||||
|
||||
@ClientCacheApplication
|
||||
static class TestConfiguration {
|
||||
|
||||
@Bean
|
||||
GemfireTestBeanPostProcessor testBeanPostProcessor() {
|
||||
return new GemfireTestBeanPostProcessor();
|
||||
}
|
||||
|
||||
@Bean
|
||||
TestClientCacheConfigurer testClientCacheConfigurerOne() {
|
||||
return new TestClientCacheConfigurer();
|
||||
}
|
||||
|
||||
@Bean
|
||||
TestClientCacheConfigurer testClientCacheConfigurerTwo() {
|
||||
return new TestClientCacheConfigurer();
|
||||
}
|
||||
|
||||
@Bean
|
||||
String nonRelevantBean() {
|
||||
return "test";
|
||||
}
|
||||
}
|
||||
|
||||
static final class TestClientCacheConfigurer implements ClientCacheConfigurer, Iterable<String> {
|
||||
|
||||
private Set<String> beanNames = new HashSet<>();
|
||||
|
||||
@Override
|
||||
public void configure(String beanName, ClientCacheFactoryBean bean) {
|
||||
this.beanNames.add(beanName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<String> iterator() {
|
||||
return Collections.unmodifiableSet(this.beanNames).iterator();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.gemfire.config.annotation;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.data.gemfire.DiskStoreFactoryBean;
|
||||
import org.springframework.data.gemfire.test.GemfireTestBeanPostProcessor;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link DiskStoreConfigurer}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.apache.geode.cache.DiskStore
|
||||
* @see org.apache.geode.cache.DiskStoreFactory
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.springframework.context.annotation.Configuration
|
||||
* @see org.springframework.data.gemfire.DiskStoreFactoryBean
|
||||
* @see org.springframework.data.gemfire.config.annotation.DiskStoreConfiguration
|
||||
* @see org.springframework.data.gemfire.config.annotation.DiskStoreConfigurer
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableDiskStore
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableDiskStores
|
||||
* @see org.springframework.test.context.ContextConfiguration
|
||||
* @see org.springframework.test.context.junit4.SpringRunner
|
||||
* @since 1.1.0
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@ContextConfiguration
|
||||
@SuppressWarnings("unused")
|
||||
public class DiskStoreConfigurerIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
@Qualifier("configurerOne")
|
||||
private TestDiskStoreConfigurer configurerOne;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("configurerTwo")
|
||||
private TestDiskStoreConfigurer configurerTwo;
|
||||
|
||||
private void assertDiskStoreConfigurerCalled(TestDiskStoreConfigurer configurer, String... beanNames) {
|
||||
assertThat(configurer).isNotNull();
|
||||
assertThat(configurer).hasSize(beanNames.length);
|
||||
assertThat(configurer).contains(beanNames);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void diskStoreConfigurerOneCalledSuccessfully() {
|
||||
assertDiskStoreConfigurerCalled(this.configurerOne, "cd", "floppy", "tape");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void diskStoreConfigurerTwoCalledSuccessfully() {
|
||||
assertDiskStoreConfigurerCalled(this.configurerTwo, "cd", "floppy", "tape");
|
||||
}
|
||||
|
||||
@PeerCacheApplication
|
||||
@EnableDiskStores(diskStores = {
|
||||
@EnableDiskStore(name = "cd"),
|
||||
@EnableDiskStore(name = "floppy"),
|
||||
@EnableDiskStore(name = "tape"),
|
||||
})
|
||||
static class TestConfiguration {
|
||||
|
||||
@Bean
|
||||
GemfireTestBeanPostProcessor testBeanPostProcessor() {
|
||||
return new GemfireTestBeanPostProcessor();
|
||||
}
|
||||
|
||||
@Bean
|
||||
TestDiskStoreConfigurer configurerOne() {
|
||||
return new TestDiskStoreConfigurer();
|
||||
}
|
||||
|
||||
@Bean
|
||||
TestDiskStoreConfigurer configurerTwo() {
|
||||
return new TestDiskStoreConfigurer();
|
||||
}
|
||||
|
||||
@Bean
|
||||
Object nonRelevantBean() {
|
||||
return "test";
|
||||
}
|
||||
}
|
||||
|
||||
static class TestDiskStoreConfigurer implements DiskStoreConfigurer, Iterable<String> {
|
||||
|
||||
private final Set<String> beanNames = new HashSet<>();
|
||||
|
||||
@Override
|
||||
public void configure(String beanName, DiskStoreFactoryBean bean) {
|
||||
this.beanNames.add(beanName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<String> iterator() {
|
||||
return Collections.unmodifiableSet(this.beanNames).iterator();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.gemfire.config.annotation;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.cache.lucene.LuceneIndex;
|
||||
import org.apache.geode.cache.lucene.LuceneService;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.FilterType;
|
||||
import org.springframework.data.gemfire.IndexFactoryBean;
|
||||
import org.springframework.data.gemfire.config.annotation.test.entities.CollocatedPartitionRegionEntity;
|
||||
import org.springframework.data.gemfire.config.annotation.test.entities.NonEntity;
|
||||
import org.springframework.data.gemfire.mapping.annotation.ClientRegion;
|
||||
import org.springframework.data.gemfire.mapping.annotation.LocalRegion;
|
||||
import org.springframework.data.gemfire.mapping.annotation.ReplicateRegion;
|
||||
import org.springframework.data.gemfire.search.lucene.LuceneIndexFactoryBean;
|
||||
import org.springframework.data.gemfire.test.GemfireTestBeanPostProcessor;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link IndexConfigurer}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.lucene.LuceneIndex
|
||||
* @see org.apache.geode.cache.query.Index
|
||||
* @see org.springframework.data.gemfire.IndexFactoryBean
|
||||
* @see org.springframework.data.gemfire.config.annotation.IndexConfigurer
|
||||
* @see org.springframework.data.gemfire.search.lucene.LuceneIndexFactoryBean
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class IndexConfigurerIntegrationTests {
|
||||
|
||||
private static ConfigurableApplicationContext applicationContext;
|
||||
|
||||
@BeforeClass
|
||||
public static void setup() {
|
||||
|
||||
applicationContext = newApplicationContext(TestConfiguration.class);
|
||||
|
||||
assertThat(applicationContext).isNotNull();
|
||||
assertThat(applicationContext.containsBean("CustomersFirstNameFunctionalIdx")).isTrue();
|
||||
assertThat(applicationContext.containsBean("CustomersIdKeyIdx")).isTrue();
|
||||
assertThat(applicationContext.containsBean("GenericRegionEntityIdKeyIdx")).isTrue();
|
||||
assertThat(applicationContext.containsBean("LastNameIdx")).isTrue();
|
||||
assertThat(applicationContext.containsBean("luceneIndex")).isTrue();
|
||||
assertThat(applicationContext.containsBean("oqlIndex")).isTrue();
|
||||
assertThat(applicationContext.containsBean("TitleLuceneIdx")).isTrue();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDown() {
|
||||
Optional.ofNullable(applicationContext).ifPresent(ConfigurableApplicationContext::close);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private static ConfigurableApplicationContext newApplicationContext(Class<?>... annotatedClasses) {
|
||||
ConfigurableApplicationContext applicationContext = new AnnotationConfigApplicationContext(annotatedClasses);
|
||||
applicationContext.registerShutdownHook();
|
||||
return applicationContext;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private void assertIndexConfigurerInvocations(TestIndexConfigurer indexConfigurer, String... indexBeanNames) {
|
||||
assertThat(indexConfigurer).isNotNull();
|
||||
assertThat(indexConfigurer).contains(indexBeanNames);
|
||||
assertThat(indexConfigurer).hasSize(indexBeanNames.length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void indexConfigurerOneCalledSuccessfully() {
|
||||
|
||||
assertIndexConfigurerInvocations(
|
||||
applicationContext.getBean("testIndexConfigurerOne", TestIndexConfigurer.class),
|
||||
"CustomersFirstNameFunctionalIdx", "CustomersIdKeyIdx", "GenericRegionEntityIdKeyIdx",
|
||||
"LastNameIdx", "TitleLuceneIdx");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void indexConfigurerTwoCalledSuccessfully() {
|
||||
|
||||
assertIndexConfigurerInvocations(
|
||||
applicationContext.getBean("testIndexConfigurerTwo", TestIndexConfigurer.class),
|
||||
"CustomersFirstNameFunctionalIdx", "CustomersIdKeyIdx", "GenericRegionEntityIdKeyIdx",
|
||||
"LastNameIdx", "TitleLuceneIdx");
|
||||
}
|
||||
|
||||
@PeerCacheApplication
|
||||
@EnableIndexing
|
||||
@SuppressWarnings("unused")
|
||||
@EnableEntityDefinedRegions(basePackageClasses = NonEntity.class,
|
||||
excludeFilters = {
|
||||
@ComponentScan.Filter(type = FilterType.ANNOTATION,
|
||||
classes = { ClientRegion.class, LocalRegion.class, ReplicateRegion.class }),
|
||||
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,
|
||||
classes = CollocatedPartitionRegionEntity.class)
|
||||
}
|
||||
)
|
||||
static class TestConfiguration {
|
||||
|
||||
@Bean
|
||||
GemfireTestBeanPostProcessor testBeanPostProcessor() {
|
||||
return new GemfireTestBeanPostProcessor();
|
||||
}
|
||||
|
||||
@Bean
|
||||
BeanPostProcessor indexFactoryBeanReplacingBeanPostProcessor() {
|
||||
|
||||
return new BeanPostProcessor() {
|
||||
|
||||
@Override
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
|
||||
if (bean instanceof LuceneIndexFactoryBean) {
|
||||
LuceneIndexFactoryBean luceneIndexFactoryBean = (LuceneIndexFactoryBean) bean;
|
||||
LuceneService mockLuceneService = mock(LuceneService.class);
|
||||
LuceneIndex mockLuceneIndex = mock(LuceneIndex.class);
|
||||
|
||||
luceneIndexFactoryBean.setLuceneIndex(mockLuceneIndex);
|
||||
luceneIndexFactoryBean.setLuceneService(mockLuceneService);
|
||||
luceneIndexFactoryBean.setRegionPath("/Test");
|
||||
}
|
||||
|
||||
return bean;
|
||||
}
|
||||
};
|
||||
}
|
||||
@Bean
|
||||
LuceneIndexFactoryBean luceneIndex() {
|
||||
return new LuceneIndexFactoryBean();
|
||||
}
|
||||
|
||||
@Bean
|
||||
IndexFactoryBean oqlIndex(GemFireCache cache) {
|
||||
|
||||
IndexFactoryBean indexFactory = new IndexFactoryBean();
|
||||
|
||||
indexFactory.setCache(cache);
|
||||
indexFactory.setExpression("*");
|
||||
indexFactory.setFrom("/Test");
|
||||
|
||||
return indexFactory;
|
||||
}
|
||||
|
||||
@Bean
|
||||
TestIndexConfigurer testIndexConfigurerOne() {
|
||||
return new TestIndexConfigurer();
|
||||
}
|
||||
|
||||
@Bean
|
||||
TestIndexConfigurer testIndexConfigurerTwo() {
|
||||
return new TestIndexConfigurer();
|
||||
}
|
||||
|
||||
@Bean
|
||||
String nonRelevantBean() {
|
||||
return "test";
|
||||
}
|
||||
}
|
||||
|
||||
private static class TestIndexConfigurer implements IndexConfigurer, Iterable<String> {
|
||||
|
||||
private final Set<String> beanNames = new HashSet<>();
|
||||
|
||||
@Override
|
||||
public void configure(String beanName, IndexFactoryBean bean) {
|
||||
this.beanNames.add(beanName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(String beanName, LuceneIndexFactoryBean bean) {
|
||||
this.beanNames.add(beanName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<String> iterator() {
|
||||
return Collections.unmodifiableSet(this.beanNames).iterator();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.gemfire.config.annotation;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.geode.cache.Cache;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.data.gemfire.CacheFactoryBean;
|
||||
import org.springframework.data.gemfire.test.GemfireTestBeanPostProcessor;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link PeerCacheConfigurer}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.junit.runner.RunWith
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see org.springframework.data.gemfire.CacheFactoryBean
|
||||
* @see org.springframework.data.gemfire.config.annotation.PeerCacheApplication
|
||||
* @see org.springframework.data.gemfire.config.annotation.PeerCacheConfigurer
|
||||
* @see org.springframework.data.gemfire.test.GemfireTestBeanPostProcessor
|
||||
* @see org.springframework.test.context.junit4.SpringRunner
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SuppressWarnings("unused")
|
||||
public class PeerCacheConfigurerIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
private Cache peerCache;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("testPeerCacheConfigurerOne")
|
||||
private TestPeerCacheConfigurer configurerOne;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("testPeerCacheConfigurerTwo")
|
||||
private TestPeerCacheConfigurer configurerTwo;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
assertThat(this.peerCache).isNotNull();
|
||||
}
|
||||
|
||||
private void assertTestPeerCacheConfigurerCalledSuccessully(TestPeerCacheConfigurer peerCacheConfigurer,
|
||||
String... beanNames) {
|
||||
|
||||
assertThat(peerCacheConfigurer).isNotNull();
|
||||
assertThat(peerCacheConfigurer).hasSize(beanNames.length);
|
||||
assertThat(peerCacheConfigurer).contains(beanNames);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void peerCacheConfigurerOneCalledSuccessfully() {
|
||||
assertTestPeerCacheConfigurerCalledSuccessully(this.configurerOne, "gemfireCache");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void peerCacheConfigurerTwoCalledSuccessfully() {
|
||||
assertTestPeerCacheConfigurerCalledSuccessully(this.configurerTwo, "gemfireCache");
|
||||
}
|
||||
|
||||
@PeerCacheApplication
|
||||
static class TestConfiguration {
|
||||
|
||||
@Bean
|
||||
GemfireTestBeanPostProcessor testBeanPostProcessor() {
|
||||
return new GemfireTestBeanPostProcessor();
|
||||
}
|
||||
|
||||
@Bean
|
||||
TestPeerCacheConfigurer testPeerCacheConfigurerOne() {
|
||||
return new TestPeerCacheConfigurer();
|
||||
}
|
||||
|
||||
@Bean
|
||||
TestPeerCacheConfigurer testPeerCacheConfigurerTwo() {
|
||||
return new TestPeerCacheConfigurer();
|
||||
}
|
||||
|
||||
@Bean
|
||||
String nonRelevantBean() {
|
||||
return "test";
|
||||
}
|
||||
}
|
||||
|
||||
static class TestPeerCacheConfigurer implements Iterable<String>, PeerCacheConfigurer {
|
||||
|
||||
private Set<String> beanNames = new HashSet<>();
|
||||
|
||||
@Override
|
||||
public void configure(String beanName, CacheFactoryBean bean) {
|
||||
this.beanNames.add(beanName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<String> iterator() {
|
||||
return Collections.unmodifiableSet(this.beanNames).iterator();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.gemfire.config.annotation;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.gemfire.client.PoolFactoryBean;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link PoolConfigurer}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.apache.geode.cache.client.Pool
|
||||
* @see org.springframework.context.annotation.Configuration
|
||||
* @see org.springframework.data.gemfire.client.PoolFactoryBean
|
||||
* @see org.springframework.data.gemfire.config.annotation.AddPoolConfiguration
|
||||
* @see org.springframework.data.gemfire.config.annotation.AddPoolsConfiguration
|
||||
* @see org.springframework.data.gemfire.config.annotation.PoolConfigurer
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnablePool
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnablePools
|
||||
* @see org.springframework.test.context.ContextConfiguration
|
||||
* @see org.springframework.test.context.junit4.SpringRunner
|
||||
* @since 1.1.0
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@ContextConfiguration
|
||||
@SuppressWarnings("unused")
|
||||
public class PoolConfigurerIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
@Qualifier("configurerOne")
|
||||
private TestPoolConfigurer configurerOne;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("configurerTwo")
|
||||
private TestPoolConfigurer configurerTwo;
|
||||
|
||||
protected void assertPoolConfigurerCalled(TestPoolConfigurer configurer, String... beanNames) {
|
||||
assertThat(configurer).isNotNull();
|
||||
assertThat(configurer).hasSize(beanNames.length);
|
||||
assertThat(configurer).contains(beanNames);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void poolConfigurerOneCalledSuccessfully() {
|
||||
assertPoolConfigurerCalled(this.configurerOne, "poolOne", "poolTwo", "poolThree");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void poolConfigurerTwoCalledSuccessfully() {
|
||||
assertPoolConfigurerCalled(this.configurerTwo, "poolOne", "poolTwo", "poolThree");
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnablePools(pools = {
|
||||
@EnablePool(name = "poolOne"),
|
||||
@EnablePool(name = "poolTwo"),
|
||||
@EnablePool(name = "poolThree"),
|
||||
})
|
||||
static class TestConfiguration {
|
||||
|
||||
@Bean
|
||||
TestPoolConfigurer configurerOne() {
|
||||
return new TestPoolConfigurer();
|
||||
}
|
||||
|
||||
@Bean
|
||||
TestPoolConfigurer configurerTwo() {
|
||||
return new TestPoolConfigurer();
|
||||
}
|
||||
|
||||
@Bean
|
||||
Object nonRelevantBean() {
|
||||
return "test";
|
||||
}
|
||||
}
|
||||
|
||||
static class TestPoolConfigurer implements Iterable<String>, PoolConfigurer {
|
||||
|
||||
private final Set<String> beanNames = new HashSet<>();
|
||||
|
||||
@Override
|
||||
public void configure(String beanName, PoolFactoryBean bean) {
|
||||
this.beanNames.add(beanName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<String> iterator() {
|
||||
return Collections.unmodifiableSet(this.beanNames).iterator();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.gemfire.config.annotation;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.FilterType;
|
||||
import org.springframework.data.gemfire.PartitionedRegionFactoryBean;
|
||||
import org.springframework.data.gemfire.RegionFactoryBean;
|
||||
import org.springframework.data.gemfire.client.ClientRegionFactoryBean;
|
||||
import org.springframework.data.gemfire.config.annotation.test.entities.CollocatedPartitionRegionEntity;
|
||||
import org.springframework.data.gemfire.config.annotation.test.entities.NonEntity;
|
||||
import org.springframework.data.gemfire.mapping.annotation.ClientRegion;
|
||||
import org.springframework.data.gemfire.mapping.annotation.LocalRegion;
|
||||
import org.springframework.data.gemfire.mapping.annotation.PartitionRegion;
|
||||
import org.springframework.data.gemfire.mapping.annotation.ReplicateRegion;
|
||||
import org.springframework.data.gemfire.test.GemfireTestBeanPostProcessor;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link RegionConfigurer}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.springframework.context.ConfigurableApplicationContext
|
||||
* @see org.springframework.context.annotation.AnnotationConfigApplicationContext
|
||||
* @see org.springframework.data.gemfire.RegionFactoryBean
|
||||
* @see org.springframework.data.gemfire.client.ClientRegionFactoryBean
|
||||
* @see org.springframework.data.gemfire.config.annotation.RegionConfigurer
|
||||
* @see org.springframework.data.gemfire.test.GemfireTestBeanPostProcessor
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public class RegionConfigurerIntegrationTests {
|
||||
|
||||
private ConfigurableApplicationContext applicationContext;
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
Optional.ofNullable(this.applicationContext).ifPresent(ConfigurableApplicationContext::close);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private void assertRegionConfigurerInvocations(TestRegionConfigurer regionConfigurer, String... regionBeanNames) {
|
||||
assertThat(regionConfigurer).isNotNull();
|
||||
assertThat(regionConfigurer).contains(regionBeanNames);
|
||||
assertThat(regionConfigurer).hasSize(regionBeanNames.length);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private ConfigurableApplicationContext newApplicationContext(Class<?>... annotatedClasses) {
|
||||
ConfigurableApplicationContext applicationContext = new AnnotationConfigApplicationContext(annotatedClasses);
|
||||
applicationContext.registerShutdownHook();
|
||||
return applicationContext;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clientRegionConfigurersCalledSuccessfully() {
|
||||
|
||||
this.applicationContext = newApplicationContext(ClientTestConfiguration.class);
|
||||
|
||||
assertThat(this.applicationContext).isNotNull();
|
||||
assertThat(this.applicationContext.containsBean("Sessions")).isTrue();
|
||||
assertThat(this.applicationContext.containsBean("GenericRegionEntity")).isTrue();
|
||||
assertThat(this.applicationContext.containsBean("Test")).isTrue();
|
||||
assertThat(this.applicationContext.containsBean("testRegionConfigurerOne")).isTrue();
|
||||
assertThat(this.applicationContext.containsBean("testRegionConfigurerTwo")).isTrue();
|
||||
|
||||
assertRegionConfigurerInvocations(
|
||||
this.applicationContext.getBean("testRegionConfigurerOne", TestRegionConfigurer.class),
|
||||
"GenericRegionEntity", "Sessions");
|
||||
|
||||
assertRegionConfigurerInvocations(
|
||||
this.applicationContext.getBean("testRegionConfigurerTwo", TestRegionConfigurer.class),
|
||||
"GenericRegionEntity", "Sessions");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void peerRegionConfigurersCalledSuccessfully() {
|
||||
|
||||
this.applicationContext = newApplicationContext(PeerTestConfiguration.class);
|
||||
|
||||
assertThat(this.applicationContext).isNotNull();
|
||||
assertThat(this.applicationContext.containsBean("Customers")).isTrue();
|
||||
assertThat(this.applicationContext.containsBean("GenericRegionEntity")).isTrue();
|
||||
assertThat(this.applicationContext.containsBean("Test")).isTrue();
|
||||
assertThat(this.applicationContext.containsBean("testRegionConfigurerOne")).isTrue();
|
||||
assertThat(this.applicationContext.containsBean("testRegionConfigurerTwo")).isTrue();
|
||||
|
||||
assertRegionConfigurerInvocations(
|
||||
this.applicationContext.getBean("testRegionConfigurerOne", TestRegionConfigurer.class),
|
||||
"Customers", "GenericRegionEntity");
|
||||
|
||||
assertRegionConfigurerInvocations(
|
||||
this.applicationContext.getBean("testRegionConfigurerTwo", TestRegionConfigurer.class),
|
||||
"Customers", "GenericRegionEntity");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
static class AbstractTestConfiguration {
|
||||
|
||||
@Bean
|
||||
GemfireTestBeanPostProcessor testBeanPostProcessor() {
|
||||
return new GemfireTestBeanPostProcessor();
|
||||
}
|
||||
|
||||
@Bean
|
||||
TestRegionConfigurer testRegionConfigurerOne() {
|
||||
return new TestRegionConfigurer();
|
||||
}
|
||||
|
||||
@Bean
|
||||
TestRegionConfigurer testRegionConfigurerTwo() {
|
||||
return new TestRegionConfigurer();
|
||||
}
|
||||
|
||||
@Bean
|
||||
String nonRelevantBean() {
|
||||
return "test";
|
||||
}
|
||||
}
|
||||
|
||||
@ClientCacheApplication
|
||||
@EnableEntityDefinedRegions(basePackageClasses = NonEntity.class,
|
||||
excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION,
|
||||
classes = { LocalRegion.class, PartitionRegion.class, ReplicateRegion.class }))
|
||||
@SuppressWarnings("unused")
|
||||
static class ClientTestConfiguration extends AbstractTestConfiguration {
|
||||
|
||||
@Bean(name = "Test")
|
||||
ClientRegionFactoryBean<Object, Object> testRegion(GemFireCache gemfireCache) {
|
||||
ClientRegionFactoryBean<Object, Object> testRegionFactory = new ClientRegionFactoryBean<>();
|
||||
testRegionFactory.setCache(gemfireCache);
|
||||
return testRegionFactory;
|
||||
}
|
||||
}
|
||||
|
||||
@PeerCacheApplication
|
||||
@EnableEntityDefinedRegions(basePackageClasses = NonEntity.class,
|
||||
excludeFilters = {
|
||||
@ComponentScan.Filter(type = FilterType.ANNOTATION,
|
||||
classes = { ClientRegion.class, LocalRegion.class, ReplicateRegion.class }),
|
||||
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,
|
||||
classes = CollocatedPartitionRegionEntity.class)
|
||||
}
|
||||
)
|
||||
@SuppressWarnings("unused")
|
||||
static class PeerTestConfiguration extends AbstractTestConfiguration {
|
||||
|
||||
@Bean(name = "Test")
|
||||
PartitionedRegionFactoryBean<Object, Object> testRegion(GemFireCache gemfireCache) {
|
||||
PartitionedRegionFactoryBean<Object, Object> testRegionFactory = new PartitionedRegionFactoryBean<>();
|
||||
testRegionFactory.setCache(gemfireCache);
|
||||
return testRegionFactory;
|
||||
}
|
||||
}
|
||||
|
||||
private static class TestRegionConfigurer implements Iterable<String>, RegionConfigurer {
|
||||
|
||||
private final Set<String> beanNames = new HashSet<>();
|
||||
|
||||
@Override
|
||||
public void configure(String beanName, RegionFactoryBean<?, ?> bean) {
|
||||
this.beanNames.add(beanName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(String beanName, ClientRegionFactoryBean<?, ?> bean) {
|
||||
this.beanNames.add(beanName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<String> iterator() {
|
||||
return Collections.unmodifiableSet(this.beanNames).iterator();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,21 +16,23 @@
|
||||
|
||||
package org.springframework.data.gemfire.config.xml;
|
||||
|
||||
import static java.util.Arrays.stream;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNotSame;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.data.gemfire.util.ArrayUtils.nullSafeArray;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.apache.geode.cache.CacheListener;
|
||||
@@ -46,6 +48,7 @@ import org.apache.geode.cache.LoaderHelper;
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.apache.geode.cache.RegionAttributes;
|
||||
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.util.CacheWriterAdapter;
|
||||
import org.apache.geode.compression.Compressor;
|
||||
@@ -66,12 +69,13 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* The ClientRegionNamespaceTest class is a test suite of test cases testing the contract and functionality
|
||||
* of GemFire Client Region namespace support in SDG.
|
||||
* Unit tests for Spring Data GemFire's XML namespace support for client {@link Region Regions}.
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @author David Turanski
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @see org.springframework.data.gemfire.client.ClientRegionFactoryBean
|
||||
* @see org.springframework.data.gemfire.config.xml.ClientRegionParser
|
||||
*/
|
||||
@@ -81,35 +85,29 @@ import org.springframework.util.ObjectUtils;
|
||||
public class ClientRegionNamespaceTest {
|
||||
|
||||
@Autowired
|
||||
private ApplicationContext context;
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
@AfterClass
|
||||
public static void tearDown() {
|
||||
for (String name : new File(".").list(new FilenameFilter() {
|
||||
@Override
|
||||
public boolean accept(File dir, String name) {
|
||||
return name.startsWith("BACKUP");
|
||||
}
|
||||
})) {
|
||||
new File(name).delete();
|
||||
}
|
||||
stream(nullSafeArray(new File(".").list((dir, name) -> name.startsWith("BACKUP")), String.class))
|
||||
.forEach(fileName -> new File(fileName).delete());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBeanNames() throws Exception {
|
||||
assertTrue(context.containsBean("SimpleRegion"));
|
||||
assertTrue(context.containsBean("Publisher"));
|
||||
assertTrue(context.containsBean("ComplexRegion"));
|
||||
assertTrue(context.containsBean("PersistentRegion"));
|
||||
assertTrue(context.containsBean("OverflowRegion"));
|
||||
assertTrue(context.containsBean("Compressed"));
|
||||
assertTrue(applicationContext.containsBean("SimpleRegion"));
|
||||
assertTrue(applicationContext.containsBean("Publisher"));
|
||||
assertTrue(applicationContext.containsBean("ComplexRegion"));
|
||||
assertTrue(applicationContext.containsBean("PersistentRegion"));
|
||||
assertTrue(applicationContext.containsBean("OverflowRegion"));
|
||||
assertTrue(applicationContext.containsBean("Compressed"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleClientRegion() throws Exception {
|
||||
assertTrue(context.containsBean("simple"));
|
||||
assertTrue(applicationContext.containsBean("simple"));
|
||||
|
||||
Region<?, ?> simple = context.getBean("simple", Region.class);
|
||||
Region<?, ?> simple = applicationContext.getBean("simple", Region.class);
|
||||
|
||||
assertNotNull("The 'SimpleRegion' Client Region was not properly configured and initialized!", simple);
|
||||
assertEquals("SimpleRegion", simple.getName());
|
||||
@@ -121,9 +119,10 @@ public class ClientRegionNamespaceTest {
|
||||
@Test
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void testPublishingClientRegion() throws Exception {
|
||||
assertTrue(context.containsBean("empty"));
|
||||
assertTrue(applicationContext.containsBean("empty"));
|
||||
|
||||
ClientRegionFactoryBean emptyClientRegionFactoryBean = context.getBean("&empty", ClientRegionFactoryBean.class);
|
||||
ClientRegionFactoryBean emptyClientRegionFactoryBean = applicationContext
|
||||
.getBean("&empty", ClientRegionFactoryBean.class);
|
||||
|
||||
assertNotNull(emptyClientRegionFactoryBean);
|
||||
assertEquals(DataPolicy.EMPTY, TestUtils.readField("dataPolicy", emptyClientRegionFactoryBean));
|
||||
@@ -135,9 +134,10 @@ public class ClientRegionNamespaceTest {
|
||||
@Test
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void testComplexClientRegion() throws Exception {
|
||||
assertTrue(context.containsBean("complex"));
|
||||
assertTrue(applicationContext.containsBean("complex"));
|
||||
|
||||
ClientRegionFactoryBean complexClientRegionFactoryBean = context.getBean("&complex", ClientRegionFactoryBean.class);
|
||||
ClientRegionFactoryBean complexClientRegionFactoryBean = applicationContext
|
||||
.getBean("&complex", ClientRegionFactoryBean.class);
|
||||
|
||||
assertNotNull(complexClientRegionFactoryBean);
|
||||
|
||||
@@ -145,7 +145,7 @@ public class ClientRegionNamespaceTest {
|
||||
|
||||
assertFalse(ObjectUtils.isEmpty(cacheListeners));
|
||||
assertEquals(2, cacheListeners.length);
|
||||
assertSame(cacheListeners[0], context.getBean("c-listener"));
|
||||
assertSame(cacheListeners[0], applicationContext.getBean("c-listener"));
|
||||
assertTrue(cacheListeners[1] instanceof SimpleCacheListener);
|
||||
assertNotSame(cacheListeners[0], cacheListeners[1]);
|
||||
|
||||
@@ -161,9 +161,9 @@ public class ClientRegionNamespaceTest {
|
||||
@Test
|
||||
@SuppressWarnings({ "deprecation", "rawtypes" })
|
||||
public void testPersistentClientRegion() throws Exception {
|
||||
assertTrue(context.containsBean("persistent"));
|
||||
assertTrue(applicationContext.containsBean("persistent"));
|
||||
|
||||
Region persistent = context.getBean("persistent", Region.class);
|
||||
Region persistent = applicationContext.getBean("persistent", Region.class);
|
||||
|
||||
assertNotNull("The 'PersistentRegion' Region was not properly configured and initialized!", persistent);
|
||||
assertEquals("PersistentRegion", persistent.getName());
|
||||
@@ -179,9 +179,10 @@ public class ClientRegionNamespaceTest {
|
||||
@Test
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void testOverflowClientRegion() throws Exception {
|
||||
assertTrue(context.containsBean("overflow"));
|
||||
assertTrue(applicationContext.containsBean("overflow"));
|
||||
|
||||
ClientRegionFactoryBean overflowClientRegionFactoryBean = context.getBean("&overflow", ClientRegionFactoryBean.class);
|
||||
ClientRegionFactoryBean overflowClientRegionFactoryBean = applicationContext
|
||||
.getBean("&overflow", ClientRegionFactoryBean.class);
|
||||
|
||||
assertNotNull(overflowClientRegionFactoryBean);
|
||||
assertEquals("diskStore", TestUtils.readField("diskStoreName", overflowClientRegionFactoryBean));
|
||||
@@ -203,9 +204,9 @@ public class ClientRegionNamespaceTest {
|
||||
|
||||
@Test
|
||||
public void testClientRegionWithCacheLoaderAndCacheWriter() throws Exception {
|
||||
assertTrue(context.containsBean("loadWithWrite"));
|
||||
assertTrue(applicationContext.containsBean("loadWithWrite"));
|
||||
|
||||
ClientRegionFactoryBean factory = context.getBean("&loadWithWrite", ClientRegionFactoryBean.class);
|
||||
ClientRegionFactoryBean factory = applicationContext.getBean("&loadWithWrite", ClientRegionFactoryBean.class);
|
||||
|
||||
assertNotNull(factory);
|
||||
assertEquals("LoadedFullOfWrites", TestUtils.readField("name", factory));
|
||||
@@ -216,9 +217,9 @@ public class ClientRegionNamespaceTest {
|
||||
|
||||
@Test
|
||||
public void testCompressedReplicateRegion() {
|
||||
assertTrue(context.containsBean("Compressed"));
|
||||
assertTrue(applicationContext.containsBean("Compressed"));
|
||||
|
||||
Region<?, ?> compressed = context.getBean("Compressed", Region.class);
|
||||
Region<?, ?> compressed = applicationContext.getBean("Compressed", Region.class);
|
||||
|
||||
assertNotNull("The 'Compressed' Client Region was not properly configured and initialized!", compressed);
|
||||
assertEquals("Compressed", compressed.getName());
|
||||
@@ -235,9 +236,9 @@ public class ClientRegionNamespaceTest {
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testClientRegionWithAttributes() {
|
||||
assertTrue(context.containsBean("client-with-attributes"));
|
||||
assertTrue(applicationContext.containsBean("client-with-attributes"));
|
||||
|
||||
Region<Long, String> clientRegion = context.getBean("client-with-attributes", Region.class);
|
||||
Region<Long, String> clientRegion = applicationContext.getBean("client-with-attributes", Region.class);
|
||||
|
||||
assertNotNull("The 'client-with-attributes' Client Region was not properly configured and initialized!", clientRegion);
|
||||
assertEquals("client-with-attributes", clientRegion.getName());
|
||||
@@ -258,9 +259,11 @@ public class ClientRegionNamespaceTest {
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testClientRegionWithRegisteredInterests() throws Exception {
|
||||
assertTrue(context.containsBean("client-with-interests"));
|
||||
|
||||
ClientRegionFactoryBean factoryBean = context.getBean("&client-with-interests", ClientRegionFactoryBean.class);
|
||||
assertTrue(applicationContext.containsBean("client-with-interests"));
|
||||
|
||||
ClientRegionFactoryBean factoryBean =
|
||||
applicationContext.getBean("&client-with-interests", ClientRegionFactoryBean.class);
|
||||
|
||||
assertNotNull(factoryBean);
|
||||
|
||||
@@ -276,10 +279,11 @@ public class ClientRegionNamespaceTest {
|
||||
|
||||
assertNotNull(mockClientRegion);
|
||||
|
||||
verify(mockClientRegion, times(1)).registerInterest(eq(".*"), eq(InterestResultPolicy.KEYS),
|
||||
eq(true), eq(false));
|
||||
verify(mockClientRegion, times(1)).registerInterestRegex(eq("keyPrefix.*"), eq(InterestResultPolicy.KEYS_VALUES),
|
||||
eq(true), eq(false));
|
||||
verify(mockClientRegion, times(1)).registerInterest(eq(".*"),
|
||||
eq(InterestResultPolicy.KEYS), eq(true), eq(false));
|
||||
|
||||
verify(mockClientRegion, times(1)).registerInterestRegex(eq("keyPrefix.*"),
|
||||
eq(InterestResultPolicy.KEYS_VALUES), eq(true), eq(false));
|
||||
}
|
||||
|
||||
protected void assertInterest(final boolean expectedDurable, final boolean expectedReceiveValues,
|
||||
@@ -300,38 +304,41 @@ public class ClientRegionNamespaceTest {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static final class MockCacheFactoryBean implements FactoryBean<ClientCache>, InitializingBean {
|
||||
static final class MockCacheFactoryBean implements FactoryBean<ClientCache>, InitializingBean {
|
||||
|
||||
protected static final AtomicReference<Region> MOCK_REGION_REF = new AtomicReference<Region>(null);
|
||||
static final AtomicReference<Region> MOCK_REGION_REF = new AtomicReference<Region>(null);
|
||||
|
||||
private ClientCache mockClientCache;
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
mockClientCache = mock(ClientCache.class, ClientRegionNamespaceTest.class.getSimpleName()
|
||||
.concat(".MockClientCache"));
|
||||
this.mockClientCache = mock(ClientCache.class,
|
||||
ClientRegionNamespaceTest.class.getSimpleName().concat(".MockClientCache"));
|
||||
|
||||
MOCK_REGION_REF.compareAndSet(null, mock(Region.class, ClientRegionNamespaceTest.class.getSimpleName()
|
||||
.concat(".MockClientRegion")));
|
||||
ClientRegionFactory mockClientRegionFactory = mock(ClientRegionFactory.class,
|
||||
ClientRegionNamespaceTest.class.getSimpleName().concat("MockClientRegionFactory"));
|
||||
|
||||
when(mockClientCache.getRegion(anyString())).thenReturn(MOCK_REGION_REF.get());
|
||||
when(this.mockClientCache.createClientRegionFactory(any(ClientRegionShortcut.class)))
|
||||
.thenReturn(mockClientRegionFactory);
|
||||
|
||||
Region mockRegion = mock(Region.class,
|
||||
ClientRegionNamespaceTest.class.getSimpleName().concat(".MockClientRegion"));
|
||||
|
||||
when(mockClientRegionFactory.create(anyString())).thenReturn(mockRegion);
|
||||
|
||||
MOCK_REGION_REF.compareAndSet(null, mockRegion);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientCache getObject() throws Exception {
|
||||
return mockClientCache;
|
||||
return this.mockClientCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return ClientCache.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class TestCacheLoader implements CacheLoader<Object, Object> {
|
||||
@@ -371,6 +378,5 @@ public class ClientRegionNamespaceTest {
|
||||
public String toString() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,15 +37,18 @@ import org.springframework.data.gemfire.RegionFactoryBean;
|
||||
*/
|
||||
public class InvalidRegionDefinitionUsingBeansNamespaceTest {
|
||||
|
||||
private static final String CONFIG_LOCATION =
|
||||
"org/springframework/data/gemfire/config/xml/InvalidDataPolicyPersistentAttributeSettingsBeansNamespaceTest.xml";
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testInvalidDataPolicyPersistentAttributeSettings() {
|
||||
try {
|
||||
new ClassPathXmlApplicationContext(
|
||||
"org/springframework/data/gemfire/config/xml/InvalidDataPolicyPersistentAttributeSettingsBeansNamespaceTest.xml");
|
||||
new ClassPathXmlApplicationContext(CONFIG_LOCATION);
|
||||
}
|
||||
catch (BeanCreationException expected) {
|
||||
assertTrue(expected.getCause() instanceof IllegalArgumentException);
|
||||
assertEquals("Data Policy 'REPLICATE' is invalid when persistent is true.", expected.getCause().getMessage());
|
||||
assertEquals("Data Policy [REPLICATE] is invalid when persistent is true.", expected.getCause().getMessage());
|
||||
|
||||
throw (IllegalArgumentException) expected.getCause();
|
||||
}
|
||||
}
|
||||
@@ -53,5 +56,4 @@ public class InvalidRegionDefinitionUsingBeansNamespaceTest {
|
||||
@SuppressWarnings("unused")
|
||||
public static final class TestRegionFactoryBean<K, V> extends RegionFactoryBean<K, V> {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -44,9 +44,9 @@ public class SubRegionWithInvalidDataPolicyTest {
|
||||
"/org/springframework/data/gemfire/config/xml/subregion-with-invalid-datapolicy.xml");
|
||||
}
|
||||
catch (XmlBeanDefinitionStoreException expected) {
|
||||
//expected.printStackTrace(System.err);
|
||||
assertTrue(expected.getCause() instanceof SAXParseException);
|
||||
assertTrue(expected.getCause().getMessage().contains("PERSISTENT_PARTITION"));
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
@@ -58,13 +58,12 @@ public class SubRegionWithInvalidDataPolicyTest {
|
||||
"/org/springframework/data/gemfire/config/xml/subregion-with-inconsistent-datapolicy-persistent-settings.xml");
|
||||
}
|
||||
catch (BeanCreationException expected) {
|
||||
//expected.printStackTrace(System.err);
|
||||
assertTrue(expected.getMessage().contains("Error creating bean with name '/Parent/Child'"));
|
||||
assertTrue(expected.getCause() instanceof IllegalArgumentException);
|
||||
assertEquals("Data Policy 'REPLICATE' is invalid when persistent is true.",
|
||||
assertEquals("Data Policy [REPLICATE] is invalid when persistent is true.",
|
||||
expected.getCause().getMessage());
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -84,6 +84,7 @@ public class ClientCacheFunctionExecutionWithPdxIntegrationTest extends ClientSe
|
||||
|
||||
@BeforeClass
|
||||
public static void startGemFireServer() throws Exception {
|
||||
|
||||
int availablePort = findAvailablePort();
|
||||
|
||||
gemfireServer = run(ServerProcess.class,
|
||||
@@ -101,8 +102,10 @@ public class ClientCacheFunctionExecutionWithPdxIntegrationTest extends ClientSe
|
||||
stop(gemfireServer);
|
||||
}
|
||||
|
||||
protected PdxInstance toPdxInstance(final Map<String, Object> pdxData) {
|
||||
PdxInstanceFactory pdxInstanceFactory = gemfireClientCache.createPdxInstanceFactory(pdxData.get("@type").toString());
|
||||
private PdxInstance toPdxInstance(Map<String, Object> pdxData) {
|
||||
|
||||
PdxInstanceFactory pdxInstanceFactory =
|
||||
gemfireClientCache.createPdxInstanceFactory(pdxData.get("@type").toString());
|
||||
|
||||
for (Map.Entry<String, Object> entry : pdxData.entrySet()) {
|
||||
pdxInstanceFactory.writeObject(entry.getKey(), entry.getValue());
|
||||
@@ -112,9 +115,10 @@ public class ClientCacheFunctionExecutionWithPdxIntegrationTest extends ClientSe
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvertedFunctionArgumentTypes() {
|
||||
Class[] argumentTypes = functionExecutions.captureConvertedArgumentTypes("test", 1, Boolean.TRUE,
|
||||
new Person("Jon", "Doe"), Gender.MALE);
|
||||
public void convertedFunctionArgumentTypes() {
|
||||
|
||||
Class[] argumentTypes = functionExecutions.captureConvertedArgumentTypes("test", 1,
|
||||
Boolean.TRUE, new Person("Jon", "Doe"), Gender.MALE);
|
||||
|
||||
assertNotNull(argumentTypes);
|
||||
assertEquals(5, argumentTypes.length);
|
||||
@@ -126,9 +130,10 @@ public class ClientCacheFunctionExecutionWithPdxIntegrationTest extends ClientSe
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnconvertedFunctionArgumentTypes() {
|
||||
Class[] argumentTypes = functionExecutions.captureUnconvertedArgumentTypes("test", 2, Boolean.FALSE,
|
||||
new Person("Jane", "Doe"), Gender.FEMALE);
|
||||
public void unconvertedFunctionArgumentTypes() {
|
||||
|
||||
Class[] argumentTypes = functionExecutions.captureUnconvertedArgumentTypes("test", 2,
|
||||
Boolean.FALSE, new Person("Jane", "Doe"), Gender.FEMALE);
|
||||
|
||||
assertNotNull(argumentTypes);
|
||||
assertEquals(5, argumentTypes.length);
|
||||
@@ -140,13 +145,14 @@ public class ClientCacheFunctionExecutionWithPdxIntegrationTest extends ClientSe
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAddressFieldValue() {
|
||||
public void getAddressFieldValue() {
|
||||
assertEquals("Portland", functionExecutions.getAddressField(new Address(
|
||||
"100 Main St.", "Portland", "OR", "97205"), "city"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPdxDataFieldValue() {
|
||||
public void pdxDataFieldValue() {
|
||||
|
||||
Map<String, Object> pdxData = new HashMap<String, Object>(3);
|
||||
|
||||
pdxData.put("@type", "x.y.z.domain.MyApplicationDomainType");
|
||||
@@ -162,6 +168,7 @@ public class ClientCacheFunctionExecutionWithPdxIntegrationTest extends ClientSe
|
||||
public static class ApplicationDomainFunctions {
|
||||
|
||||
private Class[] getArgumentTypes(final Object... arguments) {
|
||||
|
||||
Class[] argumentTypes = new Class[arguments.length];
|
||||
int index = 0;
|
||||
|
||||
@@ -174,25 +181,27 @@ public class ClientCacheFunctionExecutionWithPdxIntegrationTest extends ClientSe
|
||||
}
|
||||
|
||||
@GemfireFunction
|
||||
public Class[] captureConvertedArgumentTypes(final String stringValue, final Integer integerValue,
|
||||
final Boolean booleanValue, final Person person, final Gender gender) {
|
||||
public Class[] captureConvertedArgumentTypes(String stringValue, Integer integerValue, Boolean booleanValue,
|
||||
Person person, Gender gender) {
|
||||
|
||||
return getArgumentTypes(stringValue, integerValue, booleanValue, person, gender);
|
||||
}
|
||||
|
||||
@GemfireFunction
|
||||
public Class[] captureUnconvertedArgumentTypes(final String stringValue, final Integer integerValue,
|
||||
final Boolean booleanValue, final Object domainObject, final Object enumValue) {
|
||||
public Class[] captureUnconvertedArgumentTypes(String stringValue, Integer integerValue, Boolean booleanValue,
|
||||
Object domainObject, Object enumValue) {
|
||||
|
||||
return getArgumentTypes(stringValue, integerValue, booleanValue, domainObject, enumValue);
|
||||
}
|
||||
|
||||
@GemfireFunction
|
||||
public String getAddressField(final PdxInstance address, final String fieldName) {
|
||||
Assert.isTrue(Address.class.getName().equals(address.getClassName()));
|
||||
public String getAddressField(PdxInstance address, String fieldName) {
|
||||
Assert.isTrue(Address.class.getName().equals(address.getClassName()), "Address is not the correct type");
|
||||
return String.valueOf(address.getField(fieldName));
|
||||
}
|
||||
|
||||
@GemfireFunction
|
||||
public Object getDataField(final PdxInstance data, final String fieldName) {
|
||||
public Object getDataField(PdxInstance data, String fieldName) {
|
||||
return data.getField(fieldName);
|
||||
}
|
||||
}
|
||||
@@ -204,11 +213,12 @@ public class ClientCacheFunctionExecutionWithPdxIntegrationTest extends ClientSe
|
||||
private final String state; // refactor; use Enum!
|
||||
private final String zipCode;
|
||||
|
||||
public Address(final String street, final String city, final String state, final String zipCode) {
|
||||
public Address(String street, String city, String state, String zipCode) {
|
||||
Assert.hasText("The Address 'street' must be specified", street);
|
||||
Assert.hasText("The Address 'city' must be specified", city);
|
||||
Assert.hasText("The Address 'state' must be specified", state);
|
||||
Assert.hasText("The Address 'zipCode' must be specified", zipCode);
|
||||
|
||||
this.street = street;
|
||||
this.city = city;
|
||||
this.state = state;
|
||||
@@ -233,6 +243,7 @@ public class ClientCacheFunctionExecutionWithPdxIntegrationTest extends ClientSe
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
@@ -251,11 +262,14 @@ public class ClientCacheFunctionExecutionWithPdxIntegrationTest extends ClientSe
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
|
||||
int hashValue = 17;
|
||||
|
||||
hashValue = 37 * hashValue + ObjectUtils.nullSafeHashCode(getStreet());
|
||||
hashValue = 37 * hashValue + ObjectUtils.nullSafeHashCode(getCity());
|
||||
hashValue = 37 * hashValue + ObjectUtils.nullSafeHashCode(getState());
|
||||
hashValue = 37 * hashValue + ObjectUtils.nullSafeHashCode(getZipCode());
|
||||
|
||||
return hashValue;
|
||||
}
|
||||
|
||||
@@ -275,9 +289,10 @@ public class ClientCacheFunctionExecutionWithPdxIntegrationTest extends ClientSe
|
||||
private final String firstName;
|
||||
private final String lastName;
|
||||
|
||||
public Person(final String firstName, final String lastName) {
|
||||
public Person(String firstName, String lastName) {
|
||||
Assert.hasText(firstName, "The person's first name must be specified!");
|
||||
Assert.hasText(lastName, "The person's last name must be specified!");
|
||||
|
||||
this.firstName = firstName;
|
||||
this.lastName = lastName;
|
||||
}
|
||||
@@ -292,6 +307,7 @@ public class ClientCacheFunctionExecutionWithPdxIntegrationTest extends ClientSe
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
@@ -308,9 +324,12 @@ public class ClientCacheFunctionExecutionWithPdxIntegrationTest extends ClientSe
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
|
||||
int hashValue = 17;
|
||||
|
||||
hashValue = 37 * hashValue + ObjectUtils.nullSafeHashCode(getFirstName());
|
||||
hashValue = 37 * hashValue + ObjectUtils.nullSafeHashCode(getLastName());
|
||||
|
||||
return hashValue;
|
||||
}
|
||||
|
||||
@@ -324,18 +343,18 @@ public class ClientCacheFunctionExecutionWithPdxIntegrationTest extends ClientSe
|
||||
|
||||
private final PdxSerializer[] pdxSerializers;
|
||||
|
||||
private ComposablePdxSerializer(final PdxSerializer[] pdxSerializers) {
|
||||
private ComposablePdxSerializer(PdxSerializer[] pdxSerializers) {
|
||||
this.pdxSerializers = pdxSerializers;
|
||||
}
|
||||
|
||||
public static PdxSerializer compose(final PdxSerializer... pdxSerializers) {
|
||||
public static PdxSerializer compose(PdxSerializer... pdxSerializers) {
|
||||
return (pdxSerializers == null ? null : (pdxSerializers.length == 1 ? pdxSerializers[0]
|
||||
: new ComposablePdxSerializer(pdxSerializers)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean toData(final Object obj, final PdxWriter out) {
|
||||
for (PdxSerializer pdxSerializer : pdxSerializers) {
|
||||
public boolean toData(Object obj, PdxWriter out) {
|
||||
for (PdxSerializer pdxSerializer : this.pdxSerializers) {
|
||||
if (pdxSerializer.toData(obj, out)) {
|
||||
return true;
|
||||
}
|
||||
@@ -345,8 +364,8 @@ public class ClientCacheFunctionExecutionWithPdxIntegrationTest extends ClientSe
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object fromData(final Class<?> type, final PdxReader in) {
|
||||
for (PdxSerializer pdxSerializer : pdxSerializers) {
|
||||
public Object fromData(Class<?> type, final PdxReader in) {
|
||||
for (PdxSerializer pdxSerializer : this.pdxSerializers) {
|
||||
Object obj = pdxSerializer.fromData(type, in);
|
||||
|
||||
if (obj != null) {
|
||||
@@ -393,7 +412,8 @@ public class ClientCacheFunctionExecutionWithPdxIntegrationTest extends ClientSe
|
||||
public static class AddressPdxSerializer implements PdxSerializer {
|
||||
|
||||
@Override
|
||||
public boolean toData(final Object obj, final PdxWriter out) {
|
||||
public boolean toData(Object obj, PdxWriter out) {
|
||||
|
||||
if (obj instanceof Address) {
|
||||
Address address = (Address) obj;
|
||||
out.writeString("street", address.getStreet());
|
||||
@@ -407,7 +427,8 @@ public class ClientCacheFunctionExecutionWithPdxIntegrationTest extends ClientSe
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object fromData(final Class<?> type, final PdxReader in) {
|
||||
public Object fromData(Class<?> type, PdxReader in) {
|
||||
|
||||
if (Address.class.isAssignableFrom(type)) {
|
||||
return new Address(in.readString("street"), in.readString("city"), in.readString("state"),
|
||||
in.readString("zipCode"));
|
||||
@@ -419,7 +440,8 @@ public class ClientCacheFunctionExecutionWithPdxIntegrationTest extends ClientSe
|
||||
public static class PersonPdxSerializer implements PdxSerializer {
|
||||
|
||||
@Override
|
||||
public boolean toData(final Object obj, final PdxWriter out) {
|
||||
public boolean toData(Object obj, PdxWriter out) {
|
||||
|
||||
if (obj instanceof Person) {
|
||||
Person person = (Person) obj;
|
||||
out.writeString("firstName", person.getFirstName());
|
||||
@@ -431,7 +453,7 @@ public class ClientCacheFunctionExecutionWithPdxIntegrationTest extends ClientSe
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object fromData(final Class<?> type, final PdxReader in) {
|
||||
public Object fromData(Class<?> type, PdxReader in) {
|
||||
if (Person.class.isAssignableFrom(type)) {
|
||||
return new Person(in.readString("firstName"), in.readString("lastName"));
|
||||
}
|
||||
|
||||
@@ -32,44 +32,45 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ImportResource;
|
||||
import org.springframework.data.gemfire.function.execution.GemfireOnServerFunctionTemplate;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
* @author David Turanski
|
||||
*
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@RunWith(SpringRunner.class)
|
||||
@ContextConfiguration(classes = { TestClientCacheConfig.class })
|
||||
public class FunctionExecutionClientCacheTests {
|
||||
|
||||
@Autowired
|
||||
ApplicationContext context;
|
||||
ApplicationContext applicationContext;
|
||||
|
||||
@Test
|
||||
public void contextCreated() throws Exception {
|
||||
ClientCache cache = context.getBean("gemfireCache", ClientCache.class);
|
||||
Pool pool = context.getBean("gemfirePool", Pool.class);
|
||||
|
||||
ClientCache cache = applicationContext.getBean("gemfireCache", ClientCache.class);
|
||||
Pool pool = applicationContext.getBean("gemfirePool", Pool.class);
|
||||
|
||||
assertEquals("gemfirePool", pool.getName());
|
||||
assertTrue(cache.getDefaultPool().getLocators().isEmpty());
|
||||
assertEquals(1, cache.getDefaultPool().getServers().size());
|
||||
assertEquals(pool.getServers().get(0), cache.getDefaultPool().getServers().get(0));
|
||||
|
||||
Region region = context.getBean("r1", Region.class);
|
||||
Region region = applicationContext.getBean("r1", Region.class);
|
||||
|
||||
assertEquals("gemfirePool", region.getAttributes().getPoolName());
|
||||
|
||||
GemfireOnServerFunctionTemplate template = context.getBean(GemfireOnServerFunctionTemplate.class);
|
||||
GemfireOnServerFunctionTemplate template = applicationContext.getBean(GemfireOnServerFunctionTemplate.class);
|
||||
|
||||
assertTrue(template.getResultCollector() instanceof MyResultCollector);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ImportResource("/org/springframework/data/gemfire/function/config/FunctionExecutionCacheClientTests-context.xml")
|
||||
@EnableGemfireFunctionExecutions(basePackages = "org.springframework.data.gemfire.function.config.three")
|
||||
class TestClientCacheConfig {
|
||||
|
||||
@Bean
|
||||
MyResultCollector myResultCollector() {
|
||||
return new MyResultCollector();
|
||||
@@ -115,5 +116,4 @@ class MyResultCollector implements ResultCollector {
|
||||
public Object getResult(long arg0, TimeUnit arg1) throws FunctionException, InterruptedException {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,14 +23,12 @@ import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.FilterType;
|
||||
import org.springframework.data.gemfire.CacheFactoryBean;
|
||||
import org.springframework.data.gemfire.LocalRegionFactoryBean;
|
||||
import org.springframework.data.gemfire.config.annotation.PeerCacheApplication;
|
||||
import org.springframework.data.gemfire.repository.sample.Person;
|
||||
import org.springframework.data.gemfire.repository.sample.PersonRepository;
|
||||
import org.springframework.data.gemfire.test.GemfireTestApplicationContextInitializer;
|
||||
import org.springframework.data.gemfire.test.MockCacheFactoryBean;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
@@ -39,29 +37,24 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
* repository configuration).
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author John Blum
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(initializers=GemfireTestApplicationContextInitializer.class)
|
||||
public class GemfireRepositoriesRegistrarIntegrationTest {
|
||||
|
||||
@Configuration
|
||||
@PeerCacheApplication
|
||||
@EnableGemfireRepositories(value = "org.springframework.data.gemfire.repository.sample",
|
||||
includeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,
|
||||
value = org.springframework.data.gemfire.repository.sample.PersonRepository.class))
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
public GemFireCache cache() throws Exception {
|
||||
public Region<Long, Person> simple(GemFireCache gemfireCache) throws Exception {
|
||||
|
||||
CacheFactoryBean factory = new MockCacheFactoryBean();
|
||||
return factory.getObject();
|
||||
}
|
||||
LocalRegionFactoryBean<Long, Person> factory = new LocalRegionFactoryBean<>();
|
||||
|
||||
@Bean
|
||||
public Region<Long, Person> simple() throws Exception {
|
||||
|
||||
LocalRegionFactoryBean<Long, Person> factory = new LocalRegionFactoryBean<Long, Person>();
|
||||
factory.setCache(cache());
|
||||
factory.setCache(gemfireCache);
|
||||
factory.setName("simple");
|
||||
factory.afterPropertiesSet();
|
||||
|
||||
@@ -75,5 +68,4 @@ public class GemfireRepositoriesRegistrarIntegrationTest {
|
||||
@Test
|
||||
public void bootstrapsRepositoriesCorrectly() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ public class LuceneIndexFactoryBeanUnitTests {
|
||||
doReturn(mockCache).when(factoryBean).resolveCache();
|
||||
doReturn(mockLuceneService).when(factoryBean).resolveLuceneService();
|
||||
doReturn("/Example").when(factoryBean).resolveRegionPath();
|
||||
doReturn(mockLuceneIndex).when(factoryBean).createIndex(eq("ExampleIndex"), eq("/Example"));
|
||||
doReturn(mockLuceneIndex).when(factoryBean).createLuceneIndex(eq("ExampleIndex"), eq("/Example"));
|
||||
|
||||
factoryBean.setIndexName("ExampleIndex");
|
||||
|
||||
@@ -113,10 +113,10 @@ public class LuceneIndexFactoryBeanUnitTests {
|
||||
assertThat(factoryBean.getObject()).isEqualTo(mockLuceneIndex);
|
||||
|
||||
verify(factoryBean, times(1)).resolveCache();
|
||||
verify(factoryBean, times(1)).resolveLuceneService();
|
||||
verify(factoryBean, times(2)).resolveLuceneService();
|
||||
verify(factoryBean, times(1)).resolveRegionPath();
|
||||
verify(factoryBean, times(1))
|
||||
.createIndex(eq("ExampleIndex"), eq("/Example"));
|
||||
.createLuceneIndex(eq("ExampleIndex"), eq("/Example"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -129,7 +129,7 @@ public class LuceneIndexFactoryBeanUnitTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createIndexWithAllFields() {
|
||||
public void createLuceneIndexWithAllFields() {
|
||||
factoryBean.setLuceneService(mockLuceneService);
|
||||
|
||||
when(mockLuceneService.getIndex(eq("ExampleIndex"), eq("/Example"))).thenReturn(mockLuceneIndex);
|
||||
@@ -137,7 +137,7 @@ public class LuceneIndexFactoryBeanUnitTests {
|
||||
assertThat(factoryBean.getFieldAnalyzers()).isEmpty();
|
||||
assertThat(factoryBean.getFields()).isEmpty();
|
||||
assertThat(factoryBean.getLuceneService()).isSameAs(mockLuceneService);
|
||||
assertThat(factoryBean.createIndex("ExampleIndex", "/Example")).isEqualTo(mockLuceneIndex);
|
||||
assertThat(factoryBean.createLuceneIndex("ExampleIndex", "/Example")).isEqualTo(mockLuceneIndex);
|
||||
|
||||
verify(mockLuceneService, times(1))
|
||||
.createIndex(eq("ExampleIndex"), eq("/Example"), eq(LuceneService.REGION_VALUE_FIELD));
|
||||
@@ -146,7 +146,7 @@ public class LuceneIndexFactoryBeanUnitTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createIndexWithFieldAnalyzers() {
|
||||
public void createLuceneIndexWithFieldAnalyzers() {
|
||||
Map<String, Analyzer> fieldAnalyzers = Collections.singletonMap("fieldOne", mockAnalyzer);
|
||||
|
||||
factoryBean.setFieldAnalyzers(fieldAnalyzers);
|
||||
@@ -157,7 +157,7 @@ public class LuceneIndexFactoryBeanUnitTests {
|
||||
assertThat(factoryBean.getFieldAnalyzers()).isEqualTo(fieldAnalyzers);
|
||||
assertThat(factoryBean.getFields()).isEmpty();
|
||||
assertThat(factoryBean.getLuceneService()).isSameAs(mockLuceneService);
|
||||
assertThat(factoryBean.createIndex("ExampleIndex", "/Example")).isEqualTo(mockLuceneIndex);
|
||||
assertThat(factoryBean.createLuceneIndex("ExampleIndex", "/Example")).isEqualTo(mockLuceneIndex);
|
||||
|
||||
verify(mockLuceneService, times(1))
|
||||
.createIndex(eq("ExampleIndex"), eq("/Example"), eq(fieldAnalyzers));
|
||||
@@ -166,7 +166,7 @@ public class LuceneIndexFactoryBeanUnitTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createIndexWithTargetedFields() {
|
||||
public void createLuceneIndexWithTargetedFields() {
|
||||
factoryBean.setFields("fieldOne", "fieldTwo");
|
||||
factoryBean.setLuceneService(mockLuceneService);
|
||||
|
||||
@@ -175,7 +175,7 @@ public class LuceneIndexFactoryBeanUnitTests {
|
||||
assertThat(factoryBean.getFieldAnalyzers()).isEmpty();
|
||||
assertThat(factoryBean.getFields()).containsAll(Arrays.asList("fieldOne", "fieldTwo"));
|
||||
assertThat(factoryBean.getLuceneService()).isSameAs(mockLuceneService);
|
||||
assertThat(factoryBean.createIndex("ExampleIndex", "/Example")).isEqualTo(mockLuceneIndex);
|
||||
assertThat(factoryBean.createLuceneIndex("ExampleIndex", "/Example")).isEqualTo(mockLuceneIndex);
|
||||
|
||||
verify(mockLuceneService, times(1))
|
||||
.createIndex(eq("ExampleIndex"), eq("/Example"), eq("fieldOne"), eq("fieldTwo"));
|
||||
|
||||
@@ -44,11 +44,12 @@ import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
/**
|
||||
* The CacheServerFactoryBeanTest class is a test suite of test cases testing the contract and functionality
|
||||
* of the CacheServerFactoryBean class.
|
||||
* Unit tests for {@link CacheServerFactoryBean}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see org.apache.geode.cache.server.CacheServer
|
||||
* @see org.springframework.data.gemfire.server.CacheServerFactoryBean
|
||||
* @since 1.6.0
|
||||
*/
|
||||
@@ -146,7 +147,7 @@ public class CacheServerFactoryBeanTest {
|
||||
new CacheServerFactoryBean().afterPropertiesSet();
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
assertEquals("A GemFire Cache is required.", expected.getMessage());
|
||||
assertEquals("Cache is required", expected.getMessage());
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
@@ -228,5 +229,4 @@ public class CacheServerFactoryBeanTest {
|
||||
assertFalse(factoryBean.isRunning());
|
||||
assertTrue(called.get());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright 2017 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.support;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link AbstractFactoryBeanSupport}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mock
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.mockito.Spy
|
||||
* @see org.springframework.data.gemfire.support.AbstractFactoryBeanSupport
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class AbstractFactoryBeanSupportUnitTests {
|
||||
|
||||
@Mock
|
||||
private Log mockLog;
|
||||
|
||||
@Spy
|
||||
private TestFactoryBeanSupport<?> factoryBeanSupport;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
when(factoryBeanSupport.getLog()).thenReturn(mockLog);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setAndGetBeanClassLoader() {
|
||||
assertThat(factoryBeanSupport.getBeanClassLoader()).isNull();
|
||||
|
||||
ClassLoader mockClassLoader = mock(ClassLoader.class);
|
||||
|
||||
factoryBeanSupport.setBeanClassLoader(mockClassLoader);
|
||||
|
||||
assertThat(factoryBeanSupport.getBeanClassLoader()).isSameAs(mockClassLoader);
|
||||
|
||||
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
|
||||
|
||||
factoryBeanSupport.setBeanClassLoader(systemClassLoader);
|
||||
|
||||
assertThat(factoryBeanSupport.getBeanClassLoader()).isSameAs(systemClassLoader);
|
||||
|
||||
factoryBeanSupport.setBeanClassLoader(null);
|
||||
|
||||
assertThat(factoryBeanSupport.getBeanClassLoader()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setAndGetBeanFactory() {
|
||||
assertThat(factoryBeanSupport.getBeanFactory()).isNull();
|
||||
|
||||
BeanFactory mockBeanFactory = mock(BeanFactory.class);
|
||||
|
||||
factoryBeanSupport.setBeanFactory(mockBeanFactory);
|
||||
|
||||
assertThat(factoryBeanSupport.getBeanFactory()).isSameAs(mockBeanFactory);
|
||||
|
||||
factoryBeanSupport.setBeanFactory(null);
|
||||
|
||||
assertThat(factoryBeanSupport.getBeanFactory()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setAndGetBeanName() {
|
||||
assertThat(factoryBeanSupport.getBeanName()).isNullOrEmpty();
|
||||
|
||||
factoryBeanSupport.setBeanName("test");
|
||||
|
||||
assertThat(factoryBeanSupport.getBeanName()).isEqualTo("test");
|
||||
|
||||
factoryBeanSupport.setBeanName(null);
|
||||
|
||||
assertThat(factoryBeanSupport.getBeanName()).isNullOrEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSingletonDefaultsToTrue() {
|
||||
assertThat(factoryBeanSupport.isSingleton()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void logsDebugWhenDebugIsEnabled() {
|
||||
when(mockLog.isDebugEnabled()).thenReturn(true);
|
||||
|
||||
factoryBeanSupport.logDebug("%s log test", "debug");
|
||||
|
||||
verify(mockLog, times(1)).isDebugEnabled();
|
||||
verify(mockLog, times(1)).debug(eq("debug log test"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void logsInfoWhenInfoIsEnabled() {
|
||||
when(mockLog.isInfoEnabled()).thenReturn(true);
|
||||
|
||||
factoryBeanSupport.logInfo("%s log test", "info");
|
||||
|
||||
verify(mockLog, times(1)).isInfoEnabled();
|
||||
verify(mockLog, times(1)).info(eq("info log test"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void suppressesDebugLoggingWhenDebugIsDisabled() {
|
||||
when(mockLog.isDebugEnabled()).thenReturn(false);
|
||||
|
||||
factoryBeanSupport.logDebug(() -> "test");
|
||||
|
||||
verify(mockLog, times(1)).isDebugEnabled();
|
||||
verify(mockLog, never()).debug(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void suppressesInfoLoggingWhenInfoIsDisabled() {
|
||||
when(mockLog.isInfoEnabled()).thenReturn(false);
|
||||
|
||||
factoryBeanSupport.logInfo(() -> "test");
|
||||
|
||||
verify(mockLog, times(1)).isInfoEnabled();
|
||||
verify(mockLog, never()).info(any());
|
||||
}
|
||||
|
||||
private static class TestFactoryBeanSupport<T> extends AbstractFactoryBeanSupport<T> {
|
||||
|
||||
@Override
|
||||
public T getObject() throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return Object.class;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,8 @@
|
||||
|
||||
package org.springframework.data.gemfire.test;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.springframework.data.gemfire.CacheFactoryBean;
|
||||
|
||||
@@ -27,36 +29,39 @@ public class MockCacheFactoryBean extends CacheFactoryBean {
|
||||
}
|
||||
|
||||
public MockCacheFactoryBean(CacheFactoryBean cacheFactoryBean) {
|
||||
|
||||
setUseBeanFactoryLocator(false);
|
||||
|
||||
if (cacheFactoryBean != null) {
|
||||
setBeanClassLoader(cacheFactoryBean.getBeanClassLoader());
|
||||
setBeanFactory(cacheFactoryBean.getBeanFactory());
|
||||
setBeanName(cacheFactoryBean.getBeanName());
|
||||
setCacheXml(cacheFactoryBean.getCacheXml());
|
||||
setPhase(cacheFactoryBean.getPhase());
|
||||
setProperties(cacheFactoryBean.getProperties());
|
||||
setClose(cacheFactoryBean.getClose());
|
||||
setCopyOnRead(cacheFactoryBean.getCopyOnRead());
|
||||
setCriticalHeapPercentage(cacheFactoryBean.getCriticalHeapPercentage());
|
||||
setDynamicRegionSupport(cacheFactoryBean.getDynamicRegionSupport());
|
||||
setEnableAutoReconnect(cacheFactoryBean.getEnableAutoReconnect());
|
||||
setEvictionHeapPercentage(cacheFactoryBean.getEvictionHeapPercentage());
|
||||
setGatewayConflictResolver(cacheFactoryBean.getGatewayConflictResolver());
|
||||
setJndiDataSources(cacheFactoryBean.getJndiDataSources());
|
||||
setLockLease(cacheFactoryBean.getLockLease());
|
||||
setLockTimeout(cacheFactoryBean.getLockTimeout());
|
||||
setMessageSyncInterval(cacheFactoryBean.getMessageSyncInterval());
|
||||
setPdxDiskStoreName(cacheFactoryBean.getPdxDiskStoreName());
|
||||
setPdxIgnoreUnreadFields(cacheFactoryBean.getPdxIgnoreUnreadFields());
|
||||
setPdxPersistent(cacheFactoryBean.getPdxPersistent());
|
||||
setPdxReadSerialized(cacheFactoryBean.getPdxReadSerialized());
|
||||
setPdxSerializer(cacheFactoryBean.getPdxSerializer());
|
||||
setSearchTimeout(cacheFactoryBean.getSearchTimeout());
|
||||
setTransactionListeners(cacheFactoryBean.getTransactionListeners());
|
||||
setTransactionWriter(cacheFactoryBean.getTransactionWriter());
|
||||
setUseBeanFactoryLocator(cacheFactoryBean.isUseBeanFactoryLocator());
|
||||
}
|
||||
Optional.ofNullable(cacheFactoryBean).ifPresent(it -> {
|
||||
setBeanClassLoader(it.getBeanClassLoader());
|
||||
setBeanFactory(it.getBeanFactory());
|
||||
setBeanName(it.getBeanName());
|
||||
setCacheXml(it.getCacheXml());
|
||||
setPhase(it.getPhase());
|
||||
setProperties(it.getProperties());
|
||||
setClose(it.isClose());
|
||||
setCopyOnRead(it.getCopyOnRead());
|
||||
setCriticalHeapPercentage(it.getCriticalHeapPercentage());
|
||||
setDynamicRegionSupport(it.getDynamicRegionSupport());
|
||||
setEnableAutoReconnect(it.getEnableAutoReconnect());
|
||||
setEvictionHeapPercentage(it.getEvictionHeapPercentage());
|
||||
setGatewayConflictResolver(it.getGatewayConflictResolver());
|
||||
setJndiDataSources(it.getJndiDataSources());
|
||||
setLockLease(it.getLockLease());
|
||||
setLockTimeout(it.getLockTimeout());
|
||||
setMessageSyncInterval(it.getMessageSyncInterval());
|
||||
setPdxDiskStoreName(it.getPdxDiskStoreName());
|
||||
setPdxIgnoreUnreadFields(it.getPdxIgnoreUnreadFields());
|
||||
setPdxPersistent(it.getPdxPersistent());
|
||||
setPdxReadSerialized(it.getPdxReadSerialized());
|
||||
setPdxSerializer(it.getPdxSerializer());
|
||||
setSearchTimeout(it.getSearchTimeout());
|
||||
setTransactionListeners(it.getTransactionListeners());
|
||||
setTransactionWriter(it.getTransactionWriter());
|
||||
setUseBeanFactoryLocator(it.isUseBeanFactoryLocator());
|
||||
});
|
||||
|
||||
applyPeerCacheConfigurers(cacheFactoryBean.getCompositePeerCacheConfigurer());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -66,5 +71,4 @@ public class MockCacheFactoryBean extends CacheFactoryBean {
|
||||
stubCache.setProperties(getProperties());
|
||||
return (T) stubCache;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
*/
|
||||
package org.springframework.data.gemfire.test;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.springframework.data.gemfire.client.ClientCacheFactoryBean;
|
||||
|
||||
@@ -22,38 +24,41 @@ import org.springframework.data.gemfire.client.ClientCacheFactoryBean;
|
||||
public class MockClientCacheFactoryBean extends ClientCacheFactoryBean {
|
||||
|
||||
public MockClientCacheFactoryBean(ClientCacheFactoryBean clientCacheFactoryBean) {
|
||||
|
||||
setUseBeanFactoryLocator(false);
|
||||
|
||||
if (clientCacheFactoryBean != null) {
|
||||
this.beanFactoryLocator = clientCacheFactoryBean.getBeanFactoryLocator();
|
||||
setBeanClassLoader(clientCacheFactoryBean.getBeanClassLoader());
|
||||
setBeanFactory(clientCacheFactoryBean.getBeanFactory());
|
||||
setBeanName(clientCacheFactoryBean.getBeanName());
|
||||
setCacheXml(clientCacheFactoryBean.getCacheXml());
|
||||
setCopyOnRead(clientCacheFactoryBean.getCopyOnRead());
|
||||
setCriticalHeapPercentage(clientCacheFactoryBean.getCriticalHeapPercentage());
|
||||
setDurableClientId(clientCacheFactoryBean.getDurableClientId());
|
||||
setDurableClientTimeout(clientCacheFactoryBean.getDurableClientTimeout());
|
||||
setDynamicRegionSupport(clientCacheFactoryBean.getDynamicRegionSupport());
|
||||
setEvictionHeapPercentage(clientCacheFactoryBean.getEvictionHeapPercentage());
|
||||
setGatewayConflictResolver(clientCacheFactoryBean.getGatewayConflictResolver());
|
||||
setJndiDataSources(clientCacheFactoryBean.getJndiDataSources());
|
||||
setKeepAlive(clientCacheFactoryBean.isKeepAlive());
|
||||
setLockLease(clientCacheFactoryBean.getLockLease());
|
||||
setLockTimeout(clientCacheFactoryBean.getLockTimeout());
|
||||
setMessageSyncInterval(clientCacheFactoryBean.getMessageSyncInterval());
|
||||
setPdxDiskStoreName(clientCacheFactoryBean.getPdxDiskStoreName());
|
||||
setPdxIgnoreUnreadFields(clientCacheFactoryBean.getPdxIgnoreUnreadFields());
|
||||
setPdxPersistent(clientCacheFactoryBean.getPdxPersistent());
|
||||
setPdxReadSerialized(clientCacheFactoryBean.getPdxReadSerialized());
|
||||
setPdxSerializer(clientCacheFactoryBean.getPdxSerializer());
|
||||
setPoolName(clientCacheFactoryBean.getPoolName());
|
||||
setProperties(clientCacheFactoryBean.getProperties());
|
||||
setReadyForEvents(clientCacheFactoryBean.getReadyForEvents());
|
||||
setSearchTimeout(clientCacheFactoryBean.getSearchTimeout());
|
||||
setTransactionListeners(clientCacheFactoryBean.getTransactionListeners());
|
||||
setTransactionWriter(clientCacheFactoryBean.getTransactionWriter());
|
||||
}
|
||||
Optional.ofNullable(clientCacheFactoryBean).ifPresent(it -> {
|
||||
this.beanFactoryLocator = it.getBeanFactoryLocator();
|
||||
setBeanClassLoader(it.getBeanClassLoader());
|
||||
setBeanFactory(it.getBeanFactory());
|
||||
setBeanName(it.getBeanName());
|
||||
setCacheXml(it.getCacheXml());
|
||||
setCopyOnRead(it.getCopyOnRead());
|
||||
setCriticalHeapPercentage(it.getCriticalHeapPercentage());
|
||||
setDurableClientId(it.getDurableClientId());
|
||||
setDurableClientTimeout(it.getDurableClientTimeout());
|
||||
setDynamicRegionSupport(it.getDynamicRegionSupport());
|
||||
setEvictionHeapPercentage(it.getEvictionHeapPercentage());
|
||||
setGatewayConflictResolver(it.getGatewayConflictResolver());
|
||||
setJndiDataSources(it.getJndiDataSources());
|
||||
setKeepAlive(it.isKeepAlive());
|
||||
setLockLease(it.getLockLease());
|
||||
setLockTimeout(it.getLockTimeout());
|
||||
setMessageSyncInterval(it.getMessageSyncInterval());
|
||||
setPdxDiskStoreName(it.getPdxDiskStoreName());
|
||||
setPdxIgnoreUnreadFields(it.getPdxIgnoreUnreadFields());
|
||||
setPdxPersistent(it.getPdxPersistent());
|
||||
setPdxReadSerialized(it.getPdxReadSerialized());
|
||||
setPdxSerializer(it.getPdxSerializer());
|
||||
setPoolName(it.getPoolName());
|
||||
setProperties(it.getProperties());
|
||||
setReadyForEvents(it.getReadyForEvents());
|
||||
setSearchTimeout(it.getSearchTimeout());
|
||||
setTransactionListeners(it.getTransactionListeners());
|
||||
setTransactionWriter(it.getTransactionWriter());
|
||||
});
|
||||
|
||||
applyClientCacheConfigurers(clientCacheFactoryBean.getCompositeClientCacheConfigurer());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -62,6 +67,4 @@ public class MockClientCacheFactoryBean extends ClientCacheFactoryBean {
|
||||
stubCache.setProperties(getProperties());
|
||||
return (T) stubCache;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -16,18 +16,17 @@
|
||||
<context:property-placeholder/>
|
||||
|
||||
<util:properties id="gemfireProperties">
|
||||
<prop key="log-level">warning</prop>
|
||||
<prop key="log-level">config</prop>
|
||||
</util:properties>
|
||||
|
||||
<gfe:pool id="serverConnectionPool">
|
||||
<gfe:server host="localhost" port="${spring.data.gemfire.cache.server.port:40404}"/>
|
||||
</gfe:pool>
|
||||
<bean id="addressPdxSerializer"
|
||||
class="org.springframework.data.gemfire.function.ClientCacheFunctionExecutionWithPdxIntegrationTest$AddressPdxSerializer"/>
|
||||
|
||||
<bean id="addressPdxSerializer" class="org.springframework.data.gemfire.function.ClientCacheFunctionExecutionWithPdxIntegrationTest$AddressPdxSerializer"/>
|
||||
<bean id="personPdxSerializer"
|
||||
class="org.springframework.data.gemfire.function.ClientCacheFunctionExecutionWithPdxIntegrationTest$PersonPdxSerializer"/>
|
||||
|
||||
<bean id="personPdxSerializer" class="org.springframework.data.gemfire.function.ClientCacheFunctionExecutionWithPdxIntegrationTest$PersonPdxSerializer"/>
|
||||
|
||||
<bean id="domainBasedPdxSerializer" class="org.springframework.data.gemfire.function.ClientCacheFunctionExecutionWithPdxIntegrationTest$ComposablePdxSerializerFactoryBean">
|
||||
<bean id="domainBasedPdxSerializer"
|
||||
class="org.springframework.data.gemfire.function.ClientCacheFunctionExecutionWithPdxIntegrationTest$ComposablePdxSerializerFactoryBean">
|
||||
<property name="pdxSerializers">
|
||||
<list>
|
||||
<ref bean="addressPdxSerializer"/>
|
||||
@@ -38,6 +37,10 @@
|
||||
|
||||
<gfe:client-cache properties-ref="gemfireProperties" pool-name="serverConnectionPool" pdx-serializer-ref="domainBasedPdxSerializer"/>
|
||||
|
||||
<gfe:pool id="serverConnectionPool">
|
||||
<gfe:server host="localhost" port="${spring.data.gemfire.cache.server.port:40404}"/>
|
||||
</gfe:pool>
|
||||
|
||||
<gfe-data:function-executions base-package="org.springframework.data.gemfire.function.sample">
|
||||
<gfe-data:include-filter type="assignable" expression="org.springframework.data.gemfire.function.sample.ApplicationDomainFunctionExecutions"/>
|
||||
</gfe-data:function-executions>
|
||||
|
||||
@@ -15,14 +15,17 @@
|
||||
<util:properties id="gemfireProperties">
|
||||
<prop key="name">SpringGemFireServerFunctionCreationWithPdx</prop>
|
||||
<prop key="mcast-port">0</prop>
|
||||
<prop key="log-level">warning</prop>
|
||||
<prop key="log-level">config</prop>
|
||||
</util:properties>
|
||||
|
||||
<bean id="addressPdxSerializer" class="org.springframework.data.gemfire.function.ClientCacheFunctionExecutionWithPdxIntegrationTest$AddressPdxSerializer"/>
|
||||
<bean id="addressPdxSerializer"
|
||||
class="org.springframework.data.gemfire.function.ClientCacheFunctionExecutionWithPdxIntegrationTest$AddressPdxSerializer"/>
|
||||
|
||||
<bean id="personPdxSerializer" class="org.springframework.data.gemfire.function.ClientCacheFunctionExecutionWithPdxIntegrationTest$PersonPdxSerializer"/>
|
||||
<bean id="personPdxSerializer"
|
||||
class="org.springframework.data.gemfire.function.ClientCacheFunctionExecutionWithPdxIntegrationTest$PersonPdxSerializer"/>
|
||||
|
||||
<bean id="domainBasedPdxSerializer" class="org.springframework.data.gemfire.function.ClientCacheFunctionExecutionWithPdxIntegrationTest$ComposablePdxSerializerFactoryBean">
|
||||
<bean id="domainBasedPdxSerializer"
|
||||
class="org.springframework.data.gemfire.function.ClientCacheFunctionExecutionWithPdxIntegrationTest$ComposablePdxSerializerFactoryBean">
|
||||
<property name="pdxSerializers">
|
||||
<list>
|
||||
<ref bean="addressPdxSerializer"/>
|
||||
|
||||
Reference in New Issue
Block a user