diff --git a/pom.xml b/pom.xml
index 6a9a9208..35914404 100644
--- a/pom.xml
+++ b/pom.xml
@@ -19,6 +19,7 @@
2.7.7
1.3.2
3.6.2
+ 1.0.0
9.1.1
2.0.2
1.01
@@ -47,6 +48,14 @@
+
+
+ javax.cache
+ cache-api
+ ${cache-api.version}
+ true
+
+
@@ -55,7 +64,7 @@
1.0.1
test
-
+
javax.interceptor
javax.interceptor-api
diff --git a/src/main/java/org/springframework/data/gemfire/cache/config/GemfireCachingConfiguration.java b/src/main/java/org/springframework/data/gemfire/cache/config/GemfireCachingConfiguration.java
index b9467b81..dcf97f0a 100644
--- a/src/main/java/org/springframework/data/gemfire/cache/config/GemfireCachingConfiguration.java
+++ b/src/main/java/org/springframework/data/gemfire/cache/config/GemfireCachingConfiguration.java
@@ -26,8 +26,13 @@ import org.springframework.data.gemfire.cache.GemfireCacheManager;
* The {@link GemfireCachingConfiguration} class is a Spring {@link Configuration @Configuration} class
* used to configure Pivotal GemFire or Apache Geode as the caching provider in Spring's Cache Abstraction.
*
- * Additionally, this Spring {@link Configuration} class also enables the Spring Cache Abstraction
- * with {@link EnableCaching}.
+ * This {@link Configuration @Configuration} class is specifically responsible for declaring and registering
+ * Spring Data GemFire/Geode's {@link GemfireCacheManager} implementation to properly enable either Pivotal GemFire
+ * or Apache Geode as the caching provider used with Springs Cache Abstraction.
+ *
+ * Additionally, this Spring {@link Configuration @Configuration} class also enables the Spring Cache Abstraction
+ * by declaring Spring's {@link EnableCaching} annotation for the user extending or importing this class using
+ * the SDG provided {@link EnableGemfireCaching} annotation.
*
* @author John Blum
* @see org.apache.geode.cache.GemFireCache
diff --git a/src/main/java/org/springframework/data/gemfire/config/annotation/CachingDefinedRegionsConfiguration.java b/src/main/java/org/springframework/data/gemfire/config/annotation/CachingDefinedRegionsConfiguration.java
index 6062bc3d..f5c3b5e6 100644
--- a/src/main/java/org/springframework/data/gemfire/config/annotation/CachingDefinedRegionsConfiguration.java
+++ b/src/main/java/org/springframework/data/gemfire/config/annotation/CachingDefinedRegionsConfiguration.java
@@ -16,14 +16,17 @@
package org.springframework.data.gemfire.config.annotation;
+import static java.util.Arrays.asList;
import static java.util.Arrays.stream;
import static org.springframework.data.gemfire.util.ArrayUtils.asArray;
import static org.springframework.data.gemfire.util.ArrayUtils.nullSafeArray;
+import static org.springframework.data.gemfire.util.StreamUtils.concat;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
@@ -32,6 +35,11 @@ import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
+import javax.cache.annotation.CacheDefaults;
+import javax.cache.annotation.CacheRemove;
+import javax.cache.annotation.CacheRemoveAll;
+import javax.cache.annotation.CacheResult;
+
import org.apache.geode.cache.GemFireCache;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.RegionShortcut;
@@ -45,7 +53,6 @@ import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
-import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
@@ -105,21 +112,10 @@ import org.springframework.util.StringUtils;
@Configuration
public class CachingDefinedRegionsConfiguration extends AbstractAnnotationConfigSupport implements ImportAware {
- private static final Class[] CLASS_CACHE_ANNOTATION_TYPES;
-
- private static final Class[] METHOD_CACHE_ANNOTATION_TYPES =
- asArray(Cacheable.class, CacheEvict.class, CachePut.class);
-
- static {
-
- List annotationTypes = new ArrayList<>();
-
- Collections.addAll(annotationTypes, METHOD_CACHE_ANNOTATION_TYPES);
- annotationTypes.add(CacheConfig.class);
-
- CLASS_CACHE_ANNOTATION_TYPES = annotationTypes.toArray(new Class[annotationTypes.size()]);
-
- }
+ private final CacheNameResolver composableCacheNameResolver = type ->
+ asList(new Jsr107CacheAnnotationsCacheNameResolver(), new SpringCacheAnnotationsCacheNameResolver()).stream()
+ .flatMap(cacheNameResolver -> cacheNameResolver.resolveCacheNames(type).stream())
+ .collect(Collectors.toSet());
private ClientRegionShortcut clientRegionShortcut = ClientRegionShortcut.PROXY;
@@ -142,6 +138,17 @@ public class CachingDefinedRegionsConfiguration extends AbstractAnnotationConfig
return EnableCachingDefinedRegions.class;
}
+ /**
+ * Returns the configured {@link CacheNameResolver} to resolve all the declared cache name on Spring application
+ * beans/components declared and registered in the Spring container (context).
+ *
+ * @return the configured {@link CacheNameResolver} to resolve all teh caches used by the Spring application.
+ * @see org.springframework.data.gemfire.config.annotation.CachingDefinedRegionsConfiguration.CacheNameResolver
+ */
+ protected CacheNameResolver getCacheNameResolver() {
+ return this.composableCacheNameResolver;
+ }
+
/**
* Configures the {@link ClientRegionShortcut} specifying the data management policy to use
* when creating a client {@link Region}.
@@ -273,7 +280,7 @@ public class CachingDefinedRegionsConfiguration extends AbstractAnnotationConfig
@Bean
@SuppressWarnings("all")
- public BeanDefinitionRegistryPostProcessor cacheAbstractionAnnotationsRegionBeanDefinitionRegistrar() {
+ public BeanDefinitionRegistryPostProcessor cachingAnnotationsRegionBeanDefinitionRegistrar() {
return new BeanDefinitionRegistryPostProcessorSupport() {
@@ -284,24 +291,6 @@ public class CachingDefinedRegionsConfiguration extends AbstractAnnotationConfig
};
}
- @Bean
- @SuppressWarnings("all")
- public BeanPostProcessor cacheAbstractionAnnotationsRegionBeanRegistrar(ConfigurableBeanFactory beanFactory) {
-
- return new BeanPostProcessor() {
-
- @Nullable @Override
- public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
-
- if (isNotInfrastructureBean(bean)) {
- registerRegionBeans(collectCacheNames(bean.getClass()), beanFactory);
- }
-
- return bean;
- }
- };
- }
-
void registerBeanDefinitions(BeanDefinitionRegistry registry) {
for (String beanName : registry.getBeanDefinitionNames()) {
@@ -310,73 +299,11 @@ public class CachingDefinedRegionsConfiguration extends AbstractAnnotationConfig
if (isNotInfrastructureBean(beanDefinition)) {
resolveBeanClass(beanDefinition, registry).ifPresent(beanClass ->
- registerRegionBeanDefinitions(collectCacheNames(beanClass), registry));
+ registerRegionBeanDefinitions(getCacheNameResolver().resolveCacheNames(beanClass), registry));
}
}
}
- @SuppressWarnings("unchecked")
- private Set collectCacheNames(Class> type) {
-
- Set cacheNames = new HashSet<>();
-
- cacheNames.addAll(collectCachingCacheNames(type));
- cacheNames.addAll(collectCacheNames(type, CLASS_CACHE_ANNOTATION_TYPES));
-
- stream(type.getMethods()).forEach(method -> {
- if (isUserLevelMethod(method)) {
- cacheNames.addAll(collectCachingCacheNames(method));
- cacheNames.addAll(collectCacheNames(method, METHOD_CACHE_ANNOTATION_TYPES));
- }
- });
-
- return cacheNames;
- }
-
- @SuppressWarnings("all")
- Set collectCacheNames(AnnotatedElement annotatedElement,
- Class extends Annotation>... annotationTypes) {
-
- Stream cacheNames = stream(nullSafeArray(annotationTypes, Class.class))
- .map(annotationType -> resolveAnnotation(annotatedElement, annotationType))
- .flatMap(annotation -> collectCacheNames((Annotation) annotation).stream());
-
- return cacheNames.collect(Collectors.toSet());
- }
-
- private Set collectCacheNames(Annotation annotation) {
-
- return Optional.ofNullable(annotation)
- .map(this::getAnnotationAttributes)
- .map(annotationAttributes -> annotationAttributes.getStringArray("cacheNames"))
- .map(CollectionUtils::asSet)
- .orElse(Collections.emptySet());
- }
-
- private Set collectCachingCacheNames(AnnotatedElement annotatedElement) {
-
- Set cacheNames = new HashSet<>();
-
- Optional.ofNullable(resolveAnnotation(annotatedElement, Caching.class))
- .ifPresent(caching -> {
-
- cacheNames.addAll(stream(nullSafeArray(caching.cacheable(), Cacheable.class))
- .flatMap(cacheable -> collectCacheNames(cacheable).stream())
- .collect(Collectors.toSet()));
-
- cacheNames.addAll(stream(nullSafeArray(caching.evict(), CacheEvict.class))
- .flatMap(cacheEvict -> collectCacheNames(cacheEvict).stream())
- .collect(Collectors.toSet()));
-
- cacheNames.addAll(stream(nullSafeArray(caching.put(), CachePut.class))
- .flatMap(cachePut -> collectCacheNames(cachePut).stream())
- .collect(Collectors.toSet()));
-
- });
-
- return cacheNames;
- }
-
private BeanDefinitionRegistry registerRegionBeanDefinitions(Set cacheNames,
BeanDefinitionRegistry registry) {
@@ -400,6 +327,24 @@ public class CachingDefinedRegionsConfiguration extends AbstractAnnotationConfig
return registry;
}
+ @Bean
+ @SuppressWarnings("all")
+ public BeanPostProcessor cachingAnnotationsRegionBeanRegistrar(ConfigurableBeanFactory beanFactory) {
+
+ return new BeanPostProcessor() {
+
+ @Nullable @Override
+ public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
+
+ if (isNotInfrastructureBean(bean)) {
+ registerRegionBeans(getCacheNameResolver().resolveCacheNames(bean.getClass()), beanFactory);
+ }
+
+ return bean;
+ }
+ };
+ }
+
private ConfigurableBeanFactory registerRegionBeans(Set cacheNames, ConfigurableBeanFactory beanFactory) {
cacheNames.forEach(cacheName -> {
@@ -432,4 +377,148 @@ public class CachingDefinedRegionsConfiguration extends AbstractAnnotationConfig
return beanFactory;
}
+
+ /**
+ * {@link CacheNameResolver} is a {@link FunctionalInterface} declaring a contract for all implementations
+ * used to resolve all cache names declared and used by a Spring application. A resolver typically inspects
+ * all the application beans/components declared and registered in the Spring container (context) setup by
+ * the application to determine whether the application components require caching behavior.
+ *
+ * @see org.springframework.data.gemfire.config.annotation.CachingDefinedRegionsConfiguration.Jsr107CacheAnnotationsCacheNameResolver
+ * @see org.springframework.data.gemfire.config.annotation.CachingDefinedRegionsConfiguration.SpringCacheAnnotationsCacheNameResolver
+ */
+ @FunctionalInterface
+ protected interface CacheNameResolver {
+ Set resolveCacheNames(Class> type);
+ }
+
+ /**
+ * {@link AbstractCacheNameResolver} is an abstract base class encapsulating reusable functionality common
+ * to all {@link CacheNameResolver} implementations.
+ *
+ * Current implementations support inlude JSR-107, JCache API annotation and Spring's Cache Abstraction annotations.
+ *
+ * @see org.springframework.data.gemfire.config.annotation.CachingDefinedRegionsConfiguration.CacheNameResolver
+ */
+ protected abstract class AbstractCacheNameResolver implements CacheNameResolver {
+
+ private final String JSR_107_CACHE_NAME_ATTRIBUTE_NAME = "cacheName";
+ private final String SPRING_CACHE_NAMES_ATTRIBUTE_NAME = "cacheNames";
+
+ private final String[] EMPTY_ARRAY = new String[0];
+
+ protected abstract Class extends Annotation>[] getClassCacheAnnotationTypes();
+
+ protected abstract Class extends Annotation>[] getMethodCacheAnnotationTypes();
+
+ @SuppressWarnings("unchecked")
+ protected Class[] append(Class[] annotationTypes, Class... additionalAnnotationTypes) {
+
+ List annotationTypeList = new ArrayList<>(Arrays.asList(annotationTypes));
+
+ Collections.addAll(annotationTypeList, additionalAnnotationTypes);
+
+ return annotationTypeList.toArray(new Class[annotationTypeList.size()]);
+ }
+
+ protected Set resolveCacheNames(Annotation annotation) {
+
+ return Optional.ofNullable(annotation)
+ .map(it -> getAnnotationAttributes(it))
+ .map(annotationAttributes -> {
+
+ String attributeName = annotationAttributes.containsKey(SPRING_CACHE_NAMES_ATTRIBUTE_NAME)
+ ? SPRING_CACHE_NAMES_ATTRIBUTE_NAME : JSR_107_CACHE_NAME_ATTRIBUTE_NAME;
+
+ return annotationAttributes.containsKey(attributeName)
+ ? annotationAttributes.getStringArray(attributeName)
+ : EMPTY_ARRAY;
+
+ })
+ .map(CollectionUtils::asSet)
+ .orElse(Collections.emptySet());
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Set resolveCacheNames(Class> type) {
+
+ Set cacheNames = new HashSet<>();
+
+ cacheNames.addAll(resolveCacheNames(type, getClassCacheAnnotationTypes()));
+
+ stream(type.getMethods())
+ .filter(method -> isUserLevelMethod(method))
+ .forEach(method -> cacheNames.addAll(resolveCacheNames(method, getMethodCacheAnnotationTypes())));
+
+ return cacheNames;
+ }
+
+ @SuppressWarnings("all")
+ protected Set resolveCacheNames(AnnotatedElement annotatedElement,
+ Class extends Annotation>... annotationTypes) {
+
+ Stream cacheNames = stream(nullSafeArray(annotationTypes, Class.class))
+ .map(annotationType -> resolveAnnotation(annotatedElement, annotationType))
+ .flatMap(annotation -> resolveCacheNames((Annotation) annotation).stream());
+
+ return cacheNames.collect(Collectors.toSet());
+ }
+ }
+
+ protected class Jsr107CacheAnnotationsCacheNameResolver extends AbstractCacheNameResolver {
+
+ @Override
+ @SuppressWarnings("unchecked")
+ protected Class extends Annotation>[] getClassCacheAnnotationTypes() {
+ return append(getMethodCacheAnnotationTypes(), CacheDefaults.class);
+ }
+
+ @Override
+ protected Class extends Annotation>[] getMethodCacheAnnotationTypes() {
+ return asArray(javax.cache.annotation.CachePut.class, CacheRemove.class,
+ CacheRemoveAll.class, CacheResult.class);
+ }
+ }
+
+ protected class SpringCacheAnnotationsCacheNameResolver extends AbstractCacheNameResolver {
+
+ @Override
+ @SuppressWarnings("unchecked")
+ protected Class extends Annotation>[] getClassCacheAnnotationTypes() {
+ return append(getMethodCacheAnnotationTypes(), Caching.class);
+ }
+
+ @Override
+ protected Class extends Annotation>[] getMethodCacheAnnotationTypes() {
+ return asArray(Cacheable.class, CacheEvict.class, CachePut.class);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Set resolveCacheNames(Class> type) {
+
+ Set cacheNames = super.resolveCacheNames(type);
+
+ cacheNames.addAll(resolveCachingCacheNames(type));
+
+ stream(type.getMethods()).filter(method -> isUserLevelMethod(method))
+ .forEach(method -> cacheNames.addAll(resolveCachingCacheNames(method)));
+
+ return cacheNames;
+ }
+
+ @SuppressWarnings("unchecked")
+ private Set resolveCachingCacheNames(AnnotatedElement annotatedElement) {
+
+ Set cacheNames = new HashSet<>();
+
+ Optional.ofNullable(resolveAnnotation(annotatedElement, Caching.class)).ifPresent(caching ->
+ concat(stream(caching.cacheable()), stream(caching.evict()), stream(caching.put()))
+ .flatMap(cacheAnnotation -> resolveCacheNames(cacheAnnotation).stream())
+ .collect(Collectors.toCollection(() -> cacheNames)));
+
+ return cacheNames;
+ }
+ }
}
diff --git a/src/main/java/org/springframework/data/gemfire/config/annotation/EnableLocator.java b/src/main/java/org/springframework/data/gemfire/config/annotation/EnableLocator.java
index 5f19b344..acb6eecc 100644
--- a/src/main/java/org/springframework/data/gemfire/config/annotation/EnableLocator.java
+++ b/src/main/java/org/springframework/data/gemfire/config/annotation/EnableLocator.java
@@ -68,7 +68,7 @@ public @interface EnableLocator {
*
* Defaults to {@literal 10334}.
*
- * Use the {@literal spring.data.gemfire.locator.host} property in {@literal application.properties}.
+ * Use the {@literal spring.data.gemfire.locator.port} property in {@literal application.properties}.
*/
int port() default LocatorConfiguration.DEFAULT_LOCATOR_PORT;
diff --git a/src/main/java/org/springframework/data/gemfire/util/ArrayUtils.java b/src/main/java/org/springframework/data/gemfire/util/ArrayUtils.java
index f071d107..6ffce0dd 100644
--- a/src/main/java/org/springframework/data/gemfire/util/ArrayUtils.java
+++ b/src/main/java/org/springframework/data/gemfire/util/ArrayUtils.java
@@ -49,7 +49,7 @@ public abstract class ArrayUtils {
* @return the given {@code array} if not {@literal null} or empty otherwise return the {@code defaultArray}.
*/
public static T[] defaultIfEmpty(T[] array, T[] defaultArray) {
- return (!ObjectUtils.isEmpty(array) ? array : defaultArray);
+ return !ObjectUtils.isEmpty(array) ? array : defaultArray;
}
/**
@@ -76,7 +76,7 @@ public abstract class ArrayUtils {
* @see #getFirst(Object[], Object)
*/
public static T getFirst(T[] array, T defaultValue) {
- return (isEmpty(array) ? defaultValue : array[0]);
+ return isEmpty(array) ? defaultValue : array[0];
}
/**
@@ -91,8 +91,9 @@ public abstract class ArrayUtils {
* @see java.lang.reflect.Array#newInstance(Class, int)
*/
public static Object[] insert(Object[] originalArray, int position, Object element) {
- Object[] newArray = (Object[]) Array.newInstance(originalArray.getClass().getComponentType(),
- originalArray.length + 1);
+
+ Object[] newArray =
+ (Object[]) Array.newInstance(originalArray.getClass().getComponentType(), originalArray.length + 1);
// copy all elements before the given position (here, position refers to the length, or number of elements
@@ -106,7 +107,8 @@ public abstract class ArrayUtils {
// copy remaining elements from originalArray, starting at position, to new array
if (position < originalArray.length) {
- System.arraycopy(originalArray, position, newArray, position + 1, originalArray.length - position);
+ System.arraycopy(originalArray, position, newArray, position + 1,
+ originalArray.length - position);
}
return newArray;
@@ -120,7 +122,7 @@ public abstract class ArrayUtils {
* @see #length(Object...)
*/
public static boolean isEmpty(Object[] array) {
- return (length(array) == 0);
+ return length(array) == 0;
}
/**
@@ -130,7 +132,7 @@ public abstract class ArrayUtils {
* @return the length of the given array or 0 if the array reference is null.
*/
public static int length(Object[] array) {
- return (array != null ? array.length : 0);
+ return array != null ? array.length : 0;
}
/**
@@ -145,7 +147,7 @@ public abstract class ArrayUtils {
*/
@SuppressWarnings("unchecked")
public static T[] nullSafeArray(T[] array, Class componentType) {
- return (array != null ? array : (T[]) Array.newInstance(componentType, 0));
+ return array != null ? array : (T[]) Array.newInstance(componentType, 0);
}
/**
@@ -159,8 +161,9 @@ public abstract class ArrayUtils {
* @see java.lang.reflect.Array#newInstance(Class, int)
*/
public static Object[] remove(Object[] originalArray, int position) {
- Object[] newArray = (Object[]) Array.newInstance(originalArray.getClass().getComponentType(),
- originalArray.length - 1);
+
+ Object[] newArray =
+ (Object[]) Array.newInstance(originalArray.getClass().getComponentType(), originalArray.length - 1);
// copy all elements before position (here, position refers to the length, or number of elements to be copied
if (position > 0) {
@@ -169,7 +172,8 @@ public abstract class ArrayUtils {
// copy remaining elements after position from the originalArray
if (position < originalArray.length - 1) {
- System.arraycopy(originalArray, position + 1, newArray, position, originalArray.length - 1 - position);
+ System.arraycopy(originalArray, position + 1, newArray, position,
+ originalArray.length - 1 - position);
}
return newArray;
@@ -184,7 +188,9 @@ public abstract class ArrayUtils {
* @see java.util.Arrays#sort(Object[])
*/
public static > T[] sort(T[] array) {
+
Arrays.sort(array);
+
return array;
}
}
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 73393781..ed0f8a91 100644
--- a/src/main/java/org/springframework/data/gemfire/util/CacheUtils.java
+++ b/src/main/java/org/springframework/data/gemfire/util/CacheUtils.java
@@ -23,7 +23,6 @@ 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;
@@ -67,13 +66,16 @@ 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"!
//((InternalDistributedSystem) distributedSystem).getConfig().getDurableClientId();
- return (isConnected(distributedSystem) && StringUtils.hasText(distributedSystem.getProperties()
- .getProperty(DURABLE_CLIENT_ID_PROPERTY_NAME, null)));
+ return Optional.ofNullable(clientCache)
+ .map(CacheUtils::getDistributedSystem)
+ .filter(DistributedSystem::isConnected)
+ .map(DistributedSystem::getProperties)
+ .map(properties -> properties.getProperty(DURABLE_CLIENT_ID_PROPERTY_NAME, null))
+ .filter(StringUtils::hasText)
+ .isPresent();
}
/* (non-Javadoc) */
@@ -91,6 +93,7 @@ public abstract class CacheUtils extends DistributedSystemUtils {
/* (non-Javadoc) */
public static boolean closeCache() {
+
try {
CacheFactory.getAnyInstance().close();
return true;
@@ -102,6 +105,7 @@ public abstract class CacheUtils extends DistributedSystemUtils {
/* (non-Javadoc) */
public static boolean closeClientCache() {
+
try {
ClientCacheFactory.getAnyInstance().close();
return true;
@@ -113,6 +117,7 @@ public abstract class CacheUtils extends DistributedSystemUtils {
/* (non-Javadoc) */
public static Cache getCache() {
+
try {
return CacheFactory.getAnyInstance();
}
@@ -123,6 +128,7 @@ public abstract class CacheUtils extends DistributedSystemUtils {
/* (non-Javadoc) */
public static ClientCache getClientCache() {
+
try {
return ClientCacheFactory.getAnyInstance();
}
@@ -135,9 +141,4 @@ public abstract class CacheUtils extends DistributedSystemUtils {
public static GemFireCache resolveGemFireCache() {
return Optional.ofNullable(getClientCache()).orElseGet(CacheUtils::getCache);
}
-
- /* (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/CollectionUtils.java b/src/main/java/org/springframework/data/gemfire/util/CollectionUtils.java
index e11556eb..431ecaea 100644
--- a/src/main/java/org/springframework/data/gemfire/util/CollectionUtils.java
+++ b/src/main/java/org/springframework/data/gemfire/util/CollectionUtils.java
@@ -16,6 +16,7 @@
package org.springframework.data.gemfire.util;
+import static java.util.stream.StreamSupport.stream;
import static org.springframework.data.gemfire.util.ArrayUtils.nullSafeArray;
import java.util.ArrayList;
@@ -26,6 +27,7 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
import java.util.TreeMap;
@@ -61,11 +63,10 @@ public abstract class CollectionUtils extends org.springframework.util.Collectio
* @see java.util.Collection
*/
public static > T addAll(T collection, Iterable iterable) {
- Assert.notNull(collection, "Collection must not be null");
- for (E element : nullSafeIterable(iterable)) {
- collection.add(element);
- }
+ Assert.notNull(collection, "Collection is required");
+
+ stream(nullSafeIterable(iterable).spliterator(), false).forEach(collection::add);
return collection;
}
@@ -79,8 +80,11 @@ public abstract class CollectionUtils extends org.springframework.util.Collectio
*/
@SafeVarargs
public static Set asSet(T... elements) {
+
Set set = new HashSet<>(elements.length);
+
Collections.addAll(set, elements);
+
return Collections.unmodifiableSet(set);
}
@@ -93,6 +97,7 @@ public abstract class CollectionUtils extends org.springframework.util.Collectio
* @see java.util.Collection#contains(Object)
*/
public static boolean containsAny(Collection> collection, Object... elements) {
+
if (collection != null) {
for (Object element : nullSafeArray(elements, Object.class)) {
if (collection.contains(element)) {
@@ -104,20 +109,6 @@ public abstract class CollectionUtils extends org.springframework.util.Collectio
return false;
}
- /**
- * Returns the given {@link Iterable} if not {@literal null} or empty, otherwise returns the {@code defaultIterable}.
- *
- * @param concrete {@link Class} type of the {@link Iterable}.
- * @param {@link Class} type of the elements in the {@link Iterable Iterables}.
- * @param iterable {@link Iterable} to evaluate.
- * @param defaultIterable {@link Iterable} to return if the given {@code iterable} is {@literal null} or empty.
- * @return {@code iterable} if not {@literal null} or empty otherwise return {@code defaultIterable}.
- * @see java.lang.Iterable
- */
- public static > T defaultIfEmpty(T iterable, T defaultIterable) {
- return (iterable != null && iterable.iterator().hasNext() ? iterable : defaultIterable);
- }
-
/**
* Returns an empty {@link Iterable} object.
*
@@ -168,7 +159,7 @@ public abstract class CollectionUtils extends org.springframework.util.Collectio
* @see java.util.Collection
*/
public static Collection nullSafeCollection(Collection collection) {
- return (collection != null ? collection : Collections.emptyList());
+ return collection != null ? collection : Collections.emptyList();
}
/**
@@ -182,7 +173,21 @@ public abstract class CollectionUtils extends org.springframework.util.Collectio
* @see java.util.Iterator
*/
public static Iterable nullSafeIterable(Iterable iterable) {
- return (iterable != null ? iterable : Collections::emptyIterator);
+ return iterable != null ? iterable : Collections::emptyIterator;
+ }
+
+ /**
+ * Returns the given {@link Iterable} if not {@literal null} or empty, otherwise returns the {@code defaultIterable}.
+ *
+ * @param concrete {@link Class} type of the {@link Iterable}.
+ * @param {@link Class} type of the elements in the {@link Iterable Iterables}.
+ * @param iterable {@link Iterable} to evaluate.
+ * @param defaultIterable {@link Iterable} to return if the given {@code iterable} is {@literal null} or empty.
+ * @return {@code iterable} if not {@literal null} or empty otherwise return {@code defaultIterable}.
+ * @see java.lang.Iterable
+ */
+ public static > T nullSafeIterable(T iterable, T defaultIterable) {
+ return Optional.ofNullable(iterable).filter(it -> it.iterator().hasNext()).orElse(defaultIterable);
}
/**
@@ -196,7 +201,7 @@ public abstract class CollectionUtils extends org.springframework.util.Collectio
* @see java.util.List
*/
public static List nullSafeList(List list) {
- return (list != null ? list : Collections.emptyList());
+ return list != null ? list : Collections.emptyList();
}
/**
@@ -212,7 +217,7 @@ public abstract class CollectionUtils extends org.springframework.util.Collectio
*/
@SuppressWarnings("all")
public static Map nullSafeMap(Map map) {
- return (map != null ? map : Collections.emptyMap());
+ return map != null ? map : Collections.emptyMap();
}
/**
@@ -226,7 +231,7 @@ public abstract class CollectionUtils extends org.springframework.util.Collectio
* @see java.util.Set
*/
public static Set nullSafeSet(Set set) {
- return (set != null ? set : Collections.emptySet());
+ return set != null ? set : Collections.emptySet();
}
/**
@@ -239,7 +244,9 @@ public abstract class CollectionUtils extends org.springframework.util.Collectio
* @see java.util.List
*/
public static > List sort(List list) {
+
Collections.sort(list);
+
return list;
}
@@ -257,7 +264,8 @@ public abstract class CollectionUtils extends org.springframework.util.Collectio
* @see java.util.List
*/
public static List subList(List source, int... indices) {
- Assert.notNull(source, "List must not be null");
+
+ Assert.notNull(source, "List is required");
List result = new ArrayList<>(indices.length);
@@ -270,6 +278,7 @@ public abstract class CollectionUtils extends org.springframework.util.Collectio
/* (non-Javadoc) */
public static String toString(Map, ?> map) {
+
StringBuilder builder = new StringBuilder("{\n");
int count = 0;
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 3d8a5655..7b06df36 100644
--- a/src/main/java/org/springframework/data/gemfire/util/DistributedSystemUtils.java
+++ b/src/main/java/org/springframework/data/gemfire/util/DistributedSystemUtils.java
@@ -57,7 +57,8 @@ public abstract class DistributedSystemUtils extends SpringUtils {
String durableClientId, Integer durableClientTimeout) {
if (StringUtils.hasText(durableClientId)) {
- Assert.notNull(gemfireProperties, "gemfireProperties must not be null");
+
+ Assert.notNull(gemfireProperties, "gemfireProperties are required");
gemfireProperties.setProperty(DURABLE_CLIENT_ID_PROPERTY_NAME, durableClientId);
@@ -71,7 +72,7 @@ public abstract class DistributedSystemUtils extends SpringUtils {
/* (non-Javadoc) */
public static boolean isConnected(DistributedSystem distributedSystem) {
- return (distributedSystem != null && distributedSystem.isConnected());
+ return Optional.ofNullable(distributedSystem).filter(DistributedSystem::isConnected).isPresent();
}
/* (non-Javadoc) */
diff --git a/src/main/java/org/springframework/data/gemfire/util/RegionUtils.java b/src/main/java/org/springframework/data/gemfire/util/RegionUtils.java
index 36f35f56..b7a4a27e 100644
--- a/src/main/java/org/springframework/data/gemfire/util/RegionUtils.java
+++ b/src/main/java/org/springframework/data/gemfire/util/RegionUtils.java
@@ -23,10 +23,12 @@ import org.apache.geode.cache.RegionAttributes;
import org.springframework.util.StringUtils;
/**
- * The RegionUtils class...
+ * The {@link RegionUtils} class is an abstract utility class for working with {@link Region Regions}.
*
* @author John Blum
- * @since 1.0.0
+ * @see org.apache.geode.cache.Region
+ * @see org.apache.geode.cache.RegionAttributes
+ * @since 2.0.0
*/
public abstract class RegionUtils extends CacheUtils {
@@ -38,4 +40,9 @@ public abstract class RegionUtils extends CacheUtils {
.filter(StringUtils::hasText)
.isPresent();
}
+
+ /* (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/StreamUtils.java b/src/main/java/org/springframework/data/gemfire/util/StreamUtils.java
new file mode 100644
index 00000000..a4f798b1
--- /dev/null
+++ b/src/main/java/org/springframework/data/gemfire/util/StreamUtils.java
@@ -0,0 +1,51 @@
+/*
+ * 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.util;
+
+import static org.springframework.data.gemfire.util.ArrayUtils.nullSafeArray;
+
+import java.util.stream.Stream;
+
+/**
+ * The {@link StreamUtils} class is a abstract utility class for working with {@link Stream Streams}.
+ *
+ * @author John Blum
+ * @see java.util.stream.Stream
+ * @since 2.0.2
+ */
+public abstract class StreamUtils {
+
+ /**
+ * Concatenates an array of {@link Stream Streams} into a single, continuous {@link Stream}.
+ *
+ * @param {@link Class type} of elements in the {@link Stream Streams}.
+ * @param streams array of {@link Stream Streams} to concatenate.
+ * @return the concatenated array of {@link Stream Streams} as a single, continuous {@link Stream}.
+ * @see java.util.stream.Stream
+ */
+ @SuppressWarnings("unchecked")
+ public static Stream concat(Stream... streams) {
+
+ Stream concatenatedStream = Stream.empty();
+
+ for (Stream stream : nullSafeArray(streams, Stream.class)) {
+ concatenatedStream = Stream.concat(concatenatedStream, stream);
+ }
+
+ return concatenatedStream;
+ }
+}
diff --git a/src/test/java/org/springframework/data/gemfire/GemfireUtilsTest.java b/src/test/java/org/springframework/data/gemfire/GemfireUtilsTest.java
index 7622d0ee..4ae3a31d 100644
--- a/src/test/java/org/springframework/data/gemfire/GemfireUtilsTest.java
+++ b/src/test/java/org/springframework/data/gemfire/GemfireUtilsTest.java
@@ -45,6 +45,7 @@ public class GemfireUtilsTest {
@Test
public void isClientWithClientIsTrue() {
+
ClientCache mockClient = mock(ClientCache.class);
assertThat(GemfireUtils.isClient(mockClient), is(true));
@@ -54,6 +55,7 @@ public class GemfireUtilsTest {
@Test
public void isClientWithNonClientIsFalse() {
+
Cache mockCache = mock(Cache.class);
assertThat(GemfireUtils.isClient(mockCache), is(false));
@@ -63,7 +65,9 @@ public class GemfireUtilsTest {
@Test
public void isDurableWithDurableClientIsTrue() {
+
ClientCache mockClientCache = mock(ClientCache.class);
+
DistributedSystem mockDistributedSystem = mock(DistributedSystem.class);
Properties gemfireProperties = new Properties();
@@ -83,7 +87,9 @@ public class GemfireUtilsTest {
@Test
public void isDurableWhenNotDurableClientIsFalse() {
+
ClientCache mockClientCache = mock(ClientCache.class);
+
DistributedSystem mockDistributedSystem = mock(DistributedSystem.class);
Properties gemfireProperties = new Properties();
@@ -103,7 +109,9 @@ public class GemfireUtilsTest {
@Test
public void isDurableWhenDistributedSystemIsNotConnectedIsFalse() {
+
ClientCache mockClientCache = mock(ClientCache.class);
+
DistributedSystem mockDistributedSystem = mock(DistributedSystem.class);
when(mockClientCache.getDistributedSystem()).thenReturn(mockDistributedSystem);
@@ -118,6 +126,7 @@ public class GemfireUtilsTest {
@Test
public void isPeerWithPeerIsTrue() {
+
Cache mockCache = mock(Cache.class);
assertThat(GemfireUtils.isPeer(mockCache), is(true));
@@ -127,6 +136,7 @@ public class GemfireUtilsTest {
@Test
public void isPeerWithNonPeerIsFalse() {
+
ClientCache mockClientCache = mock(ClientCache.class);
assertThat(GemfireUtils.isPeer(mockClientCache), is(false));
diff --git a/src/test/java/org/springframework/data/gemfire/config/annotation/EnableCachingDefinedRegionsIntegrationTests.java b/src/test/java/org/springframework/data/gemfire/config/annotation/EnableCachingDefinedRegionsIntegrationTests.java
index c6abb7e1..3267a5bd 100644
--- a/src/test/java/org/springframework/data/gemfire/config/annotation/EnableCachingDefinedRegionsIntegrationTests.java
+++ b/src/test/java/org/springframework/data/gemfire/config/annotation/EnableCachingDefinedRegionsIntegrationTests.java
@@ -20,11 +20,16 @@ import static org.assertj.core.api.Assertions.assertThat;
import java.util.concurrent.atomic.AtomicBoolean;
+import javax.cache.annotation.CacheDefaults;
+import javax.cache.annotation.CacheRemoveAll;
+import javax.cache.annotation.CacheResult;
+
import org.apache.geode.cache.GemFireCache;
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.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.ApplicationContext;
@@ -48,44 +53,58 @@ public class EnableCachingDefinedRegionsIntegrationTests {
private ApplicationContext applicationContext;
@Autowired
- private CacheableEchoService echoService;
+ private JCacheEchoService jcacheEchoService;
+
+ @Autowired
+ private SpringCacheableEchoService springEchoService;
@Autowired
private GemFireCache gemfireCache;
@Before
public void setup() {
-
- //System.err.printf("@Cacheable Beans [%s]%n",
- // Arrays.toString(applicationContext.getBeanNamesForAnnotation(Cacheable.class)));
-
assertThat(this.gemfireCache).isNotNull();
-
- //System.err.printf("Cache Regions [%s]%n", this.gemfireCache.rootRegions().stream()
- // .map(Region::getFullPath).collect(Collectors.toSet()));
}
@Test
public void cacheRegionsExists() {
- assertThat(gemfireCache.getRegion("/Example")).isNotNull();
assertThat(gemfireCache.getRegion("/Echo")).isNotNull();
+ assertThat(gemfireCache.getRegion("/JCacheOne")).isNotNull();
+ assertThat(gemfireCache.getRegion("/JCacheTwo")).isNotNull();
+ assertThat(gemfireCache.getRegion("/SpringOne")).isNotNull();
}
@Test
- public void echoServiceOperationsAreSuccessful() {
+ public void echoServiceCachingWithJCacheIsSuccessful() {
- assertThat(echoService.isCacheMiss()).isFalse();
- assertThat(echoService.echo("one")).isEqualTo("one");
- assertThat(echoService.isCacheMiss()).isTrue();
- assertThat(echoService.echo("two")).isEqualTo("two");
- assertThat(echoService.isCacheMiss()).isTrue();
- assertThat(echoService.echo("one")).isEqualTo("one");
- assertThat(echoService.isCacheMiss()).isFalse();
- assertThat(echoService.echo("three")).isEqualTo("three");
- assertThat(echoService.isCacheMiss()).isTrue();
- assertThat(echoService.echo("two")).isEqualTo("two");
- assertThat(echoService.isCacheMiss()).isFalse();
+ assertThat(jcacheEchoService.isCacheMiss()).isFalse();
+ assertThat(jcacheEchoService.echo("four")).isEqualTo("four");
+ assertThat(jcacheEchoService.isCacheMiss()).isTrue();
+ assertThat(jcacheEchoService.echo("five")).isEqualTo("five");
+ assertThat(jcacheEchoService.isCacheMiss()).isTrue();
+ assertThat(jcacheEchoService.echo("four")).isEqualTo("four");
+ assertThat(jcacheEchoService.isCacheMiss()).isFalse();
+ assertThat(jcacheEchoService.echo("six")).isEqualTo("six");
+ assertThat(jcacheEchoService.isCacheMiss()).isTrue();
+ assertThat(jcacheEchoService.echo("five")).isEqualTo("five");
+ assertThat(jcacheEchoService.isCacheMiss()).isFalse();
+ }
+
+ @Test
+ public void echoServiceCachingWithSpringIsSuccessful() {
+
+ assertThat(springEchoService.isCacheMiss()).isFalse();
+ assertThat(springEchoService.echo("one")).isEqualTo("one");
+ assertThat(springEchoService.isCacheMiss()).isTrue();
+ assertThat(springEchoService.echo("two")).isEqualTo("two");
+ assertThat(springEchoService.isCacheMiss()).isTrue();
+ assertThat(springEchoService.echo("one")).isEqualTo("one");
+ assertThat(springEchoService.isCacheMiss()).isFalse();
+ assertThat(springEchoService.echo("three")).isEqualTo("three");
+ assertThat(springEchoService.isCacheMiss()).isTrue();
+ assertThat(springEchoService.echo("two")).isEqualTo("two");
+ assertThat(springEchoService.isCacheMiss()).isFalse();
}
@PeerCacheApplication(name = "EnableCachingDefinedRegionsIntegrationTests", logLevel = "warning")
@@ -93,18 +112,28 @@ public class EnableCachingDefinedRegionsIntegrationTests {
static class TestConfiguration {
@Bean
- CacheableEchoService echoService() {
- return new CacheableEchoService();
+ JCacheEchoService jcacheEchoService() {
+ return new JCacheEchoService();
}
@Bean
- TestService testService() {
- return new CachingTestService();
+ @Qualifier("Spring")
+ SpringCacheableEchoService springEchoService() {
+ return new SpringCacheableEchoService();
+ }
+
+ @Bean
+ TestService testServiceOne() {
+ return new SpringCachingTestService();
+ }
+
+ @Bean
+ TestService testServiceTwo() {
+ return new Jsr107CachingTestService();
}
}
- @Service
- static class CacheableEchoService {
+ static abstract class AbstractCacheableService {
private final AtomicBoolean cacheMiss = new AtomicBoolean(false);
@@ -112,9 +141,27 @@ public class EnableCachingDefinedRegionsIntegrationTests {
return this.cacheMiss.compareAndSet(true, false);
}
+ public void setCacheMiss() {
+ this.cacheMiss.set(true);
+ }
+ }
+
+ @Service
+ static class JCacheEchoService extends AbstractCacheableService {
+
+ @CacheResult(cacheName = "Echo")
+ public Object echo(String key) {
+ setCacheMiss();
+ return key;
+ }
+ }
+
+ @Service
+ static class SpringCacheableEchoService extends AbstractCacheableService {
+
@Cacheable("Echo")
public Object echo(String key) {
- this.cacheMiss.set(true);
+ setCacheMiss();
return key;
}
}
@@ -123,9 +170,19 @@ public class EnableCachingDefinedRegionsIntegrationTests {
Object testMethod(String key);
}
- static class CachingTestService implements TestService {
+ @CacheDefaults(cacheName = "JCacheOne")
+ @CacheRemoveAll(cacheName = "SpringOne")
+ static class Jsr107CachingTestService implements TestService {
- @CachePut("Example")
+ @CacheResult(cacheName = "JCacheTwo")
+ public Object testMethod(String key) {
+ return null;
+ }
+ }
+
+ static class SpringCachingTestService implements TestService {
+
+ @CachePut("SpringOne")
public Object testMethod(String key) {
return "test";
}
diff --git a/src/test/java/org/springframework/data/gemfire/config/annotation/EnableCachingDefinedRegionsUnitTests.java b/src/test/java/org/springframework/data/gemfire/config/annotation/EnableCachingDefinedRegionsUnitTests.java
index 48da903b..f1e74821 100644
--- a/src/test/java/org/springframework/data/gemfire/config/annotation/EnableCachingDefinedRegionsUnitTests.java
+++ b/src/test/java/org/springframework/data/gemfire/config/annotation/EnableCachingDefinedRegionsUnitTests.java
@@ -33,6 +33,11 @@ import java.util.Arrays;
import java.util.Map;
import java.util.Set;
+import javax.cache.annotation.CacheDefaults;
+import javax.cache.annotation.CacheRemove;
+import javax.cache.annotation.CacheRemoveAll;
+import javax.cache.annotation.CacheResult;
+
import org.apache.geode.cache.RegionShortcut;
import org.apache.geode.cache.client.ClientRegionShortcut;
import org.junit.Before;
@@ -88,7 +93,7 @@ public class EnableCachingDefinedRegionsUnitTests {
return mockBeanDefinition;
}
catch (ClassNotFoundException cause) {
- throw newRuntimeException(cause, "Mock for class [%s] failed", beanClass.getName());
+ throw newRuntimeException(cause, "Creating a mock for class [%s] failed", beanClass.getName());
}
}
@@ -111,6 +116,16 @@ public class EnableCachingDefinedRegionsUnitTests {
return mockBeanDefinitionRegistry;
}
+ @Test
+ public void annotationTypeIsEnableCachingDefinedRegions() {
+ assertThat(this.configuration.getAnnotationType()).isEqualTo(EnableCachingDefinedRegions.class);
+ }
+
+ @Test
+ public void getCacheNameResolverIsConfiguredProperly() {
+ assertThat(this.configuration.getCacheNameResolver()).isNotNull();
+ }
+
@Test
public void setGetAndResolveClientRegionShortcut() {
@@ -319,13 +334,15 @@ public class EnableCachingDefinedRegionsUnitTests {
verify(mockBeanDefinitionRegistry, times(registeredRegionBeanNames.size()))
.registerBeanDefinition(anyString(), any(BeanDefinition.class));
- registeredRegionBeanNames.forEach(beanName ->
+ registeredRegionBeanNames.forEach(beanName -> {
+ verify(mockBeanDefinitionRegistry, times(1)).containsBeanDefinition(eq(beanName));
verify(mockBeanDefinitionRegistry, times(1))
- .registerBeanDefinition(eq(beanName), any(BeanDefinition.class)));
+ .registerBeanDefinition(eq(beanName), any(BeanDefinition.class));
+ });
}
@Test
- public void cacheableServiceOneTwoThreeRegistersTwentyTwoRegionBeans() {
+ public void cacheableServiceOneTwoAndThreeRegistersTwentyTwoRegionBeans() {
Map registeredBeanDefinitions = MapBuilder.newMapBuilder()
.put("cacheableServiceOne", mockBeanDefinition(CacheableServiceOne.class))
@@ -345,45 +362,110 @@ public class EnableCachingDefinedRegionsUnitTests {
verify(mockBeanDefinitionRegistry, times(1)).getBeanDefinitionNames();
- verify(mockBeanDefinitionRegistry, times(1))
- .getBeanDefinition(eq("cacheableServiceOne"));
-
- verify(mockBeanDefinitionRegistry, times(1))
- .getBeanDefinition(eq("cacheableServiceTwo"));
-
- verify(mockBeanDefinitionRegistry, times(1))
- .getBeanDefinition(eq("cacheableServiceThree"));
+ Arrays.asList("cacheableServiceOne", "cacheableServiceTwo", "cacheableServiceThree").forEach(beanName ->
+ verify(mockBeanDefinitionRegistry, times(1)).getBeanDefinition(eq(beanName)));
verify(mockBeanDefinitionRegistry, times(registeredRegionBeanNames.size()))
.registerBeanDefinition(anyString(), any(BeanDefinition.class));
- registeredRegionBeanNames.forEach(beanName ->
+ registeredRegionBeanNames.forEach(beanName -> {
+
+ int wantedNumberOfInvocations = "RegionSix".equals(beanName) || "RegionTwo".equals(beanName) ? 2 : 1;
+
+ verify(mockBeanDefinitionRegistry, times(wantedNumberOfInvocations)).containsBeanDefinition(eq(beanName));
+
verify(mockBeanDefinitionRegistry, times(1))
- .registerBeanDefinition(eq(beanName), any(BeanDefinition.class)));
+ .registerBeanDefinition(eq(beanName), any(BeanDefinition.class));
+ });
}
@Test
- @SuppressWarnings("unchecked")
- public void collectCacheNamesForCacheableAndCachePutOnCacheableServiceThreeRegistersRegionFifteenSixteenSeventeen() {
+ public void cacheableServiceFiveRegistersRegionOneTwoThreeFourFiveSixAndSeven() {
- assertThat(this.configuration.collectCacheNames(CacheableServiceThree.class, Cacheable.class, CachePut.class))
- .containsExactly("RegionFifteen", "RegionSixteen", "RegionSeventeen");
+ Map registeredBeanDefinitions = MapBuilder.newMapBuilder()
+ .put("cacheableServiceFive", mockBeanDefinition(CacheableServiceFive.class))
+ .build();
+
+ BeanDefinitionRegistry mockBeanDefinitionRegistry = mockBeanDefinitionRegistry(registeredBeanDefinitions);
+
+ this.configuration.registerBeanDefinitions(mockBeanDefinitionRegistry);
+
+ Set registeredRegionBeanNames =
+ asSet("RegionOne", "RegionTwo", "RegionThree", "RegionFour", "RegionFive",
+ "RegionSix", "RegionSeven");
+
+ verify(mockBeanDefinitionRegistry, times(1)).getBeanDefinitionNames();
+
+ verify(mockBeanDefinitionRegistry, times(1))
+ .getBeanDefinition(eq("cacheableServiceFive"));
+
+ verify(mockBeanDefinitionRegistry, times(registeredRegionBeanNames.size()))
+ .registerBeanDefinition(anyString(), any(BeanDefinition.class));
+
+ registeredRegionBeanNames.forEach(beanName -> {
+ verify(mockBeanDefinitionRegistry, times(1)).containsBeanDefinition(eq(beanName));
+ verify(mockBeanDefinitionRegistry, times(1))
+ .registerBeanDefinition(eq(beanName), any(BeanDefinition.class));
+ });
}
@Test
- @SuppressWarnings("unchecked")
- public void collectCacheNamesForCacheableOnCacheableServiceThreeRegistersRegionFifteen() {
+ public void cacheableServiceSixRegistersRegionOneTwoThreeFourAndFive() {
- assertThat(this.configuration.collectCacheNames(CacheableServiceThree.class, Cacheable.class))
- .containsExactly("RegionFifteen");
+ Map registeredBeanDefinitions = MapBuilder.newMapBuilder()
+ .put("cacheableServiceSix", mockBeanDefinition(CacheableServiceSix.class))
+ .build();
+
+ BeanDefinitionRegistry mockBeanDefinitionRegistry = mockBeanDefinitionRegistry(registeredBeanDefinitions);
+
+ this.configuration.registerBeanDefinitions(mockBeanDefinitionRegistry);
+
+ Set registeredRegionBeanNames =
+ asSet("RegionOne", "RegionTwo", "RegionThree", "RegionFour", "RegionFive");
+
+ verify(mockBeanDefinitionRegistry, times(1)).getBeanDefinitionNames();
+
+ verify(mockBeanDefinitionRegistry, times(1))
+ .getBeanDefinition(eq("cacheableServiceSix"));
+
+ verify(mockBeanDefinitionRegistry, times(registeredRegionBeanNames.size()))
+ .registerBeanDefinition(anyString(), any(BeanDefinition.class));
+
+ registeredRegionBeanNames.forEach(beanName -> {
+ verify(mockBeanDefinitionRegistry, times(1)).containsBeanDefinition(eq(beanName));
+ verify(mockBeanDefinitionRegistry, times(1))
+ .registerBeanDefinition(eq(beanName), any(BeanDefinition.class));
+ });
}
@Test
- @SuppressWarnings("unchecked")
- public void collectCacheNamesForCachePutOnCacheableServiceThreeRegistersRegionSixteenSeventeen() {
+ public void cacheableServiceSevenRegistersRegionOneThroughEleven() {
- assertThat(this.configuration.collectCacheNames(CacheableServiceThree.class, CachePut.class))
- .containsExactly("RegionSixteen", "RegionSeventeen");
+ Map registeredBeanDefinitions = MapBuilder.newMapBuilder()
+ .put("cacheableServiceSeven", mockBeanDefinition(CacheableServiceSeven.class))
+ .build();
+
+ BeanDefinitionRegistry mockBeanDefinitionRegistry = mockBeanDefinitionRegistry(registeredBeanDefinitions);
+
+ this.configuration.registerBeanDefinitions(mockBeanDefinitionRegistry);
+
+ Set registeredRegionBeanNames =
+ asSet("RegionOne", "RegionTwo", "RegionThree", "RegionFour", "RegionFive", "RegionSix",
+ "RegionSeven", "RegionEight", "RegionNine", "RegionTen", "RegionEleven");
+
+ verify(mockBeanDefinitionRegistry, times(1)).getBeanDefinitionNames();
+
+ verify(mockBeanDefinitionRegistry, times(1))
+ .getBeanDefinition(eq("cacheableServiceSeven"));
+
+ verify(mockBeanDefinitionRegistry, times(registeredRegionBeanNames.size()))
+ .registerBeanDefinition(anyString(), any(BeanDefinition.class));
+
+ registeredRegionBeanNames.forEach(beanName -> {
+ verify(mockBeanDefinitionRegistry, times(1)).containsBeanDefinition(eq(beanName));
+ verify(mockBeanDefinitionRegistry, times(1))
+ .registerBeanDefinition(eq(beanName), any(BeanDefinition.class));
+ });
}
@Service
@@ -450,4 +532,63 @@ public class EnableCachingDefinedRegionsUnitTests {
public void cacheableMethodFive() {}
}
+
+ @CacheDefaults(cacheName = "RegionOne")
+ @CacheRemoveAll(cacheName = "RegionSix")
+ @CacheResult(cacheName = "RegionSeven")
+ @SuppressWarnings("unused")
+ static class CacheableServiceFive {
+
+ @javax.cache.annotation.CachePut(cacheName = "RegionTwo")
+ public void cacheableMethodOne() {}
+
+ @CacheRemove(cacheName = "RegionThree")
+ public void cacheableMethodTwo() {}
+
+ @CacheRemoveAll(cacheName = "RegionFour")
+ public void cacheableMethodThree() {}
+
+ @CacheResult(cacheName = "RegionFive")
+ public void cacheableMethodFour() {}
+
+ }
+
+ @CacheDefaults(cacheName = "RegionOne")
+ @javax.cache.annotation.CachePut(cacheName = "RegionOne")
+ @CacheRemoveAll(cacheName = "RegionFive")
+ @SuppressWarnings("unused")
+ static class CacheableServiceSix {
+
+ @javax.cache.annotation.CachePut(cacheName = "RegionTwo")
+ @javax.cache.annotation.CacheResult(cacheName = "RegionOne")
+ public void cacheableMethodOne() {}
+
+ @CacheRemove(cacheName = "RegionThree")
+ public void cacheableMethodTwo() {}
+
+ @CacheRemoveAll(cacheName = "RegionThree")
+ public void cacheableMethodThree() {}
+
+ @CacheResult(cacheName = "RegionFour")
+ @CacheRemove(cacheName = "RegionFive")
+ public void cacheableMethodFour() {}
+
+ }
+
+ @Caching(
+ cacheable = { @Cacheable({ "RegionSix", "RegionSeven", "RegionEight" }), @Cacheable("RegionNine")},
+ put = @CachePut("RegionTwo")
+ )
+ @CacheDefaults(cacheName = "RegionOne")
+ static class CacheableServiceSeven extends CacheableServiceSix {
+
+ @CachePut("RegionTen")
+ @CacheRemove(cacheName = "RegionFive")
+ @CacheResult(cacheName = "RegionEleven")
+ public void cacheableMethodFive() {}
+
+ @Cacheable("RegionThree")
+ public void cacheableMethodSix() {}
+
+ }
}
diff --git a/src/test/java/org/springframework/data/gemfire/config/annotation/EnableEntityDefinedRegionsUnitTests.java b/src/test/java/org/springframework/data/gemfire/config/annotation/EnableEntityDefinedRegionsUnitTests.java
index b443223f..b25cd7dc 100644
--- a/src/test/java/org/springframework/data/gemfire/config/annotation/EnableEntityDefinedRegionsUnitTests.java
+++ b/src/test/java/org/springframework/data/gemfire/config/annotation/EnableEntityDefinedRegionsUnitTests.java
@@ -24,8 +24,8 @@ 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 static org.springframework.data.gemfire.util.RegionUtils.toRegionPath;
import java.util.HashSet;
import java.util.List;
@@ -51,7 +51,6 @@ 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;
@@ -344,14 +343,11 @@ public class EnableEntityDefinedRegionsUnitTests {
}
protected static ClientCache mockClientCache() {
+
ClientCache mockClientCache = mock(ClientCache.class, mockName("ClientCache"));
- Answer> createClientRegionFactory = new Answer>() {
- @Override @SuppressWarnings("unchecked")
- public ClientRegionFactory answer(InvocationOnMock invocation) throws Throwable {
- return mockClientRegionFactory(invocation.getArgument(0));
- }
- };
+ Answer> createClientRegionFactory =
+ invocation -> mockClientRegionFactory(invocation.getArgument(0));
when(mockClientCache.createClientRegionFactory(any(ClientRegionShortcut.class)))
.thenAnswer(createClientRegionFactory);
@@ -525,6 +521,7 @@ public class EnableEntityDefinedRegionsUnitTests {
}
/* (non-Javadoc) */
+ @SuppressWarnings("unused")
protected static Answer newSetter(Class parameterType, AtomicReference argument, R returnValue) {
return invocation -> {
diff --git a/src/test/java/org/springframework/data/gemfire/util/CollectionUtilsUnitTests.java b/src/test/java/org/springframework/data/gemfire/util/CollectionUtilsUnitTests.java
index 818b52d0..380ecab8 100644
--- a/src/test/java/org/springframework/data/gemfire/util/CollectionUtilsUnitTests.java
+++ b/src/test/java/org/springframework/data/gemfire/util/CollectionUtilsUnitTests.java
@@ -44,6 +44,7 @@ import org.junit.rules.ExpectedException;
* Unit tests for {@link CollectionUtils}.
*
* @author John Blum
+ * @see java.lang.Iterable
* @see java.util.Collection
* @see java.util.Collections
* @see java.util.Enumeration
@@ -63,6 +64,7 @@ public class CollectionUtilsUnitTests {
@Test
public void addAllIterableElementsToList() {
+
List target = new ArrayList<>(Arrays.asList(1, 2, 3));
Set source = new HashSet<>(Arrays.asList(1, 2, 3));
@@ -75,6 +77,7 @@ public class CollectionUtilsUnitTests {
@Test
public void addAllIterableElementsToSet() {
+
Set target = new HashSet<>(Arrays.asList(1, 2, 3));
Set source = new HashSet<>(Arrays.asList(1, 2, 3, 4, 5));
@@ -87,15 +90,17 @@ public class CollectionUtilsUnitTests {
@Test
public void addIterableToNullCollection() {
+
exception.expect(IllegalArgumentException.class);
exception.expectCause(is(nullValue(Throwable.class)));
- exception.expectMessage("Collection must not be null");
+ exception.expectMessage("Collection is required");
CollectionUtils.addAll(null, Collections.emptySet());
}
@Test
public void addEmptyIterableToCollection() {
+
Collection target = new ArrayList<>(Arrays.asList(1, 2, 3));
target = CollectionUtils.addAll(target, Collections.emptyList());
@@ -107,6 +112,7 @@ public class CollectionUtilsUnitTests {
@Test
public void addNullIterableToCollection() {
+
Collection target = new ArrayList<>(Arrays.asList(1, 2, 3));
target = CollectionUtils.addAll(target, null);
@@ -118,6 +124,7 @@ public class CollectionUtilsUnitTests {
@Test
public void asSetContainsAllArrayElements() {
+
Object[] elements = { "a", "b", "c" };
Set> set = CollectionUtils.asSet(elements);
@@ -129,6 +136,7 @@ public class CollectionUtilsUnitTests {
@Test
public void asSetContainsUniqueArrayElements() {
+
Object[] elements = { 1, 2, 1 };
Set> set = CollectionUtils.asSet(elements);
@@ -140,6 +148,7 @@ public class CollectionUtilsUnitTests {
@Test(expected = UnsupportedOperationException.class)
public void asSetReturnsUnmodifiableSet() {
+
Set set = CollectionUtils.asSet(1, 2, 3);
assertThat(set).isNotNull();
@@ -176,36 +185,9 @@ public class CollectionUtilsUnitTests {
assertThat(CollectionUtils.containsAny(null, 1)).isFalse();
}
- @Test
- public void defaultIfEmptyWithNonNullNonEmptyIterableReturnsIterable() {
- Iterable