diff --git a/pom.xml b/pom.xml index 7c0a5939..1760f311 100644 --- a/pom.xml +++ b/pom.xml @@ -86,8 +86,8 @@ javax.enterprise cdi-api ${cdi} - provided true + provided 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 7f89e4bd..b6a65622 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 @@ -19,7 +19,6 @@ 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; @@ -34,11 +33,6 @@ 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; @@ -65,6 +59,7 @@ import org.springframework.data.gemfire.config.annotation.support.AbstractAnnota import org.springframework.data.gemfire.config.annotation.support.CacheTypeAwareRegionFactoryBean; import org.springframework.data.gemfire.support.CompositeLifecycle; import org.springframework.data.gemfire.util.CollectionUtils; +import org.springframework.data.gemfire.util.StreamUtils; import org.springframework.lang.Nullable; import org.springframework.util.StringUtils; @@ -109,8 +104,13 @@ import org.springframework.util.StringUtils; @Configuration public class CachingDefinedRegionsConfiguration extends AbstractAnnotationConfigSupport implements ImportAware { + private final CacheNameResolver[] configuredCacheNameResolvers = { + new Jsr107CacheAnnotationsCacheNameResolverFactory().create(), + new SpringCacheAnnotationsCacheNameResolver() + }; + private final CacheNameResolver composableCacheNameResolver = type -> - asList(new Jsr107CacheAnnotationsCacheNameResolver(), new SpringCacheAnnotationsCacheNameResolver()).stream() + asList(this.configuredCacheNameResolvers).stream() .flatMap(cacheNameResolver -> cacheNameResolver.resolveCacheNames(type).stream()) .collect(Collectors.toSet()); @@ -346,6 +346,7 @@ public class CachingDefinedRegionsConfiguration extends AbstractAnnotationConfig } @Bean + @SuppressWarnings("unused") public Lifecycle cachingDefinedRegionsCompositeLifecycleBean() { return this.compositeLifecycle; } @@ -356,11 +357,11 @@ public class CachingDefinedRegionsConfiguration extends AbstractAnnotationConfig * 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 Jsr107CacheAnnotationsCacheNameResolver * @see org.springframework.data.gemfire.config.annotation.CachingDefinedRegionsConfiguration.SpringCacheAnnotationsCacheNameResolver */ @FunctionalInterface - protected interface CacheNameResolver { + public interface CacheNameResolver { Set resolveCacheNames(Class type); } @@ -372,13 +373,19 @@ public class CachingDefinedRegionsConfiguration extends AbstractAnnotationConfig * * @see org.springframework.data.gemfire.config.annotation.CachingDefinedRegionsConfiguration.CacheNameResolver */ - protected abstract class AbstractCacheNameResolver implements CacheNameResolver { + public abstract static class AbstractCacheNameResolver extends AbstractAnnotationConfigSupport + 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]; + @Override + protected final Class getAnnotationType() { + return null; + } + protected abstract Class[] getClassCacheAnnotationTypes(); protected abstract Class[] getMethodCacheAnnotationTypes(); @@ -395,11 +402,12 @@ public class CachingDefinedRegionsConfiguration extends AbstractAnnotationConfig protected Set resolveCacheNames(Annotation annotation) { return Optional.ofNullable(annotation) - .map(it -> getAnnotationAttributes(it)) + .map(this::getAnnotationAttributes) .map(annotationAttributes -> { String attributeName = annotationAttributes.containsKey(SPRING_CACHE_NAMES_ATTRIBUTE_NAME) - ? SPRING_CACHE_NAMES_ATTRIBUTE_NAME : JSR_107_CACHE_NAME_ATTRIBUTE_NAME; + ? SPRING_CACHE_NAMES_ATTRIBUTE_NAME + : JSR_107_CACHE_NAME_ATTRIBUTE_NAME; return annotationAttributes.containsKey(attributeName) ? annotationAttributes.getStringArray(attributeName) @@ -407,7 +415,7 @@ public class CachingDefinedRegionsConfiguration extends AbstractAnnotationConfig }) .map(CollectionUtils::asSet) - .orElse(Collections.emptySet()); + .orElseGet(Collections::emptySet); } @Override @@ -416,7 +424,7 @@ public class CachingDefinedRegionsConfiguration extends AbstractAnnotationConfig Set cacheNames = new HashSet<>(resolveCacheNames(type, getClassCacheAnnotationTypes())); stream(type.getMethods()) - .filter(method -> isUserLevelMethod(method)) + .filter(this::isUserLevelMethod) .forEach(method -> cacheNames.addAll(resolveCacheNames(method, getMethodCacheAnnotationTypes()))); return cacheNames; @@ -434,22 +442,7 @@ public class CachingDefinedRegionsConfiguration extends AbstractAnnotationConfig } } - protected class Jsr107CacheAnnotationsCacheNameResolver extends AbstractCacheNameResolver { - - @Override - @SuppressWarnings("unchecked") - protected Class[] getClassCacheAnnotationTypes() { - return append(getMethodCacheAnnotationTypes(), CacheDefaults.class); - } - - @Override - protected Class[] getMethodCacheAnnotationTypes() { - return asArray(javax.cache.annotation.CachePut.class, CacheRemove.class, - CacheRemoveAll.class, CacheResult.class); - } - } - - protected class SpringCacheAnnotationsCacheNameResolver extends AbstractCacheNameResolver { + protected static class SpringCacheAnnotationsCacheNameResolver extends AbstractCacheNameResolver { @Override @SuppressWarnings("unchecked") @@ -469,7 +462,8 @@ public class CachingDefinedRegionsConfiguration extends AbstractAnnotationConfig cacheNames.addAll(resolveCachingCacheNames(type)); - stream(type.getMethods()).filter(method -> isUserLevelMethod(method)) + stream(type.getMethods()) + .filter(this::isUserLevelMethod) .forEach(method -> cacheNames.addAll(resolveCachingCacheNames(method))); return cacheNames; @@ -481,7 +475,7 @@ public class CachingDefinedRegionsConfiguration extends AbstractAnnotationConfig Set cacheNames = new HashSet<>(); Optional.ofNullable(resolveAnnotation(annotatedElement, Caching.class)).ifPresent(caching -> - concat(stream(caching.cacheable()), stream(caching.evict()), stream(caching.put())) + StreamUtils.concat(stream(caching.cacheable()), stream(caching.evict()), stream(caching.put())) .flatMap(cacheAnnotation -> resolveCacheNames(cacheAnnotation).stream()) .collect(Collectors.toCollection(() -> cacheNames))); diff --git a/src/main/java/org/springframework/data/gemfire/config/annotation/Jsr107CacheAnnotationsCacheNameResolver.java b/src/main/java/org/springframework/data/gemfire/config/annotation/Jsr107CacheAnnotationsCacheNameResolver.java new file mode 100644 index 00000000..17b48efa --- /dev/null +++ b/src/main/java/org/springframework/data/gemfire/config/annotation/Jsr107CacheAnnotationsCacheNameResolver.java @@ -0,0 +1,55 @@ +/* + * Copyright 2019 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 + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.gemfire.config.annotation; + +import static org.springframework.data.gemfire.util.ArrayUtils.asArray; + +import java.lang.annotation.Annotation; + +import javax.cache.annotation.CacheDefaults; +import javax.cache.annotation.CachePut; +import javax.cache.annotation.CacheRemove; +import javax.cache.annotation.CacheRemoveAll; +import javax.cache.annotation.CacheResult; + +/** + * The {@link Jsr107CacheAnnotationsCacheNameResolver} class is a {@link CachingDefinedRegionsConfiguration.CacheNameResolver} + * implementation that can resolve JSR-107, JCache API cache annotations from a given {@link Class class type}. + * + * @author John Blum + * @see java.lang.annotation.Annotation + * @see org.springframework.data.gemfire.config.annotation.CachingDefinedRegionsConfiguration.AbstractCacheNameResolver + * @since 2.2.0 + */ +class Jsr107CacheAnnotationsCacheNameResolver extends CachingDefinedRegionsConfiguration.AbstractCacheNameResolver { + + @Override + @SuppressWarnings("unchecked") + protected Class[] getClassCacheAnnotationTypes() { + return append(getMethodCacheAnnotationTypes(), CacheDefaults.class); + } + + @Override + protected Class[] getMethodCacheAnnotationTypes() { + + return asArray( + CachePut.class, + CacheRemove.class, + CacheRemoveAll.class, + CacheResult.class + ); + } +} diff --git a/src/main/java/org/springframework/data/gemfire/config/annotation/Jsr107CacheAnnotationsCacheNameResolverFactory.java b/src/main/java/org/springframework/data/gemfire/config/annotation/Jsr107CacheAnnotationsCacheNameResolverFactory.java new file mode 100644 index 00000000..054e5351 --- /dev/null +++ b/src/main/java/org/springframework/data/gemfire/config/annotation/Jsr107CacheAnnotationsCacheNameResolverFactory.java @@ -0,0 +1,55 @@ +/* + * Copyright 2019 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 + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.gemfire.config.annotation; + +import java.util.Collections; +import java.util.Set; + +import org.springframework.util.ClassUtils; + +/** + * Factory class used to construct an instance of the {@link Jsr107CacheAnnotationsCacheNameResolver} if and only if + * the JSR-107, JCache API lib is on the application classpath. + * + * @author John Blum + * @see org.springframework.data.gemfire.config.annotation.Jsr107CacheAnnotationsCacheNameResolver + * @since 2.2.0 + */ +class Jsr107CacheAnnotationsCacheNameResolverFactory { + + private final boolean jcacheApiPresent; + + Jsr107CacheAnnotationsCacheNameResolverFactory() { + + this.jcacheApiPresent = + ClassUtils.isPresent("javax.cache.annotation.CacheResult", getClass().getClassLoader()); + } + + CachingDefinedRegionsConfiguration.CacheNameResolver create() { + + return this.jcacheApiPresent + ? new Jsr107CacheAnnotationsCacheNameResolver() + : new NoOpCacheNameResolver(); + } + + private static class NoOpCacheNameResolver implements CachingDefinedRegionsConfiguration.CacheNameResolver { + + @Override + public Set resolveCacheNames(Class type) { + return Collections.emptySet(); + } + } +}