diff --git a/spring-data-geode/src/main/java/org/springframework/data/gemfire/config/annotation/support/AbstractAnnotationConfigSupport.java b/spring-data-geode/src/main/java/org/springframework/data/gemfire/config/annotation/support/AbstractAnnotationConfigSupport.java index 0f64c112..576fdb53 100644 --- a/spring-data-geode/src/main/java/org/springframework/data/gemfire/config/annotation/support/AbstractAnnotationConfigSupport.java +++ b/spring-data-geode/src/main/java/org/springframework/data/gemfire/config/annotation/support/AbstractAnnotationConfigSupport.java @@ -16,9 +16,7 @@ */ package org.springframework.data.gemfire.config.annotation.support; -import static org.springframework.data.gemfire.util.CollectionUtils.asSet; import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalArgumentException; -import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalStateException; import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; @@ -50,12 +48,14 @@ import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.env.Environment; import org.springframework.core.type.AnnotationMetadata; import org.springframework.core.type.MethodMetadata; +import org.springframework.data.gemfire.util.CollectionUtils; import org.springframework.expression.EvaluationContext; import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.expression.spel.support.StandardTypeConverter; import org.springframework.expression.spel.support.StandardTypeLocator; import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; +import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; @@ -63,17 +63,18 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * The {@link AbstractAnnotationConfigSupport} class is an abstract base class encapsulating functionality - * common to all Annotations and configuration classes used to configure Pivotal GemFire/Apache Geode objects - * with Spring Data GemFire or Spring Data Geode. + * An abstract base class encapsulating functionality common to all Spring Data for Apache Geode (SDG) annotations + * and configuration classes used to configure Apache Geode objects using Spring Data for Apache Geode. * * @author John Blum * @author Udo Kohlmeyer * @see java.lang.ClassLoader * @see java.lang.annotation.Annotation + * @see java.lang.reflect.AnnotatedElement * @see org.springframework.beans.factory.BeanClassLoaderAware * @see org.springframework.beans.factory.BeanFactory * @see org.springframework.beans.factory.BeanFactoryAware + * @see org.springframework.beans.factory.annotation.AnnotatedBeanDefinition * @see org.springframework.beans.factory.config.ConfigurableBeanFactory * @see org.springframework.beans.factory.support.AbstractBeanDefinition * @see org.springframework.beans.factory.support.BeanDefinitionRegistry @@ -90,12 +91,15 @@ public abstract class AbstractAnnotationConfigSupport implements BeanClassLoaderAware, BeanFactoryAware, EnvironmentAware { protected static final Set INFRASTRUCTURE_ROLES = - asSet(BeanDefinition.ROLE_INFRASTRUCTURE, BeanDefinition.ROLE_SUPPORT); + CollectionUtils.asSet(BeanDefinition.ROLE_INFRASTRUCTURE, BeanDefinition.ROLE_SUPPORT); protected static final String ORG_SPRINGFRAMEWORK_DATA_GEMFIRE_PACKAGE = "org.springframework.data.gemfire"; protected static final String ORG_SPRINGFRAMEWORK_PACKAGE = "org.springframework"; protected static final String SPRING_DATA_GEMFIRE_PROPERTY_PREFIX = "spring.data.gemfire."; + protected static final Supplier CURRENT_THREAD_CONTEXT_CLASS_LOADER = + () -> Thread.currentThread().getContextClassLoader(); + private BeanFactory beanFactory; private ClassLoader beanClassLoader; @@ -104,7 +108,22 @@ public abstract class AbstractAnnotationConfigSupport private final EvaluationContext evaluationContext; - private final Logger log; + private final Logger logger; + + /** + * Asserts the given, configured {@link Object} is not {@literal null}. + * + * @param {@link Class type} of the {@link Object} to assert. + * @param object {@link Object} reference to assert as not {@literal null}. + * @param message {@link String} containing the message used in the {@link IllegalStateException} + * thrown by this assertion if the {@link Object} is {@literal null}. + * @return the given {@link Object} used as the subject of this assertion. + * @throws IllegalStateException if the {@link Object} is {@literal null}. + */ + private static T assertReferenceAndReturn(T object, String message) { + Assert.state(object != null, message); + return object; + } /** * Determines whether the given {@link Number} has value. @@ -155,17 +174,18 @@ public abstract class AbstractAnnotationConfigSupport } /** - * Constructs a new instance of {@link AbstractAnnotationConfigSupport}. + * Constructs a new instance of {@link AbstractAnnotationConfigSupport} initialized with the given, non-required + * {@link BeanFactory}. * * @param beanFactory reference to the Spring {@link BeanFactory}. * @see org.springframework.beans.factory.BeanFactory * @see #newEvaluationContext(BeanFactory) - * @see #newLog() + * @see #newLogger() */ public AbstractAnnotationConfigSupport(@Nullable BeanFactory beanFactory) { this.evaluationContext = newEvaluationContext(beanFactory); - this.log = newLog(); + this.logger = newLogger(); } /** @@ -207,13 +227,13 @@ public abstract class AbstractAnnotationConfigSupport } /** - * Constructs a new instance of {@link Logger} to log statements printed by Spring Data GemFire/Geode. + * Constructs a new instance of {@link Logger} to log statements printed by Spring Data for Apache Geode. * * @return a new instance of {@link Logger}. - * @see org.apache.commons.logging.LogFactory#getLog(Class) - * @see org.apache.commons.logging.Log + * @see org.slf4j.LoggerFactory#getLogger(Class) + * @see org.slf4j.Logger */ - protected Logger newLog() { + protected @NonNull Logger newLogger() { return LoggerFactory.getLogger(getClass()); } @@ -324,12 +344,14 @@ public abstract class AbstractAnnotationConfigSupport } /** - * Null-safe method to determine whether the given {@link Object bean} is a Spring container provided + * Null-safe method used to determine whether the given {@link Object bean} is a Spring container provided * infrastructure bean. * * @param bean {@link Object} to evaluate. - * @return {@literal true} iff the {@link Object bean} is not a Spring container infrastructure bean. + * @return {@literal true} iff the {@link Object bean} is not a Spring container provided infrastructure bean. * @see #isNotInfrastructureClass(String) + * @see java.lang.Object#getClass() + * @see java.lang.Class#getName() */ protected boolean isNotInfrastructureBean(@Nullable Object bean) { @@ -341,12 +363,12 @@ public abstract class AbstractAnnotationConfigSupport } /** - * Null-safe method to determine whether the bean defined in the given {@link BeanDefinition} + * Null-safe method used to determine whether the bean defined by the given {@link BeanDefinition} * is a Spring container provided infrastructure bean. * * @param beanDefinition {@link BeanDefinition} to evaluate. - * @return {@literal true} iff the bean defined in the given {@link BeanDefinition} is not a Spring container - * infrastructure bean. + * @return {@literal true} iff the bean defined by the given {@link BeanDefinition} is not a Spring container + * provided infrastructure bean. * @see org.springframework.beans.factory.config.BeanDefinition * @see #isNotInfrastructureClass(BeanDefinition) * @see #isNotInfrastructureRole(BeanDefinition) @@ -356,12 +378,12 @@ public abstract class AbstractAnnotationConfigSupport } /** - * Null-safe method to determine whether the bean defined in the given {@link BeanDefinition} - * is a Spring container infrastructure bean based on the bean's {@link Class#getName() class type}. + * Null-safe method used to determine whether the bean defined by the given {@link BeanDefinition} + * is a Spring container infrastructure bean based on the bean's class name. * * @param beanDefinition {@link BeanDefinition} of the bean to evaluate. * @return {@literal true} iff the bean defined in the given {@link BeanDefinition} is not a Spring container - * infrastructure bean. + * infrastructure bean. Returns {@literal false} if the bean class name cannot be resolved. * @see org.springframework.beans.factory.config.BeanDefinition * @see #resolveBeanClassName(BeanDefinition) * @see #isNotInfrastructureClass(String) @@ -374,17 +396,19 @@ public abstract class AbstractAnnotationConfigSupport } /** - * Determines whether the given {@link Class#getName() class type name} is considered a Spring container + * Determines whether the given {@link Class#getName() class name} is considered a Spring container * infrastructure type. * - * The class type name is considered a Spring container infrastructure type if the package name begins with - * 'org.springframework', excluding 'org.springframework.data.gemfire'. + * The {@link String class name} is considered a Spring container infrastructure type if the package name + * begins with {@literal org.springframework}, excluding {@literal org.springframework.data.gemfire}. * - * @param className {@link String} containing the name of the class type to evaluate. - * @return {@literal true} iff the given {@link Class#getName() class type name} is not considered a - * Spring container infrastructure type. + * @param className {@link String} containing the {@literal name} of the class type to evaluate; + * must not be {@literal null}. + * @return {@literal true} iff the given {@link Class#getName() class name} is not considered a Spring container + * infrastructure type. */ - protected boolean isNotInfrastructureClass(@NonNull String className) { + boolean isNotInfrastructureClass(@NonNull String className) { + return className.startsWith(ORG_SPRINGFRAMEWORK_DATA_GEMFIRE_PACKAGE) || !className.startsWith(ORG_SPRINGFRAMEWORK_PACKAGE); } @@ -454,8 +478,10 @@ public abstract class AbstractAnnotationConfigSupport * @see #getBeanClassLoader() */ protected @NonNull ClassLoader resolveBeanClassLoader() { - return Optional.ofNullable(getBeanClassLoader()) - .orElseGet(() -> Thread.currentThread().getContextClassLoader()); + + ClassLoader beanClassLoader = getBeanClassLoader(); + + return beanClassLoader != null ? beanClassLoader : CURRENT_THREAD_CONTEXT_CLASS_LOADER.get(); } /** @@ -475,8 +501,7 @@ public abstract class AbstractAnnotationConfigSupport * @see org.springframework.beans.factory.BeanFactory */ protected @NonNull BeanFactory getBeanFactory() { - return Optional.ofNullable(this.beanFactory) - .orElseThrow(() -> newIllegalStateException("BeanFactory is required")); + return assertReferenceAndReturn(this.beanFactory, "BeanFactory is required"); } /** @@ -517,8 +542,8 @@ public abstract class AbstractAnnotationConfigSupport * @return a reference to the {@link Logger} used by this class to log {@link String messages}. * @see org.apache.commons.logging.Log */ - protected @NonNull Logger getLog() { - return this.log; + protected @NonNull Logger getLogger() { + return this.logger; } /** @@ -538,10 +563,10 @@ public abstract class AbstractAnnotationConfigSupport * @param message {@link Supplier} containing the {@link String message} and arguments to log. * @see org.apache.commons.logging.Log#isDebugEnabled() * @see org.apache.commons.logging.Log#debug(Object) - * @see #getLog() + * @see #getLogger() */ protected void logDebug(Supplier message) { - Optional.ofNullable(getLog()) + Optional.ofNullable(getLogger()) .filter(Logger::isDebugEnabled) .ifPresent(log -> log.debug(message.get())); } @@ -563,10 +588,10 @@ public abstract class AbstractAnnotationConfigSupport * @param message {@link Supplier} containing the {@link String message} and arguments to log. * @see org.apache.commons.logging.Log#isInfoEnabled() * @see org.apache.commons.logging.Log#info(Object) - * @see #getLog() + * @see #getLogger() */ protected void logInfo(Supplier message) { - Optional.ofNullable(getLog()) + Optional.ofNullable(getLogger()) .filter(Logger::isInfoEnabled) .ifPresent(log -> log.info(message.get())); } @@ -588,10 +613,10 @@ public abstract class AbstractAnnotationConfigSupport * @param message {@link Supplier} containing the {@link String message} and arguments to log. * @see org.apache.commons.logging.Log#isWarnEnabled() * @see org.apache.commons.logging.Log#warn(Object) - * @see #getLog() + * @see #getLogger() */ protected void logWarning(Supplier message) { - Optional.ofNullable(getLog()) + Optional.ofNullable(getLogger()) .filter(Logger::isWarnEnabled) .ifPresent(log -> log.info(message.get())); } @@ -613,16 +638,17 @@ public abstract class AbstractAnnotationConfigSupport * @param message {@link Supplier} containing the {@link String message} and arguments to log. * @see org.apache.commons.logging.Log#isErrorEnabled() * @see org.apache.commons.logging.Log#error(Object) - * @see #getLog() + * @see #getLogger() */ protected void logError(Supplier message) { - Optional.ofNullable(getLog()) + Optional.ofNullable(getLogger()) .filter(Logger::isErrorEnabled) .ifPresent(log -> log.info(message.get())); } /** - * Registers the {@link AbstractBeanDefinition} with the {@link BeanDefinitionRegistry} using a generated bean name. + * Registers the {@link AbstractBeanDefinition} with the {@link BeanDefinitionRegistry} using a generated + * {@link String bean name}. * * @param beanDefinition {@link AbstractBeanDefinition} to register. * @return the given {@link AbstractBeanDefinition}. @@ -642,7 +668,8 @@ public abstract class AbstractAnnotationConfigSupport } /** - * Registers the {@link AbstractBeanDefinition} with the {@link BeanDefinitionRegistry} using a generated bean name. + * Registers the {@link AbstractBeanDefinition} with the given {@link BeanDefinitionRegistry} using a generated + * {@link String bean name}. * * @param beanDefinition {@link AbstractBeanDefinition} to register. * @param registry {@link BeanDefinitionRegistry} used to register the {@link AbstractBeanDefinition}. @@ -654,9 +681,9 @@ public abstract class AbstractAnnotationConfigSupport protected @NonNull AbstractBeanDefinition register(@NonNull AbstractBeanDefinition beanDefinition, @Nullable BeanDefinitionRegistry registry) { - Optional.ofNullable(registry).ifPresent(it -> - BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, it) - ); + if (registry != null) { + BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, registry); + } return beanDefinition; } @@ -852,9 +879,9 @@ public abstract class AbstractAnnotationConfigSupport */ protected A resolveAnnotation(AnnotatedElement annotatedElement, Class annotationType) { - return (annotatedElement instanceof Class + return annotatedElement instanceof Class ? AnnotatedElementUtils.findMergedAnnotation(annotatedElement, annotationType) - : AnnotationUtils.findAnnotation(annotatedElement, annotationType)); + : AnnotationUtils.findAnnotation(annotatedElement, annotationType); } /** @@ -869,7 +896,9 @@ public abstract class AbstractAnnotationConfigSupport * @see #resolveBeanClassLoader(BeanDefinitionRegistry) * @see #resolveBeanClass(BeanDefinition, ClassLoader) */ - protected Optional> resolveBeanClass(BeanDefinition beanDefinition, BeanDefinitionRegistry registry) { + protected Optional> resolveBeanClass(@Nullable BeanDefinition beanDefinition, + @Nullable BeanDefinitionRegistry registry) { + return resolveBeanClass(beanDefinition, resolveBeanClassLoader(registry)); } @@ -882,10 +911,13 @@ public abstract class AbstractAnnotationConfigSupport * @return an {@link Optional} {@link Class} specifying the resolved type of the bean. * @see org.springframework.beans.factory.config.BeanDefinition * @see org.springframework.beans.factory.config.ConfigurableBeanFactory + * @see #resolveBeanClassLoader(ConfigurableBeanFactory) * @see #resolveBeanClass(BeanDefinition, ClassLoader) */ - protected Optional> resolveBeanClass(BeanDefinition beanDefinition, ConfigurableBeanFactory beanFactory) { - return resolveBeanClass(beanDefinition, beanFactory.getBeanClassLoader()); + protected Optional> resolveBeanClass(@Nullable BeanDefinition beanDefinition, + @NonNull ConfigurableBeanFactory beanFactory) { + + return resolveBeanClass(beanDefinition, resolveBeanClassLoader(beanFactory)); } /** @@ -900,7 +932,8 @@ public abstract class AbstractAnnotationConfigSupport * @see org.springframework.util.ClassUtils#forName(String, ClassLoader) * @see #resolveBeanClassName(BeanDefinition) */ - protected Optional> resolveBeanClass(BeanDefinition beanDefinition, ClassLoader classLoader) { + protected Optional> resolveBeanClass(@Nullable BeanDefinition beanDefinition, + @Nullable ClassLoader classLoader) { Class beanClass = beanDefinition instanceof AbstractBeanDefinition ? safeResolveType(() -> ((AbstractBeanDefinition) beanDefinition).resolveBeanClass(classLoader)) @@ -908,9 +941,8 @@ public abstract class AbstractAnnotationConfigSupport if (beanClass == null) { beanClass = resolveBeanClassName(beanDefinition) - .map(beanClassName -> - safeResolveType(() -> - ClassUtils.forName(beanClassName, classLoader))).orElse(null); + .map(beanClassName -> safeResolveType(() -> ClassUtils.forName(beanClassName, classLoader))) + .orElse(null); } return Optional.ofNullable(beanClass); @@ -925,15 +957,35 @@ public abstract class AbstractAnnotationConfigSupport * or the {@link Thread#currentThread() current Thread's} {@link Thread#getContextClassLoader() context ClassLoader}. * @see org.springframework.beans.factory.config.ConfigurableBeanFactory#getBeanClassLoader() * @see org.springframework.beans.factory.support.BeanDefinitionRegistry - * @see java.lang.Thread#currentThread() * @see java.lang.Thread#getContextClassLoader() + * @see java.lang.Thread#currentThread() */ - protected ClassLoader resolveBeanClassLoader(BeanDefinitionRegistry registry) { + protected @NonNull ClassLoader resolveBeanClassLoader(@Nullable BeanDefinitionRegistry registry) { return Optional.ofNullable(registry) - .filter(it -> it instanceof ConfigurableBeanFactory) - .map(it -> ((ConfigurableBeanFactory) it).getBeanClassLoader()) - .orElseGet(() -> Thread.currentThread().getContextClassLoader()); + .filter(ConfigurableBeanFactory.class::isInstance) + .map(ConfigurableBeanFactory.class::cast) + .map(ConfigurableBeanFactory::getBeanClassLoader) + .orElseGet(CURRENT_THREAD_CONTEXT_CLASS_LOADER); + } + + /** + * Attempts to resolve the {@link ClassLoader} used by the {@link ConfigurableBeanFactory} + * to load {@link Class} definitions of the beans created by the factory. + * + * @param beanFactory {@link ConfigurableBeanFactory} from which to resolve the {@link ClassLoader}. + * @return the resolved {@link ClassLoader} from the {@link ConfigurableBeanFactory} + * or the {@link Thread#currentThread() current Thread's} {@link Thread#getContextClassLoader() context ClassLoader}. + * @see org.springframework.beans.factory.config.ConfigurableBeanFactory#getBeanClassLoader() + * @see org.springframework.beans.factory.config.ConfigurableBeanFactory + * @see java.lang.Thread#getContextClassLoader() + * @see java.lang.Thread#currentThread() + */ + protected @NonNull ClassLoader resolveBeanClassLoader(@Nullable ConfigurableBeanFactory beanFactory) { + + return Optional.ofNullable(beanFactory) + .map(ConfigurableBeanFactory::getBeanClassLoader) + .orElseGet(CURRENT_THREAD_CONTEXT_CLASS_LOADER); } /** @@ -946,15 +998,20 @@ public abstract class AbstractAnnotationConfigSupport */ protected Optional resolveBeanClassName(@Nullable BeanDefinition beanDefinition) { - Optional beanClassName = Optional.ofNullable(beanDefinition) + Optional optionalBeanDefinition = Optional.ofNullable(beanDefinition); + + Optional beanClassName = optionalBeanDefinition .map(BeanDefinition::getBeanClassName) .filter(StringUtils::hasText); - if (!beanClassName.isPresent()) { - beanClassName = Optional.ofNullable(beanDefinition) + boolean beanClassNameNotPresent = beanClassName.isEmpty(); + + if (beanClassNameNotPresent) { + beanClassName = optionalBeanDefinition .filter(AnnotatedBeanDefinition.class::isInstance) .filter(it -> StringUtils.hasText(it.getFactoryMethodName())) - .map(it -> ((AnnotatedBeanDefinition) it).getFactoryMethodMetadata()) + .map(AnnotatedBeanDefinition.class::cast) + .map(AnnotatedBeanDefinition::getFactoryMethodMetadata) .map(MethodMetadata::getReturnTypeName); } @@ -1084,17 +1141,19 @@ public abstract class AbstractAnnotationConfigSupport } /** - * Safely resolves a {@link Class type} returned by the supplied {@link TypeResolver} where the {@link Class type} - * resolution might result in a {@link ClassNotFoundException}, or possibly, {@link NoClassDefFoundError}. + * Safely resolves a {@link Class type} returned by the given {@link TypeResolver} where the {@link Class type} + * resolution might result in a {@link ClassNotFoundException} or {@link NoClassDefFoundError}. * * @param {@link Class} of the type being resolved. * @param typeResolver {@link TypeResolver} used to resolve a specific {@link Class type}. * @return the resolved {@link Class type} or {@literal null} if the {@link Class type} returned by * the {@link TypeResolver} could not be resolved. * @see org.springframework.data.gemfire.config.annotation.support.AbstractAnnotationConfigSupport.TypeResolver + * @see java.lang.ClassNotFoundException + * @see java.lang.NoClassDefFoundError * @see java.lang.Class */ - protected Class safeResolveType(TypeResolver typeResolver) { + protected @Nullable Class safeResolveType(@NonNull TypeResolver typeResolver) { try { return typeResolver.resolve(); @@ -1109,7 +1168,7 @@ public abstract class AbstractAnnotationConfigSupport * used to resolve a particular {@link Class type}. * * Implementations are free to decide on how a {@link Class type} gets resolved, such as - * with {@link Class#forName(String)} or perhaps by using {@link ClassLoader#defineClass(String, byte[], int, int)}. + * with {@link Class#forName(String)} or by using {@literal ClassLoader#defineClass(String, byte[], int, int)}. * * @param {@link Class} of the type to resolve. */ diff --git a/spring-data-geode/src/test/java/org/springframework/data/gemfire/config/annotation/support/AbstractAnnotationConfigSupportTests.java b/spring-data-geode/src/test/java/org/springframework/data/gemfire/config/annotation/support/AbstractAnnotationConfigSupportUnitTests.java similarity index 86% rename from spring-data-geode/src/test/java/org/springframework/data/gemfire/config/annotation/support/AbstractAnnotationConfigSupportTests.java rename to spring-data-geode/src/test/java/org/springframework/data/gemfire/config/annotation/support/AbstractAnnotationConfigSupportUnitTests.java index 06f54721..38da9baa 100644 --- a/spring-data-geode/src/test/java/org/springframework/data/gemfire/config/annotation/support/AbstractAnnotationConfigSupportTests.java +++ b/spring-data-geode/src/test/java/org/springframework/data/gemfire/config/annotation/support/AbstractAnnotationConfigSupportUnitTests.java @@ -19,6 +19,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; @@ -37,6 +38,8 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.junit.MockitoJUnitRunner; +import org.apache.geode.cache.GemFireCache; + import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.ConfigurableBeanFactory; @@ -63,7 +66,7 @@ import org.springframework.data.gemfire.test.model.Person; * @since 1.1.0 */ @RunWith(MockitoJUnitRunner.class) -public class AbstractAnnotationConfigSupportTests { +public class AbstractAnnotationConfigSupportUnitTests { private AbstractAnnotationConfigSupport support; @@ -76,14 +79,38 @@ public class AbstractAnnotationConfigSupportTests { AbstractBeanDefinition mockBeanDefinition = mock(AbstractBeanDefinition.class, beanClass.getSimpleName()); - when(mockBeanDefinition.getBeanClassName()).thenReturn(beanClass.getName()); - when(mockBeanDefinition.getRole()).thenReturn(BeanDefinition.ROLE_APPLICATION); + doReturn(beanClass.getName()).when(mockBeanDefinition).getBeanClassName(); + doReturn(BeanDefinition.ROLE_APPLICATION).when(mockBeanDefinition).getRole(); return mockBeanDefinition; } @Test - public void isNotInfrastructureBeanIsTrue() { + public void isNotInfrastructureBeanWithApacheGeodeClassIsTrue() { + + BeanDefinition mockBeanDefinition = mockBeanDefinition(GemFireCache.class); + + assertThat(this.support.isNotInfrastructureBean(mockBeanDefinition)).isTrue(); + + verify(mockBeanDefinition, times(1)).getBeanClassName(); + verify(mockBeanDefinition, times(1)).getRole(); + verifyNoMoreInteractions(mockBeanDefinition); + } + + @Test + public void isNotInfrastructureBeanWithObjectClassIsTrue() { + + BeanDefinition mockBeanDefinition = mockBeanDefinition(Object.class); + + assertThat(this.support.isNotInfrastructureBean(mockBeanDefinition)).isTrue(); + + verify(mockBeanDefinition, times(1)).getBeanClassName(); + verify(mockBeanDefinition, times(1)).getRole(); + verifyNoMoreInteractions(mockBeanDefinition); + } + + @Test + public void isNotInfrastructureBeanWithSpringDataGeodeGemfireTemplateClassIsTrue() { BeanDefinition mockBeanDefinition = mockBeanDefinition(GemfireTemplate.class); @@ -91,10 +118,11 @@ public class AbstractAnnotationConfigSupportTests { verify(mockBeanDefinition, times(1)).getBeanClassName(); verify(mockBeanDefinition, times(1)).getRole(); + verifyNoMoreInteractions(mockBeanDefinition); } @Test - public void isNotInfrastructureBeanWithInfrastructureClassIsFalse() { + public void isNotInfrastructureBeanWithSpringFrameworkInfrastructureClassIsFalse() { BeanDefinition mockBeanDefinition = mockBeanDefinition(SpringVersion.class); @@ -102,6 +130,7 @@ public class AbstractAnnotationConfigSupportTests { verify(mockBeanDefinition, times(1)).getBeanClassName(); verify(mockBeanDefinition, times(1)).getRole(); + verifyNoMoreInteractions(mockBeanDefinition); } @Test @@ -109,32 +138,35 @@ public class AbstractAnnotationConfigSupportTests { BeanDefinition mockBeanDefinition = mockBeanDefinition(Object.class); - when(mockBeanDefinition.getRole()).thenReturn(BeanDefinition.ROLE_INFRASTRUCTURE); + doReturn(BeanDefinition.ROLE_INFRASTRUCTURE).when(mockBeanDefinition).getRole(); assertThat(this.support.isNotInfrastructureBean(mockBeanDefinition)).isFalse(); verify(mockBeanDefinition, never()).getBeanClassName(); verify(mockBeanDefinition, times(1)).getRole(); + verifyNoMoreInteractions(mockBeanDefinition); } @Test - public void isNotInfrastructureClassWithBeanDefinitionIsTrue() { + public void isNotInfrastructureClassWithObjectBeanDefinitionIsTrue() { BeanDefinition mockBeanDefinition = mockBeanDefinition(Object.class); assertThat(this.support.isNotInfrastructureClass(mockBeanDefinition)).isTrue(); verify(mockBeanDefinition, times(1)).getBeanClassName(); + verifyNoMoreInteractions(mockBeanDefinition); } @Test - public void isNotInfrastructureClassWithBeanDefinitionIsFalse() { + public void isNotInfrastructureClassWithSpringInfrastructureBeanDefinitionIsFalse() { BeanDefinition mockBeanDefinition = mockBeanDefinition(SpringVersion.class); assertThat(this.support.isNotInfrastructureClass(mockBeanDefinition)).isFalse(); verify(mockBeanDefinition, times(1)).getBeanClassName(); + verifyNoMoreInteractions(mockBeanDefinition); } @Test @@ -145,8 +177,7 @@ public class AbstractAnnotationConfigSupportTests { @Test public void isNotInfrastructureClassIsFalse() { assertThat(this.support.isNotInfrastructureClass("org.springframework.SomeType")).isFalse(); - assertThat(this.support.isNotInfrastructureClass("org.springframework.core.type.SomeType")) - .isFalse(); + assertThat(this.support.isNotInfrastructureClass("org.springframework.core.type.SomeType")).isFalse(); } @Test @@ -154,12 +185,13 @@ public class AbstractAnnotationConfigSupportTests { BeanDefinition mockBeanDefinition = mock(BeanDefinition.class); - when(mockBeanDefinition.getRole()).thenReturn(BeanDefinition.ROLE_APPLICATION).thenReturn(Integer.MAX_VALUE); + doReturn(BeanDefinition.ROLE_APPLICATION).doReturn(Integer.MAX_VALUE).when(mockBeanDefinition).getRole(); assertThat(this.support.isNotInfrastructureRole(mockBeanDefinition)).isTrue(); assertThat(this.support.isNotInfrastructureRole(mockBeanDefinition)).isTrue(); verify(mockBeanDefinition, times(2)).getRole(); + verifyNoMoreInteractions(mockBeanDefinition); } @Test @@ -167,13 +199,14 @@ public class AbstractAnnotationConfigSupportTests { BeanDefinition mockBeanDefinition = mock(BeanDefinition.class); - when(mockBeanDefinition.getRole()).thenReturn(BeanDefinition.ROLE_INFRASTRUCTURE) - .thenReturn(BeanDefinition.ROLE_SUPPORT); + doReturn(BeanDefinition.ROLE_INFRASTRUCTURE).doReturn(BeanDefinition.ROLE_SUPPORT) + .when(mockBeanDefinition).getRole(); assertThat(this.support.isNotInfrastructureRole(mockBeanDefinition)).isFalse(); assertThat(this.support.isNotInfrastructureRole(mockBeanDefinition)).isFalse(); verify(mockBeanDefinition, times(2)).getRole(); + verifyNoMoreInteractions(mockBeanDefinition); } @Test @@ -195,9 +228,9 @@ public class AbstractAnnotationConfigSupportTests { @Test public void requirePropertyWithNonStringValueIsSuccessful() { - when(support.resolveProperty(anyString(), eq(Integer.class), eq(null))).thenReturn(1); + when(this.support.resolveProperty(anyString(), eq(Integer.class), eq(null))).thenReturn(1); - assertThat(support.requireProperty("key", Integer.class)).isEqualTo(1); + assertThat(this.support.requireProperty("key", Integer.class)).isEqualTo(1); verify(support, times(1)) .resolveProperty(eq("key"), eq(Integer.class), eq(null)); @@ -206,21 +239,21 @@ public class AbstractAnnotationConfigSupportTests { @Test public void requirePropertyWithStringValueIsSuccessful() { - when(support.resolveProperty(anyString(), eq(String.class), eq(null))).thenReturn("test"); + when(this.support.resolveProperty(anyString(), eq(String.class), eq(null))).thenReturn("test"); - assertThat(support.requireProperty("key", String.class)).isEqualTo("test"); + assertThat(this.support.requireProperty("key", String.class)).isEqualTo("test"); - verify(support, times(1)) + verify(this.support, times(1)) .resolveProperty(eq("key"), eq(String.class), eq(null)); } @Test(expected = IllegalArgumentException.class) public void requirePropertyWithEmptyStringThrowsIllegalArgumentException() { - when(support.resolveProperty(anyString(), eq(String.class), eq(null))).thenReturn(" "); + when(this.support.resolveProperty(anyString(), eq(String.class), eq(null))).thenReturn(" "); try { - support.requireProperty("key", String.class); + this.support.requireProperty("key", String.class); } catch (IllegalArgumentException expected) { @@ -230,7 +263,7 @@ public class AbstractAnnotationConfigSupportTests { throw expected; } finally { - verify(support, times(1)) + verify(this.support, times(1)) .resolveProperty(eq("key"), eq(String.class), eq(null)); } } @@ -238,10 +271,10 @@ public class AbstractAnnotationConfigSupportTests { @Test(expected = IllegalArgumentException.class) public void requirePropertyWithNullValueThrowsIllegalArgumentException() { - when(support.resolveProperty(anyString(), any(), eq(null))).thenReturn(null); + when(this.support.resolveProperty(anyString(), any(), eq(null))).thenReturn(null); try { - support.requireProperty("key", Integer.class); + this.support.requireProperty("key", Integer.class); } catch (IllegalArgumentException expected) { assertThat(expected).hasMessage("Property [key] is required"); @@ -250,7 +283,7 @@ public class AbstractAnnotationConfigSupportTests { throw expected; } finally { - verify(support, times(1)) + verify(this.support, times(1)) .resolveProperty(eq("key"), eq(Integer.class), eq(null)); } } @@ -378,7 +411,7 @@ public class AbstractAnnotationConfigSupportTests { @Test public void resolveBeanClassLoaderIsNullSafe() { - assertThat(this.support.resolveBeanClassLoader(null)) + assertThat(this.support.resolveBeanClassLoader((BeanDefinitionRegistry) null)) .isEqualTo(Thread.currentThread().getContextClassLoader()); }