From 043cc922b95b0620b7ddb76b7bb19d96498d2561 Mon Sep 17 00:00:00 2001 From: John Blum Date: Wed, 8 Mar 2017 22:33:47 -0800 Subject: [PATCH] SGF-603 - Add ignoreIfExists attribute defaulted to true in @Region annotations for @EnableEntityDefinedRegions. --- .../data/gemfire/RegionLookupFactoryBean.java | 12 +- .../EnableEntityDefinedRegions.java | 18 +- .../EntityDefinedRegionsConfiguration.java | 102 ++++---- .../mapping/annotation/ClientRegion.java | 13 +- .../mapping/annotation/LocalRegion.java | 14 +- .../mapping/annotation/PartitionRegion.java | 13 +- .../gemfire/mapping/annotation/Region.java | 10 + .../mapping/annotation/ReplicateRegion.java | 13 +- .../data/gemfire/util/CacheUtils.java | 7 + .../gemfire/util/DistributedSystemUtils.java | 3 +- .../data/gemfire/util/SpringUtils.java | 5 +- ...yDefinedRegionsConfigurationUnitTests.java | 225 +++++++++++++----- .../test/entities/PartitionRegionEntity.java | 2 +- 13 files changed, 308 insertions(+), 129 deletions(-) diff --git a/src/main/java/org/springframework/data/gemfire/RegionLookupFactoryBean.java b/src/main/java/org/springframework/data/gemfire/RegionLookupFactoryBean.java index f731eb99..5929f566 100644 --- a/src/main/java/org/springframework/data/gemfire/RegionLookupFactoryBean.java +++ b/src/main/java/org/springframework/data/gemfire/RegionLookupFactoryBean.java @@ -16,6 +16,8 @@ package org.springframework.data.gemfire; +import java.util.Optional; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.geode.cache.GemFireCache; @@ -39,11 +41,12 @@ import org.springframework.util.StringUtils; * @see org.apache.geode.cache.Region */ @SuppressWarnings("unused") -public abstract class RegionLookupFactoryBean implements FactoryBean>, InitializingBean, BeanNameAware { +public abstract class RegionLookupFactoryBean + implements FactoryBean>, InitializingBean, BeanNameAware { protected final Log log = LogFactory.getLog(getClass()); - private Boolean lookupEnabled = Boolean.TRUE; + private Boolean lookupEnabled = false; private GemFireCache cache; @@ -69,8 +72,9 @@ public abstract class RegionLookupFactoryBean implements FactoryBeangetSubregion(regionName) - : this.cache.getRegion(regionName)); + this.region = Optional.ofNullable(getParent()) + .map(parentRegion -> parentRegion.getSubregion(regionName)) + .orElseGet(() -> this.cache.getRegion(regionName)); } if (region != null) { diff --git a/src/main/java/org/springframework/data/gemfire/config/annotation/EnableEntityDefinedRegions.java b/src/main/java/org/springframework/data/gemfire/config/annotation/EnableEntityDefinedRegions.java index 9a798336..6d37bafb 100644 --- a/src/main/java/org/springframework/data/gemfire/config/annotation/EnableEntityDefinedRegions.java +++ b/src/main/java/org/springframework/data/gemfire/config/annotation/EnableEntityDefinedRegions.java @@ -39,9 +39,7 @@ import org.springframework.core.annotation.AliasFor; * @see org.springframework.context.annotation.ComponentScan.Filter * @see org.springframework.context.annotation.Import * @see org.springframework.core.annotation.AliasFor - * @see org.springframework.data.gemfire.config.annotation.EnableIndexes * @see org.springframework.data.gemfire.config.annotation.EntityDefinedRegionsConfiguration - * @see org.springframework.data.gemfire.config.annotation.IndexConfiguration * @see org.apache.geode.cache.Region * @since 1.9.0 */ @@ -84,6 +82,14 @@ public @interface EnableEntityDefinedRegions { */ Class[] basePackageClasses() default {}; + /** + * Specifies which types are not eligible for component scanning. + * + * @return an array of {@link org.springframework.context.annotation.ComponentScan.Filter Filters} used to + * specify application persistent entities to be excluded during the component scan. + */ + 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 @@ -94,14 +100,6 @@ public @interface EnableEntityDefinedRegions { */ ComponentScan.Filter[] includeFilters() default {}; - /** - * Specifies which types are not eligible for component scanning. - * - * @return an array of {@link org.springframework.context.annotation.ComponentScan.Filter Filters} used to - * specify application persistent entities to be excluded during the component scan. - */ - ComponentScan.Filter[] excludeFilters() default {}; - /** * Determines whether the created {@link Region} will have strongly-typed key and value constraints * based on the ID and {@link Class} type of application persistent entity. diff --git a/src/main/java/org/springframework/data/gemfire/config/annotation/EntityDefinedRegionsConfiguration.java b/src/main/java/org/springframework/data/gemfire/config/annotation/EntityDefinedRegionsConfiguration.java index cd1a1e98..5d6ec597 100644 --- a/src/main/java/org/springframework/data/gemfire/config/annotation/EntityDefinedRegionsConfiguration.java +++ b/src/main/java/org/springframework/data/gemfire/config/annotation/EntityDefinedRegionsConfiguration.java @@ -17,14 +17,16 @@ package org.springframework.data.gemfire.config.annotation; -import static org.apache.geode.internal.lang.ObjectUtils.defaultIfNull; +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 java.lang.annotation.Annotation; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.regex.Pattern; @@ -67,7 +69,6 @@ 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.util.ArrayUtils; import org.springframework.data.gemfire.util.CollectionUtils; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -80,6 +81,7 @@ import org.springframework.util.StringUtils; * based on the application persistent entity classes. * * @author John Blum + * @see java.lang.annotation.Annotation * @see org.springframework.beans.factory.BeanClassLoaderAware * @see org.springframework.beans.factory.BeanFactory * @see org.springframework.beans.factory.BeanFactoryAware @@ -87,19 +89,23 @@ import org.springframework.util.StringUtils; * @see org.springframework.beans.factory.support.BeanDefinitionBuilder * @see org.springframework.beans.factory.support.BeanDefinitionRegistry * @see org.springframework.context.annotation.ImportBeanDefinitionRegistrar + * @see org.springframework.data.gemfire.FixedPartitionAttributesFactoryBean * @see org.springframework.data.gemfire.LocalRegionFactoryBean + * @see org.springframework.data.gemfire.PartitionAttributesFactoryBean * @see org.springframework.data.gemfire.PartitionedRegionFactoryBean + * @see org.springframework.data.gemfire.RegionAttributesFactoryBean * @see org.springframework.data.gemfire.ReplicatedRegionFactoryBean * @see org.springframework.data.gemfire.client.ClientRegionFactoryBean * @see org.springframework.data.gemfire.config.annotation.support.GemFireCacheTypeAwareRegionFactoryBean * @see org.springframework.data.gemfire.config.annotation.support.GemFireComponentClassTypeScanner - * @see org.springframework.data.gemfire.mapping.annotation.ClientRegion * @see org.springframework.data.gemfire.mapping.GemfireMappingContext * @see org.springframework.data.gemfire.mapping.GemfirePersistentEntity + * @see org.springframework.data.gemfire.mapping.annotation.ClientRegion * @see org.springframework.data.gemfire.mapping.annotation.LocalRegion * @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 */ @SuppressWarnings("unused") @@ -229,16 +235,16 @@ public class EntityDefinedRegionsConfiguration /* (non-Javadoc) */ protected GemfireMappingContext resolveMappingContext() { - if (this.mappingContext == null) { + return Optional.ofNullable(this.mappingContext).orElseGet(() -> { try { this.mappingContext = getBeanFactory().getBean(GemfireMappingContext.class); } catch (Throwable ignore) { this.mappingContext = new GemfireMappingContext(); } - } - return this.mappingContext; + return this.mappingContext; + }); } /** @@ -281,15 +287,14 @@ public class EntityDefinedRegionsConfiguration Set resolvedBasePackages = new HashSet<>(); - Collections.addAll(resolvedBasePackages, ArrayUtils.nullSafeArray(defaultIfEmpty( + Collections.addAll(resolvedBasePackages, nullSafeArray(defaultIfEmpty( enableEntityDefinedRegionAttributes.getStringArray("basePackages"), - enableEntityDefinedRegionAttributes.getStringArray("value")), String.class)); + enableEntityDefinedRegionAttributes.getStringArray("value")), + String.class)); - for (Class type : ArrayUtils.nullSafeArray( - enableEntityDefinedRegionAttributes.getClassArray("basePackageClasses"), Class.class)) { - - resolvedBasePackages.add(type.getPackage().getName()); - } + stream(nullSafeArray(enableEntityDefinedRegionAttributes.getClassArray( + "basePackageClasses"), Class.class)) + .forEach(type -> resolvedBasePackages.add(type.getPackage().getName())); if (resolvedBasePackages.isEmpty()) { resolvedBasePackages.add(ClassUtils.getPackageName(importingClassMetaData.getClassName())); @@ -300,7 +305,8 @@ public class EntityDefinedRegionsConfiguration /* (non-Javadoc) */ protected ClassLoader resolveBeanClassLoader() { - return (this.beanClassLoader != null ? this.beanClassLoader : Thread.currentThread().getContextClassLoader()); + return Optional.ofNullable(this.beanClassLoader) + .orElseGet(() -> Thread.currentThread().getContextClassLoader()); } /* (non-Javadoc) */ @@ -317,11 +323,8 @@ public class EntityDefinedRegionsConfiguration private Iterable parseFilters(AnnotationAttributes[] componentScanFilterAttributes) { Set typeFilters = new HashSet<>(); - for (AnnotationAttributes filterAttributes : ArrayUtils.nullSafeArray( - componentScanFilterAttributes, AnnotationAttributes.class)) { - - CollectionUtils.addAll(typeFilters, typeFiltersFor(filterAttributes)); - } + stream(nullSafeArray(componentScanFilterAttributes, AnnotationAttributes.class)) + .forEach(filterAttributes -> CollectionUtils.addAll(typeFilters, typeFiltersFor(filterAttributes))); return typeFilters; } @@ -332,7 +335,7 @@ public class EntityDefinedRegionsConfiguration Set typeFilters = new HashSet<>(); FilterType filterType = filterAttributes.getEnum("type"); - for (Class filterClass : ArrayUtils.nullSafeArray(filterAttributes.getClassArray("value"), Class.class)) { + for (Class filterClass : nullSafeArray(filterAttributes.getClassArray("value"), Class.class)) { switch (filterType) { case ANNOTATION: Assert.isAssignable(Annotation.class, filterClass, @@ -379,7 +382,7 @@ public class EntityDefinedRegionsConfiguration */ private String[] nullSafeGetPatterns(AnnotationAttributes filterAttributes) { try { - return ArrayUtils.nullSafeArray(filterAttributes.getStringArray("pattern"), String.class); + return nullSafeArray(filterAttributes.getStringArray("pattern"), String.class); } catch (IllegalArgumentException ignore) { return new String[0]; @@ -391,11 +394,8 @@ public class EntityDefinedRegionsConfiguration protected Iterable regionAnnotatedPersistentEntityTypeFilters() { Set regionAnnotatedPersistentEntityTypeFilters = new HashSet<>(); - for (Class annotationType : - org.springframework.data.gemfire.mapping.annotation.Region.REGION_ANNOTATION_TYPES) { - - regionAnnotatedPersistentEntityTypeFilters.add(new AnnotationTypeFilter(annotationType)); - } + org.springframework.data.gemfire.mapping.annotation.Region.REGION_ANNOTATION_TYPES.forEach( + annotationType -> regionAnnotatedPersistentEntityTypeFilters.add(new AnnotationTypeFilter(annotationType))); return regionAnnotatedPersistentEntityTypeFilters; } @@ -420,19 +420,17 @@ public class EntityDefinedRegionsConfiguration protected Class resolveRegionFactoryBeanClass( GemfirePersistentEntity persistentEntity) { - return defaultIfNull(regionAnnotationToRegionFactoryBeanClass.get(persistentEntity.getRegionAnnotationType()), - DEFAULT_REGION_FACTORY_BEAN_CLASS); + return Optional.>ofNullable( + regionAnnotationToRegionFactoryBeanClass.get(persistentEntity.getRegionAnnotationType())) + .orElse(DEFAULT_REGION_FACTORY_BEAN_CLASS); } /* (non-Javadoc) */ protected BeanDefinitionBuilder setRegionAttributes(GemfirePersistentEntity persistentEntity, BeanDefinitionBuilder regionFactoryBeanBuilder, boolean strict) { - Annotation regionAnnotation = persistentEntity.getRegionAnnotation(); - - if (regionAnnotation != null) { - AnnotationAttributes regionAnnotationAttributes = - AnnotationAttributes.fromMap(AnnotationUtils.getAnnotationAttributes(regionAnnotation)); + Optional.ofNullable(persistentEntity.getRegionAnnotation()).ifPresent(regionAnnotation -> { + AnnotationAttributes regionAnnotationAttributes = getAnnotationAttributes(regionAnnotation); if (strict) { regionFactoryBeanBuilder.addPropertyValue("keyConstraint", resolveIdType(persistentEntity)); @@ -442,13 +440,19 @@ public class EntityDefinedRegionsConfiguration if (regionAnnotationAttributes.containsKey("diskStoreName")) { String diskStoreName = regionAnnotationAttributes.getString("diskStoreName"); - setPropertyValueIfNotDefault(regionFactoryBeanBuilder, "diskStoreName", diskStoreName, ""); + setPropertyValueIfNotDefault(regionFactoryBeanBuilder, "diskStoreName", + diskStoreName, ""); if (StringUtils.hasText(diskStoreName)) { regionFactoryBeanBuilder.addDependsOn(diskStoreName); } } + if (regionAnnotationAttributes.containsKey("ignoreIfExists")) { + regionFactoryBeanBuilder.addPropertyValue("lookupEnabled", + regionAnnotationAttributes.getBoolean("ignoreIfExists")); + } + if (regionAnnotationAttributes.containsKey("persistent")) { setPropertyValueIfNotDefault(regionFactoryBeanBuilder, "persistent", regionAnnotationAttributes.getBoolean("persistent"), false); @@ -473,21 +477,21 @@ public class EntityDefinedRegionsConfiguration regionAttributesFactoryBeanBuilder); setReplicateRegionAttributes(regionAnnotationAttributes, regionFactoryBeanBuilder); - - } + }); return regionFactoryBeanBuilder; } /* (non-Javadoc) */ protected Class resolveDomainType(GemfirePersistentEntity persistentEntity) { - return defaultIfNull(persistentEntity.getType(), Object.class); + return Optional.ofNullable(persistentEntity.getType()).orElse(Object.class); } /* (non-Javadoc) */ protected Class resolveIdType(GemfirePersistentEntity persistentEntity) { - return (persistentEntity.hasIdProperty() ? - defaultIfNull(persistentEntity.getIdProperty().getActualType(), Object.class) : Object.class); + return (persistentEntity.hasIdProperty() + ? Optional.ofNullable(persistentEntity.getIdProperty().getActualType()).orElse(Object.class) + : Object.class); } /* (non-Javadoc) */ @@ -497,8 +501,8 @@ public class EntityDefinedRegionsConfiguration BeanDefinitionBuilder regionAttributesFactoryBeanBuilder = regionFactoryBeanBuilder; if (!ClientRegion.class.isAssignableFrom(regionAnnotation.annotationType())) { - regionAttributesFactoryBeanBuilder = BeanDefinitionBuilder.genericBeanDefinition( - RegionAttributesFactoryBean.class); + regionAttributesFactoryBeanBuilder = + BeanDefinitionBuilder.genericBeanDefinition(RegionAttributesFactoryBean.class); regionFactoryBeanBuilder.addPropertyValue("attributes", regionAttributesFactoryBeanBuilder.getBeanDefinition()); @@ -559,9 +563,8 @@ public class EntityDefinedRegionsConfiguration protected BeanDefinitionBuilder setFixedPartitionRegionAttributes(AnnotationAttributes regionAnnotationAttributes, BeanDefinitionBuilder partitionAttributesFactoryBeanBuilder) { - PartitionRegion.FixedPartition[] fixedPartitions = ArrayUtils.nullSafeArray( - regionAnnotationAttributes.getAnnotationArray("fixedPartitions", PartitionRegion.FixedPartition.class), - PartitionRegion.FixedPartition.class); + PartitionRegion.FixedPartition[] fixedPartitions = nullSafeArray(regionAnnotationAttributes.getAnnotationArray( + "fixedPartitions", PartitionRegion.FixedPartition.class), PartitionRegion.FixedPartition.class); if (!ObjectUtils.isEmpty(fixedPartitions)) { ManagedList fixedPartitionAttributesFactoryBeans = @@ -596,7 +599,8 @@ public class EntityDefinedRegionsConfiguration if (regionAnnotationAttributes.containsKey("scope")) { setPropertyValueIfNotDefault(regionFactoryBeanBuilder, "scope", - regionAnnotationAttributes.getEnum("scope").getScope(), ScopeType.DISTRIBUTED_NO_ACK); + regionAnnotationAttributes.getEnum("scope").getScope(), + ScopeType.DISTRIBUTED_NO_ACK); } return regionFactoryBeanBuilder; @@ -606,7 +610,8 @@ public class EntityDefinedRegionsConfiguration private BeanDefinitionBuilder setPropertyReferenceIfSet(BeanDefinitionBuilder beanDefinitionBuilder, String propertyName, String beanName) { - return (StringUtils.hasText(beanName) ? beanDefinitionBuilder.addPropertyReference(propertyName, beanName) + return (StringUtils.hasText(beanName) + ? beanDefinitionBuilder.addPropertyReference(propertyName, beanName) : beanDefinitionBuilder); } @@ -614,8 +619,9 @@ public class EntityDefinedRegionsConfiguration private BeanDefinitionBuilder setPropertyValueIfNotDefault(BeanDefinitionBuilder beanDefinitionBuilder, String propertyName, T value, T defaultValue) { - return (value != null && !value.equals(defaultValue) ? - beanDefinitionBuilder.addPropertyValue(propertyName, value) : beanDefinitionBuilder); + return (value != null && !value.equals(defaultValue) + ? beanDefinitionBuilder.addPropertyValue(propertyName, value) + : beanDefinitionBuilder); } /** diff --git a/src/main/java/org/springframework/data/gemfire/mapping/annotation/ClientRegion.java b/src/main/java/org/springframework/data/gemfire/mapping/annotation/ClientRegion.java index fd9672a9..c38726c4 100644 --- a/src/main/java/org/springframework/data/gemfire/mapping/annotation/ClientRegion.java +++ b/src/main/java/org/springframework/data/gemfire/mapping/annotation/ClientRegion.java @@ -34,7 +34,8 @@ import org.springframework.data.gemfire.config.xml.GemfireConstants; * {@link Annotation} defining the Client {@link Region} in which the application persistent entity will be stored. * * @author John Blum - * @see Region + * @see org.springframework.data.gemfire.config.annotation.EntityDefinedRegionsConfiguration + * @see org.springframework.data.gemfire.mapping.annotation.Region * @since 1.9.0 */ @Target(ElementType.TYPE) @@ -86,6 +87,16 @@ public @interface ClientRegion { */ boolean diskSynchronous() default true; + /** + * Determines whether an entity annotated with this Region annotation will ignore any existing Region definition + * identified by the given {@link #name()} for this entity. + * + * Overrides the global, {@link EnableEntityDefinedRegions#ignoreIfExists()} setting. + * + * Defaults to {@literal true}. + */ + boolean ignoreIfExists() default true; + /** * Name of the GemFire/Geode {@link Pool} used by this persistent entity's {@link org.apache.geode.cache.Region} * data access operations sent to the corresponding {@link org.apache.geode.cache.Region} diff --git a/src/main/java/org/springframework/data/gemfire/mapping/annotation/LocalRegion.java b/src/main/java/org/springframework/data/gemfire/mapping/annotation/LocalRegion.java index 512f31b0..65b6724f 100644 --- a/src/main/java/org/springframework/data/gemfire/mapping/annotation/LocalRegion.java +++ b/src/main/java/org/springframework/data/gemfire/mapping/annotation/LocalRegion.java @@ -26,12 +26,14 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.core.annotation.AliasFor; +import org.springframework.data.gemfire.config.annotation.EnableEntityDefinedRegions; /** * {@link Annotation} defining the Local {@link Region} in which the application persistent entity will be stored. * * @author John Blum - * @see Region + * @see org.springframework.data.gemfire.config.annotation.EnableEntityDefinedRegions + * @see org.springframework.data.gemfire.mapping.annotation.Region * @since 1.9.0 */ @Target(ElementType.TYPE) @@ -83,6 +85,16 @@ public @interface LocalRegion { */ boolean diskSynchronous() default true; + /** + * Determines whether an entity annotated with this Region annotation will ignore any existing Region definition + * identified by the given {@link #name()} for this entity. + * + * Overrides the global, {@link EnableEntityDefinedRegions#ignoreIfExists()} setting. + * + * Defaults to {@literal true}. + */ + boolean ignoreIfExists() default true; + /** * Determines whether this {@link org.apache.geode.cache.Region Region's} data access operations participates in * any existing, Global JTA transaction in progress. diff --git a/src/main/java/org/springframework/data/gemfire/mapping/annotation/PartitionRegion.java b/src/main/java/org/springframework/data/gemfire/mapping/annotation/PartitionRegion.java index 744b0401..7ffffdca 100644 --- a/src/main/java/org/springframework/data/gemfire/mapping/annotation/PartitionRegion.java +++ b/src/main/java/org/springframework/data/gemfire/mapping/annotation/PartitionRegion.java @@ -31,7 +31,8 @@ import org.springframework.core.annotation.AliasFor; * {@link Annotation} defining the Partition {@link Region} in which the application persistent entity will be stored. * * @author John Blum - * @see Region + * @see org.springframework.data.gemfire.config.annotation.EntityDefinedRegionsConfiguration + * @see org.springframework.data.gemfire.mapping.annotation.Region * @since 1.9.0 */ @Target(ElementType.TYPE) @@ -105,6 +106,16 @@ public @interface PartitionRegion { */ FixedPartition[] fixedPartitions() default {}; + /** + * Determines whether an entity annotated with this Region annotation will ignore any existing Region definition + * identified by the given {@link #name()} for this entity. + * + * Overrides the global, {@link EnableEntityDefinedRegions#ignoreIfExists()} setting. + * + * Defaults to {@literal true}. + */ + boolean ignoreIfExists() default true; + /** * Determines whether this {@link org.apache.geode.cache.Region Region's} data access operations participates in * any existing, Global JTA transaction in progress. diff --git a/src/main/java/org/springframework/data/gemfire/mapping/annotation/Region.java b/src/main/java/org/springframework/data/gemfire/mapping/annotation/Region.java index e682214e..11aa80cb 100644 --- a/src/main/java/org/springframework/data/gemfire/mapping/annotation/Region.java +++ b/src/main/java/org/springframework/data/gemfire/mapping/annotation/Region.java @@ -71,4 +71,14 @@ public @interface Region { @AliasFor(attribute = "name") String value() default ""; + /** + * Determines whether an entity annotated with this Region annotation will ignore any existing Region definition + * identified by the given {@link #name()} for this entity. + * + * Overrides the global, {@link EnableEntityDefinedRegions#ignoreIfExists()} setting. + * + * Defaults to {@literal true}. + */ + boolean ignoreIfExists() default true; + } diff --git a/src/main/java/org/springframework/data/gemfire/mapping/annotation/ReplicateRegion.java b/src/main/java/org/springframework/data/gemfire/mapping/annotation/ReplicateRegion.java index 656258a1..8e3f0efc 100644 --- a/src/main/java/org/springframework/data/gemfire/mapping/annotation/ReplicateRegion.java +++ b/src/main/java/org/springframework/data/gemfire/mapping/annotation/ReplicateRegion.java @@ -32,7 +32,8 @@ import org.springframework.data.gemfire.ScopeType; * {@link Annotation} defining the Replicate {@link Region} in which the application persistent entity will be stored. * * @author John Blum - * @see Region + * @see org.springframework.data.gemfire.config.annotation.EntityDefinedRegionsConfiguration + * @see org.springframework.data.gemfire.mapping.annotation.Region * @since 1.9.0 */ @Target(ElementType.TYPE) @@ -84,6 +85,16 @@ public @interface ReplicateRegion { */ boolean diskSynchronous() default true; + /** + * Determines whether an entity annotated with this Region annotation will ignore any existing Region definition + * identified by the given {@link #name()} for this entity. + * + * Overrides the global, {@link EnableEntityDefinedRegions#ignoreIfExists()} setting. + * + * Defaults to {@literal true}. + */ + boolean ignoreIfExists() default true; + /** * Determines whether this {@link org.apache.geode.cache.Region Region's} data access operations participates in * any existing, Global JTA transaction in progress. diff --git a/src/main/java/org/springframework/data/gemfire/util/CacheUtils.java b/src/main/java/org/springframework/data/gemfire/util/CacheUtils.java index 3a236547..2049fa35 100644 --- a/src/main/java/org/springframework/data/gemfire/util/CacheUtils.java +++ b/src/main/java/org/springframework/data/gemfire/util/CacheUtils.java @@ -21,6 +21,7 @@ import org.apache.geode.cache.Cache; import org.apache.geode.cache.CacheClosedException; import org.apache.geode.cache.CacheFactory; import org.apache.geode.cache.GemFireCache; +import org.apache.geode.cache.Region; import org.apache.geode.cache.client.ClientCache; import org.apache.geode.cache.client.ClientCacheFactory; import org.apache.geode.distributed.DistributedSystem; @@ -125,7 +126,13 @@ public abstract class CacheUtils extends DistributedSystemUtils { } } + /* (non-Javadoc) */ public static GemFireCache resolveGemFireCache() { return defaultIfNull(getCache(), CacheUtils::getClientCache); } + + /* (non-Javadoc) */ + public static String toRegionPath(String regionName) { + return String.format("%1$s%2$s", Region.SEPARATOR, regionName); + } } diff --git a/src/main/java/org/springframework/data/gemfire/util/DistributedSystemUtils.java b/src/main/java/org/springframework/data/gemfire/util/DistributedSystemUtils.java index afb10d4b..3d8a5655 100644 --- a/src/main/java/org/springframework/data/gemfire/util/DistributedSystemUtils.java +++ b/src/main/java/org/springframework/data/gemfire/util/DistributedSystemUtils.java @@ -16,6 +16,7 @@ package org.springframework.data.gemfire.util; +import java.util.Optional; import java.util.Properties; import org.apache.geode.cache.GemFireCache; @@ -87,7 +88,7 @@ public abstract class DistributedSystemUtils extends SpringUtils { /* (non-Javadoc) */ @SuppressWarnings("unchecked") public static T getDistributedSystem(GemFireCache gemfireCache) { - return (gemfireCache != null ? (T) gemfireCache.getDistributedSystem() : null); + return (T) Optional.ofNullable(gemfireCache).map(GemFireCache::getDistributedSystem).orElse(null); } /* (non-Javadoc)*/ diff --git a/src/main/java/org/springframework/data/gemfire/util/SpringUtils.java b/src/main/java/org/springframework/data/gemfire/util/SpringUtils.java index a4c3ccb0..d1055e30 100644 --- a/src/main/java/org/springframework/data/gemfire/util/SpringUtils.java +++ b/src/main/java/org/springframework/data/gemfire/util/SpringUtils.java @@ -23,6 +23,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Optional; import java.util.function.Supplier; import org.springframework.beans.factory.BeanFactory; @@ -57,12 +58,12 @@ public abstract class SpringUtils { /* (non-Javadoc) */ public static T defaultIfNull(T value, T defaultValue) { - return (value != null ? value : defaultValue); + return Optional.ofNullable(value).orElse(defaultValue); } /* (non-Javadoc) */ public static T defaultIfNull(T value, Supplier supplier) { - return (value != null ? value : supplier.get()); + return Optional.ofNullable(value).orElseGet(supplier); } /* (non-Javadoc) */ diff --git a/src/test/java/org/springframework/data/gemfire/config/annotation/EnableEntityDefinedRegionsConfigurationUnitTests.java b/src/test/java/org/springframework/data/gemfire/config/annotation/EnableEntityDefinedRegionsConfigurationUnitTests.java index a69121a0..d956f218 100644 --- a/src/test/java/org/springframework/data/gemfire/config/annotation/EnableEntityDefinedRegionsConfigurationUnitTests.java +++ b/src/test/java/org/springframework/data/gemfire/config/annotation/EnableEntityDefinedRegionsConfigurationUnitTests.java @@ -21,10 +21,16 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyBoolean; import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import static org.springframework.data.gemfire.util.CacheUtils.toRegionPath; +import static org.springframework.data.gemfire.util.CollectionUtils.nullSafeList; +import java.util.HashSet; import java.util.List; +import java.util.Optional; +import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; @@ -32,10 +38,12 @@ import org.apache.geode.cache.Cache; import org.apache.geode.cache.DataPolicy; import org.apache.geode.cache.DiskStore; import org.apache.geode.cache.FixedPartitionAttributes; +import org.apache.geode.cache.GemFireCache; import org.apache.geode.cache.PartitionAttributes; import org.apache.geode.cache.PartitionResolver; import org.apache.geode.cache.Region; import org.apache.geode.cache.RegionAttributes; +import org.apache.geode.cache.RegionExistsException; import org.apache.geode.cache.RegionFactory; import org.apache.geode.cache.Scope; import org.apache.geode.cache.client.ClientCache; @@ -43,8 +51,8 @@ import org.apache.geode.cache.client.ClientRegionFactory; import org.apache.geode.cache.client.ClientRegionShortcut; import org.junit.After; import org.junit.Test; -import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; +import org.springframework.beans.factory.BeanCreationException; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; @@ -52,17 +60,21 @@ import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; import org.springframework.context.annotation.Lazy; +import org.springframework.data.gemfire.PartitionedRegionFactoryBean; +import org.springframework.data.gemfire.ReplicatedRegionFactoryBean; import org.springframework.data.gemfire.client.ClientRegionShortcutWrapper; import org.springframework.data.gemfire.config.annotation.test.entities.ClientRegionEntity; import org.springframework.data.gemfire.config.annotation.test.entities.CollocatedPartitionRegionEntity; import org.springframework.data.gemfire.config.annotation.test.entities.GenericRegionEntity; +import org.springframework.data.gemfire.config.annotation.test.entities.LocalRegionEntity; import org.springframework.data.gemfire.config.annotation.test.entities.NonEntity; +import org.springframework.data.gemfire.config.annotation.test.entities.PartitionRegionEntity; +import org.springframework.data.gemfire.config.annotation.test.entities.ReplicateRegionEntity; import org.springframework.data.gemfire.config.xml.GemfireConstants; 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.util.CollectionUtils; /** * Unit tests for the {@link EnableEntityDefinedRegions} annotation and {@link EntityDefinedRegionsConfiguration} class. @@ -78,25 +90,26 @@ public class EnableEntityDefinedRegionsConfigurationUnitTests { private static final AtomicInteger MOCK_ID = new AtomicInteger(0); + private static final Set> cacheRegions = new HashSet<>(); + private ConfigurableApplicationContext applicationContext; @After public void tearDown() { - if (applicationContext != null) { - applicationContext.close(); - } + Optional.ofNullable(this.applicationContext).ifPresent(ConfigurableApplicationContext::close); + cacheRegions.clear(); } /* (non-Javadoc) */ protected void assertRegion(Region region, String name) { - assertRegion(region, name, null, null); + assertRegion(region, name, toRegionPath(name), null, null); } /* (non-Javadoc) */ protected void assertRegion(Region region, String name, Class keyConstraint, Class valueConstraint) { - assertRegion(region, name, String.format("%1$s%2$s", Region.SEPARATOR, name), keyConstraint, valueConstraint); + assertRegion(region, name, toRegionPath(name), keyConstraint, valueConstraint); } /* (non-Javadoc) */ @@ -158,7 +171,7 @@ public class EnableEntityDefinedRegionsConfigurationUnitTests { assertThat(partitionAttributes).isNotNull(); List fixedPartitionAttributes = - CollectionUtils.nullSafeList(partitionAttributes.getFixedPartitionAttributes()); + nullSafeList(partitionAttributes.getFixedPartitionAttributes()); for (FixedPartitionAttributes attributes : fixedPartitionAttributes) { if (attributes.getPartitionName().equals(partitionName)) { @@ -184,15 +197,15 @@ public class EnableEntityDefinedRegionsConfigurationUnitTests { Region sessions = applicationContext.getBean("Sessions", Region.class); assertRegion(sessions, "Sessions", String.class, ClientRegionEntity.class); - assertRegionAttributes(sessions.getAttributes(), DataPolicy.NORMAL, null, true, false, - GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME, null); + assertRegionAttributes(sessions.getAttributes(), DataPolicy.NORMAL, null, true, + false, GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME, null); Region genericRegionEntity = applicationContext.getBean("GenericRegionEntity", Region.class); assertRegion(genericRegionEntity, "GenericRegionEntity", Long.class, GenericRegionEntity.class); - assertRegionAttributes(genericRegionEntity.getAttributes(), DataPolicy.EMPTY, null, true, false, - GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME, null); + assertRegionAttributes(genericRegionEntity.getAttributes(), DataPolicy.EMPTY, null, + true, false, GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME, null); assertThat(applicationContext.containsBean("CollocatedPartitionRegionEntity")).isFalse(); assertThat(applicationContext.containsBean("ContactEvents")).isFalse(); @@ -212,19 +225,20 @@ public class EnableEntityDefinedRegionsConfigurationUnitTests { Region customers = applicationContext.getBean("Customers", Region.class); assertRegion(customers, "Customers"); - assertRegionAttributes(customers.getAttributes(), DataPolicy.PERSISTENT_PARTITION, null, true, false, null, - Scope.DISTRIBUTED_NO_ACK); - assertPartitionAttributes(customers.getAttributes().getPartitionAttributes(), null, null, 1); - assertFixedPartitionAttributes(findFixedPartitionAttributes( - customers.getAttributes().getPartitionAttributes(), "one"), "one", true, 16); - assertFixedPartitionAttributes(findFixedPartitionAttributes( - customers.getAttributes().getPartitionAttributes(), "two"), "two", false, 21); + assertRegionAttributes(customers.getAttributes(), DataPolicy.PERSISTENT_PARTITION, null, + true, false, null, Scope.DISTRIBUTED_NO_ACK); + assertPartitionAttributes(customers.getAttributes().getPartitionAttributes(), null, + null, 1); + assertFixedPartitionAttributes(findFixedPartitionAttributes(customers.getAttributes().getPartitionAttributes(), + "one"), "one", true, 16); + assertFixedPartitionAttributes(findFixedPartitionAttributes(customers.getAttributes().getPartitionAttributes(), + "two"), "two", false, 21); Region contactEvents = applicationContext.getBean("ContactEvents", Region.class); assertRegion(contactEvents, "ContactEvents"); - assertRegionAttributes(contactEvents.getAttributes(), DataPolicy.PERSISTENT_PARTITION, "mockDiskStore", - false, true, null, Scope.DISTRIBUTED_NO_ACK); + assertRegionAttributes(contactEvents.getAttributes(), DataPolicy.PERSISTENT_PARTITION, + "mockDiskStore", false, true, null, Scope.DISTRIBUTED_NO_ACK); assertPartitionAttributes(contactEvents.getAttributes().getPartitionAttributes(), "Customers", applicationContext.getBean("mockPartitionResolver", PartitionResolver.class), 2); @@ -238,23 +252,49 @@ public class EnableEntityDefinedRegionsConfigurationUnitTests { assertThat(applicationContext.containsBean("Sessions")).isFalse(); } + @Test(expected = RegionExistsException.class) + public void entityPeerPartitionRegionAlreadyDefinedThrowsRegionExistsException() { + try { + applicationContext = newApplicationContext(ExistingPartitionRegionPersistentEntitiesConfiguration.class); + } + catch (BeanCreationException expected) { + assertThat(expected).hasCauseInstanceOf(RegionExistsException.class); + assertThat(expected.getCause()).hasMessage("/Customers"); + + throw (RegionExistsException) expected.getCause(); + } + } + @Test @SuppressWarnings("unchecked") - public void entityServerRegionsDefined() { - applicationContext = newApplicationContext(AllServerPersistentEntitiesConfiguration.class); + public void entityReplicateRegionAlreadyDefinedIgnoresEntityDefinedRegionDefinition() { + applicationContext = newApplicationContext(ExistingReplicateRegionPersistentEntitiesConfiguration.class); Region accounts = applicationContext.getBean("Accounts", Region.class); assertRegion(accounts, "Accounts"); - assertRegionAttributes(accounts.getAttributes(), DataPolicy.REPLICATE, null, true, false, null, - Scope.DISTRIBUTED_ACK); + assertRegionAttributes(accounts.getAttributes(), DataPolicy.REPLICATE, null, true, + false, null, Scope.DISTRIBUTED_NO_ACK); + } + + @Test + @SuppressWarnings("unchecked") + public void entityServerRegionsDefined() { + applicationContext = newApplicationContext(ServerPersistentEntitiesConfiguration.class); + + Region accounts = applicationContext.getBean("Accounts", Region.class); + + assertRegion(accounts, "Accounts"); + assertRegionAttributes(accounts.getAttributes(), DataPolicy.REPLICATE, null, true, + false, null, Scope.DISTRIBUTED_ACK); Region customers = applicationContext.getBean("Customers", Region.class); assertRegion(customers, "Customers"); - assertRegionAttributes(customers.getAttributes(), DataPolicy.PERSISTENT_PARTITION, null, true, false, null, - Scope.DISTRIBUTED_NO_ACK); - assertPartitionAttributes(customers.getAttributes().getPartitionAttributes(), null, null, 1); + assertRegionAttributes(customers.getAttributes(), DataPolicy.PERSISTENT_PARTITION, + null, true, false, null, Scope.DISTRIBUTED_NO_ACK); + assertPartitionAttributes(customers.getAttributes().getPartitionAttributes(), null, + null, 1); Region localRegionEntity = applicationContext.getBean("LocalRegionEntity", Region.class); @@ -262,11 +302,12 @@ public class EnableEntityDefinedRegionsConfigurationUnitTests { assertRegionAttributes(localRegionEntity.getAttributes(), DataPolicy.NORMAL, null, true, false, null, Scope.LOCAL); - Region genericRegionEntity = applicationContext.getBean("GenericRegionEntity", Region.class); + Region genericRegionEntity = + applicationContext.getBean("GenericRegionEntity", Region.class); assertRegion(genericRegionEntity, "GenericRegionEntity"); - assertRegionAttributes(genericRegionEntity.getAttributes(), DataPolicy.NORMAL, null, true, false, null, - Scope.DISTRIBUTED_NO_ACK); + assertRegionAttributes(genericRegionEntity.getAttributes(), DataPolicy.NORMAL, + null, true, false, null, Scope.DISTRIBUTED_NO_ACK); assertThat(applicationContext.containsBean("CollocatedPartitionRegionEntity")).isFalse(); assertThat(applicationContext.containsBean("ContactEvents")).isFalse(); @@ -287,13 +328,14 @@ public class EnableEntityDefinedRegionsConfigurationUnitTests { Cache mockCache = mock(Cache.class); Answer> createRegionFactory = invocation -> { - RegionAttributes defaultRegionAttributes = - mockRegionAttributes(null, null, true, false, null, null, null, Scope.DISTRIBUTED_NO_ACK, null); + RegionAttributes defaultRegionAttributes = mockRegionAttributes(null, + null, true, false, null, null, + null, Scope.DISTRIBUTED_NO_ACK, null); RegionAttributes regionAttributes = (invocation.getArguments().length == 1 ? invocation.getArgumentAt(0, RegionAttributes.class) : defaultRegionAttributes); - return mockRegionFactory(regionAttributes); + return mockRegionFactory(mockCache, regionAttributes); }; when(mockCache.createRegionFactory()).thenAnswer(createRegionFactory); @@ -341,7 +383,7 @@ public class EnableEntityDefinedRegionsConfigurationUnitTests { when(mockClientRegionFactory.setValueConstraint(any(Class.class))).thenAnswer( newSetter(Class.class, valueConstraint, mockClientRegionFactory)); - final RegionAttributes mockRegionAttributes = + RegionAttributes mockRegionAttributes = mock(RegionAttributes.class, mockName("MockClientRegionAttributes")); when(mockRegionAttributes.getDataPolicy()).thenReturn( @@ -352,11 +394,17 @@ public class EnableEntityDefinedRegionsConfigurationUnitTests { when(mockRegionAttributes.getPoolName()).thenAnswer(newGetter(poolName)); when(mockRegionAttributes.getValueConstraint()).thenAnswer(newGetter(valueConstraint)); - when(mockClientRegionFactory.create(anyString())).thenAnswer(new Answer>() { - @Override - public Region answer(InvocationOnMock invocation) throws Throwable { - return mockRegion(invocation.getArgumentAt(0, String.class), mockRegionAttributes); - } + when(mockClientRegionFactory.create(anyString())).thenAnswer(invocation -> { + String regionName = invocation.getArgumentAt(0, String.class); + + cacheRegions.stream().filter(region -> region.getName().equals(regionName)).findAny() + .ifPresent(region -> { throw new RegionExistsException(region); }); + + Region region = mockRegion(regionName, mockRegionAttributes); + + cacheRegions.add(region); + + return region; }); return mockClientRegionFactory; @@ -368,7 +416,8 @@ public class EnableEntityDefinedRegionsConfigurationUnitTests { String diskStoreName, boolean diskSynchronous, boolean ignoreJta, Class keyConstraint, PartitionAttributes partitionAttributes, String poolName, Scope scope, Class valueConstraint) { - RegionAttributes mockRegionAttributes = mock(RegionAttributes.class, mockName("MockRegionAttributes")); + RegionAttributes mockRegionAttributes = + mock(RegionAttributes.class, mockName("MockRegionAttributes")); when(mockRegionAttributes.getDataPolicy()).thenReturn(dataPolicy); when(mockRegionAttributes.getDiskStoreName()).thenReturn(diskStoreName); @@ -385,7 +434,9 @@ public class EnableEntityDefinedRegionsConfigurationUnitTests { /* (non-Javadoc) */ @SuppressWarnings("unchecked") - protected static RegionFactory mockRegionFactory(RegionAttributes regionAttributes) { + protected static RegionFactory mockRegionFactory(GemFireCache mockCache, + RegionAttributes regionAttributes) { + RegionFactory mockRegionFactory = mock(RegionFactory.class, mockName("MockRegionFactory")); AtomicReference dataPolicy = new AtomicReference<>(regionAttributes.getDataPolicy()); @@ -393,8 +444,8 @@ public class EnableEntityDefinedRegionsConfigurationUnitTests { AtomicReference diskSynchronous = new AtomicReference<>(regionAttributes.isDiskSynchronous()); AtomicReference ignoreJta = new AtomicReference<>(regionAttributes.getIgnoreJTA()); AtomicReference keyConstraint = new AtomicReference<>(null); - AtomicReference partitionAttributes = new AtomicReference<>( - regionAttributes.getPartitionAttributes()); + AtomicReference partitionAttributes = + new AtomicReference<>(regionAttributes.getPartitionAttributes()); AtomicReference scope = new AtomicReference<>(regionAttributes.getScope()); AtomicReference valueConstraint = new AtomicReference<>(null); @@ -422,7 +473,7 @@ public class EnableEntityDefinedRegionsConfigurationUnitTests { when(mockRegionFactory.setValueConstraint(any(Class.class))).thenAnswer( newSetter(Class.class, valueConstraint, mockRegionFactory)); - final RegionAttributes mockRegionAttributes = + RegionAttributes mockRegionAttributes = mock(RegionAttributes.class, mockName("MockRegionAttributes")); when(mockRegionAttributes.getDataPolicy()).thenAnswer(newGetter(dataPolicy)); @@ -434,11 +485,20 @@ public class EnableEntityDefinedRegionsConfigurationUnitTests { when(mockRegionAttributes.getScope()).thenAnswer(newGetter(scope)); when(mockRegionAttributes.getValueConstraint()).thenAnswer(newGetter(valueConstraint)); - when(mockRegionFactory.create(anyString())).thenAnswer(new Answer>() { - @Override - public Region answer(InvocationOnMock invocation) throws Throwable { - return mockRegion(invocation.getArgumentAt(0, String.class), mockRegionAttributes); - } + when(mockRegionFactory.create(anyString())).thenAnswer(invocation -> { + String regionName = invocation.getArgumentAt(0, String.class); + + cacheRegions.stream().filter(region -> region.getName().equals(regionName)).findAny() + .ifPresent(region -> { throw new RegionExistsException(region); }); + + Region mockRegion = mockRegion(regionName, mockRegionAttributes); + + cacheRegions.add(mockRegion); + + when(mockCache.getRegion(eq(regionName))).thenReturn((Region) mockRegion); + when(mockRegion.getRegionService()).thenReturn(mockCache); + + return mockRegion; }); return mockRegionFactory; @@ -450,7 +510,7 @@ public class EnableEntityDefinedRegionsConfigurationUnitTests { Region mockRegion = mock(Region.class, mockName(name)); when(mockRegion.getName()).thenReturn(name); - when(mockRegion.getFullPath()).thenReturn(String.format("%1$s%2$s", Region.SEPARATOR, name)); + when(mockRegion.getFullPath()).thenReturn(toRegionPath(name)); when(mockRegion.getAttributes()).thenReturn(regionAttributes); return mockRegion; @@ -489,24 +549,17 @@ public class EnableEntityDefinedRegionsConfigurationUnitTests { } } - @EnableEntityDefinedRegions(basePackageClasses = NonEntity.class, - excludeFilters = { @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = ClientRegion.class), - @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = CollocatedPartitionRegionEntity.class) }) @SuppressWarnings("all") - static class AllServerPersistentEntitiesConfiguration extends ServerCacheConfiguration { - } - @EnableEntityDefinedRegions(basePackageClasses = NonEntity.class, strict = true, excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = { LocalRegion.class, PartitionRegion.class, ReplicateRegion.class })) - @SuppressWarnings("all") static class ClientPersistentEntitiesConfiguration extends ClientCacheConfiguration { } + @SuppressWarnings("all") @EnableEntityDefinedRegions(basePackageClasses = NonEntity.class, excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = { ClientRegion.class, LocalRegion.class, ReplicateRegion.class })) - @SuppressWarnings("all") static class PeerPartitionRegionPersistentEntitiesConfiguration extends ServerCacheConfiguration { @Bean @Lazy @@ -519,4 +572,58 @@ public class EnableEntityDefinedRegionsConfigurationUnitTests { return mock(PartitionResolver.class, mockName("MockPartitionResolver")); } } + + @SuppressWarnings("all") + @EnableEntityDefinedRegions(basePackageClasses = NonEntity.class, + excludeFilters = { @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = ClientRegion.class), + @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = CollocatedPartitionRegionEntity.class) }) + static class ServerPersistentEntitiesConfiguration extends ServerCacheConfiguration { + } + + @EnableEntityDefinedRegions(basePackageClasses = NonEntity.class, + excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = { + ClientRegionEntity.class, CollocatedPartitionRegionEntity.class, GenericRegionEntity.class, + LocalRegionEntity.class, ReplicateRegionEntity.class + }) + ) + static class ExistingPartitionRegionPersistentEntitiesConfiguration extends ServerCacheConfiguration { + + @Bean + @SuppressWarnings("unused") + PartitionedRegionFactoryBean customersRegion(GemFireCache gemfireCache) { + PartitionedRegionFactoryBean customers = new PartitionedRegionFactoryBean<>(); + + customers.setCache(gemfireCache); + customers.setClose(false); + customers.setPersistent(false); + customers.setRegionName("Customers"); + + return customers; + } + } + + @SuppressWarnings("all") + @EnableEntityDefinedRegions(basePackageClasses = NonEntity.class, + excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = { + ClientRegionEntity.class, CollocatedPartitionRegionEntity.class, GenericRegionEntity.class, + LocalRegionEntity.class, PartitionRegionEntity.class + }) + ) + static class ExistingReplicateRegionPersistentEntitiesConfiguration extends ServerCacheConfiguration { + + @Bean + @SuppressWarnings("unused") + ReplicatedRegionFactoryBean accountsRegion(GemFireCache gemfireCache) { + ReplicatedRegionFactoryBean accounts = new ReplicatedRegionFactoryBean<>(); + + accounts.setCache(gemfireCache); + accounts.setClose(false); + accounts.setLookupEnabled(true); + accounts.setPersistent(false); + accounts.setRegionName("Accounts"); + accounts.setScope(Scope.DISTRIBUTED_NO_ACK); + + return accounts; + } + } } diff --git a/src/test/java/org/springframework/data/gemfire/config/annotation/test/entities/PartitionRegionEntity.java b/src/test/java/org/springframework/data/gemfire/config/annotation/test/entities/PartitionRegionEntity.java index 8cecc0c7..ea527af2 100644 --- a/src/test/java/org/springframework/data/gemfire/config/annotation/test/entities/PartitionRegionEntity.java +++ b/src/test/java/org/springframework/data/gemfire/config/annotation/test/entities/PartitionRegionEntity.java @@ -30,7 +30,7 @@ import org.springframework.data.gemfire.mapping.annotation.PartitionRegion; * @author John Blum * @since 1.9.0 */ -@PartitionRegion(name = "Customers", persistent = true, redundantCopies = 1, +@PartitionRegion(name = "Customers", ignoreIfExists = false, persistent = true, redundantCopies = 1, fixedPartitions = { @PartitionRegion.FixedPartition(name = "one", primary = true, numBuckets = 16), @PartitionRegion.FixedPartition(name = "two", numBuckets = 21)