From c37ae270a4e8fa54b7e11fbc57688ebb549457b2 Mon Sep 17 00:00:00 2001 From: John Blum Date: Thu, 12 Dec 2019 17:34:04 -0800 Subject: [PATCH] DATAGEODE-280 - Refactor ContinuousQueryListenerContainer to use PoolResolver. --- .../data/gemfire/GemfireUtils.java | 19 -- .../ContinuousQueryListenerContainer.java | 181 ++++++++---- .../data/gemfire/util/CollectionUtils.java | 1 - .../data/gemfire/util/SpringUtils.java | 17 ++ ...inuousQueryListenerContainerUnitTests.java | 268 ++++++++++++------ .../gemfire/util/SpringUtilsUnitTests.java | 45 +++ 6 files changed, 365 insertions(+), 166 deletions(-) diff --git a/spring-data-geode/src/main/java/org/springframework/data/gemfire/GemfireUtils.java b/spring-data-geode/src/main/java/org/springframework/data/gemfire/GemfireUtils.java index 4f33aea5..73e65dd9 100644 --- a/spring-data-geode/src/main/java/org/springframework/data/gemfire/GemfireUtils.java +++ b/spring-data-geode/src/main/java/org/springframework/data/gemfire/GemfireUtils.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.gemfire; import org.apache.geode.cache.CacheFactory; @@ -26,13 +25,8 @@ import org.springframework.data.gemfire.util.RegionUtils; import org.springframework.util.ClassUtils; /** -<<<<<<< HEAD - * {@link GemfireUtils} is an abstract utility class encapsulating common functionality to access features - * and capabilities of GemFire based on version and other configuration meta-data. -======= * {@link GemfireUtils} is an abstract utility class encapsulating common functionality for accessing features * and capabilities of Apache Geode or Pivotal GemFire based on version as well as other configuration meta-data. ->>>>>>> 284e248b... SGF-826 - Move away from Spring Data Commons deprecations. * * @author John Blum * @see org.apache.geode.cache.CacheFactory @@ -58,7 +52,6 @@ public abstract class GemfireUtils extends RegionUtils { private static final String GATEWAY_SENDER_ELEMENT_NAME = "gateway-sender"; private static final String GATEWAY_SENDER_TYPE_NAME = "org.apache.geode.internal.cache.wan.GatewaySenderFactoryImpl"; - /* (non-Javadoc) */ public static String apacheGeodeProductName() { try { @@ -69,7 +62,6 @@ public abstract class GemfireUtils extends RegionUtils { } } - /* (non-Javadoc) */ public static String apacheGeodeVersion() { try { @@ -80,12 +72,10 @@ public abstract class GemfireUtils extends RegionUtils { } } - /* (non-Javadoc) */ public static boolean isClassAvailable(String fullyQualifiedClassName) { return ClassUtils.isPresent(fullyQualifiedClassName, GemfireUtils.class.getClassLoader()); } - /* (non-Javadoc) */ public static boolean isGemfireFeatureAvailable(GemfireFeature feature) { boolean featureAvailable = (!GemfireFeature.AEQ.equals(feature) || isAsyncEventQueueAvailable()); @@ -96,7 +86,6 @@ public abstract class GemfireUtils extends RegionUtils { return featureAvailable; } - /* (non-Javadoc) */ public static boolean isGemfireFeatureAvailable(Element element) { boolean featureAvailable = (!isAsyncEventQueue(element) || isAsyncEventQueueAvailable()); @@ -107,37 +96,30 @@ public abstract class GemfireUtils extends RegionUtils { return featureAvailable; } - /* (non-Javadoc) */ public static boolean isGemfireFeatureUnavailable(GemfireFeature feature) { return !isGemfireFeatureAvailable(feature); } - /* (non-Javadoc) */ public static boolean isGemfireFeatureUnavailable(Element element) { return !isGemfireFeatureAvailable(element); } - /* (non-Javadoc) */ private static boolean isAsyncEventQueue(Element element) { return ASYNC_EVENT_QUEUE_ELEMENT_NAME.equals(element.getLocalName()); } - /* (non-Javadoc) */ private static boolean isAsyncEventQueueAvailable() { return isClassAvailable(ASYNC_EVENT_QUEUE_TYPE_NAME); } - /* (non-Javadoc) */ private static boolean isContinuousQuery(Element element) { return CQ_ELEMENT_NAME.equals(element.getLocalName()); } - /* (non-Javadoc) */ private static boolean isContinuousQueryAvailable() { return isClassAvailable(CQ_TYPE_NAME); } - /* (non-Javadoc) */ private static boolean isGateway(Element element) { String elementLocalName = element.getLocalName(); @@ -146,7 +128,6 @@ public abstract class GemfireUtils extends RegionUtils { || GATEWAY_SENDER_ELEMENT_NAME.equals(elementLocalName)); } - /* (non-Javadoc) */ private static boolean isGatewayAvailable() { return isClassAvailable(GATEWAY_SENDER_TYPE_NAME); } diff --git a/spring-data-geode/src/main/java/org/springframework/data/gemfire/listener/ContinuousQueryListenerContainer.java b/spring-data-geode/src/main/java/org/springframework/data/gemfire/listener/ContinuousQueryListenerContainer.java index 6bd098a7..d01d2ceb 100644 --- a/spring-data-geode/src/main/java/org/springframework/data/gemfire/listener/ContinuousQueryListenerContainer.java +++ b/spring-data-geode/src/main/java/org/springframework/data/gemfire/listener/ContinuousQueryListenerContainer.java @@ -13,12 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.gemfire.listener; import static org.springframework.data.gemfire.util.CollectionUtils.nullSafeList; import static org.springframework.data.gemfire.util.CollectionUtils.nullSafeSet; -import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalArgumentException; import java.util.Arrays; import java.util.Collections; @@ -34,7 +32,6 @@ import java.util.stream.StreamSupport; import org.apache.geode.cache.RegionService; import org.apache.geode.cache.client.Pool; -import org.apache.geode.cache.client.PoolManager; import org.apache.geode.cache.query.CqAttributes; import org.apache.geode.cache.query.CqEvent; import org.apache.geode.cache.query.CqException; @@ -57,18 +54,22 @@ import org.springframework.core.task.SimpleAsyncTaskExecutor; import org.springframework.core.task.TaskExecutor; import org.springframework.data.gemfire.GemfireQueryException; import org.springframework.data.gemfire.GemfireUtils; +import org.springframework.data.gemfire.client.PoolResolver; import org.springframework.data.gemfire.client.support.DefaultableDelegatingPoolAdapter; import org.springframework.data.gemfire.client.support.DelegatingPoolAdapter; +import org.springframework.data.gemfire.client.support.PoolManagerPoolResolver; import org.springframework.data.gemfire.config.annotation.ContinuousQueryListenerContainerConfigurer; import org.springframework.data.gemfire.config.xml.GemfireConstants; import org.springframework.data.gemfire.util.ArrayUtils; import org.springframework.data.gemfire.util.CollectionUtils; +import org.springframework.data.gemfire.util.SpringUtils; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ErrorHandler; import org.springframework.util.StringUtils; /** - * Container providing asynchronous processing/handling for Pivotal GemFire / Apache Geode Continuous Queries (CQ). + * Container providing asynchronous processing/handling for Apache Geode Continuous Queries (CQ). * * @author Costin Leau * @author John Blum @@ -89,6 +90,7 @@ import org.springframework.util.StringUtils; * @see org.springframework.context.SmartLifecycle * @see org.springframework.core.task.SimpleAsyncTaskExecutor * @see org.springframework.core.task.TaskExecutor + * @see org.springframework.data.gemfire.client.PoolResolver * @see org.springframework.data.gemfire.client.support.DefaultableDelegatingPoolAdapter * @see org.springframework.data.gemfire.client.support.DelegatingPoolAdapter * @see org.springframework.util.ErrorHandler @@ -102,6 +104,9 @@ public class ContinuousQueryListenerContainer implements BeanFactoryAware, BeanN public static final String DEFAULT_THREAD_NAME_PREFIX = String.format("%s-", ContinuousQueryListenerContainer.class.getSimpleName()); + // Default PoolResolver uses Apache Geode's PoolManager + protected static final PoolResolver DEFAULT_POOL_RESOLVER = new PoolManagerPoolResolver(); + private boolean autoStartup = true; private volatile boolean initialized = false; @@ -124,6 +129,8 @@ public class ContinuousQueryListenerContainer implements BeanFactoryAware, BeanN protected final Logger logger = LoggerFactory.getLogger(getClass()); + private PoolResolver poolResolver = DEFAULT_POOL_RESOLVER; + private Queue continuousQueries = new ConcurrentLinkedQueue<>(); private QueryService queryService; @@ -144,12 +151,19 @@ public class ContinuousQueryListenerContainer implements BeanFactoryAware, BeanN this.initialized = true; } + /** + * Applies configuration customizations to this {@link ContinuousQueryListenerContainer} from the registered + * composite {@link ContinuousQueryListenerContainerConfigurer} objects. + * + * @see #getCompositeContinuousQueryListenerContainerConfigurer() + * @see #applyContinuousQueryListenerContainerConfigurers(ContinuousQueryListenerContainerConfigurer...) + */ private void applyContinuousQueryListenerContainerConfigurers() { applyContinuousQueryListenerContainerConfigurers(getCompositeContinuousQueryListenerContainerConfigurer()); } /** - * Applies the array of {@link ContinuousQueryListenerContainerConfigurer} objects to customize the configuration + * Applies an array of {@link ContinuousQueryListenerContainerConfigurer} objects to customize the configuration * of this {@link ContinuousQueryListenerContainer}. * * @param configurers array of {@link ContinuousQueryListenerContainerConfigurer} used to customize @@ -166,7 +180,7 @@ public class ContinuousQueryListenerContainer implements BeanFactoryAware, BeanN } /** - * Applies the {@link Iterable} of {@link ContinuousQueryListenerContainerConfigurer} objects to customize + * Applies an {@link Iterable} of {@link ContinuousQueryListenerContainerConfigurer} objects to customize * the configuration of this {@link ContinuousQueryListenerContainer}. * * @param configurers {@link Iterable} of {@link ContinuousQueryListenerContainerConfigurer} used to customize @@ -180,6 +194,18 @@ public class ContinuousQueryListenerContainer implements BeanFactoryAware, BeanN .forEach(configurer -> configurer.configure(getBeanName(), this)); } + /** + * Resolves a {@link Pool} object with the given {@link String name} from the configured {@link PoolResolver}. + * + * @param poolName {@link String name} of the {@link Pool} to resolve. + * @return a resolved {@link Pool} object from the given {@link String name}. + * @see org.apache.geode.cache.client.Pool + * @see #getPoolResolver() + */ + @Nullable Pool resolvePool(String poolName) { + return getPoolResolver().resolve(poolName); + } + /** * Resolves the name of the {@link Pool} configured to handle the registered Continuous Queries. * @@ -193,7 +219,7 @@ public class ContinuousQueryListenerContainer implements BeanFactoryAware, BeanN .filter(StringUtils::hasText) .orElseGet(() -> Optional.ofNullable(getBeanFactory()) - .filter(it -> it.containsBean(GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME)) + .filter(it -> SpringUtils.isMatchingBean(it, GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME, Pool.class)) .map(it -> GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME) .orElse(GemfireUtils.DEFAULT_POOL_NAME)); } @@ -207,7 +233,7 @@ public class ContinuousQueryListenerContainer implements BeanFactoryAware, BeanN * * However, if the {@link BeanFactory} was not configured, or no bean exists in the Spring container * with the given {@link String name} or of the {@link Pool} type, then the named {@link Pool} is looked up - * in GemFire/Geode's {@link PoolManager}. + * in GemFire/Geode's {@link org.apache.geode.cache.client.PoolManager}. * * @param poolName {@link String} containing the name of the {@link Pool} to initialize. * @return the given {@link Pool} name. @@ -215,13 +241,12 @@ public class ContinuousQueryListenerContainer implements BeanFactoryAware, BeanN String eagerlyInitializePool(String poolName) { Supplier poolNameResolver = () -> { - Assert.notNull(PoolManager.find(poolName), String.format("No Pool with name [%s] was found", poolName)); + Assert.notNull(resolvePool(poolName), String.format("No Pool with name [%s] was found", poolName)); return poolName; }; return Optional.ofNullable(getBeanFactory()) - .filter(it -> it.containsBean(poolName)) - .filter(it -> it.isTypeMatch(poolName, Pool.class)) + .filter(it -> SpringUtils.isMatchingBean(it, poolName, Pool.class)) .map(it -> { try { it.getBean(poolName, Pool.class); @@ -247,9 +272,13 @@ public class ContinuousQueryListenerContainer implements BeanFactoryAware, BeanN QueryService queryService = getQueryService(); if (queryService == null || StringUtils.hasText(poolName)) { - setQueryService(DefaultableDelegatingPoolAdapter.from( - DelegatingPoolAdapter.from(PoolManager.find(poolName))) - .preferPool().getQueryService(queryService)); + + Pool resolvedPool = resolvePool(poolName); + + DefaultableDelegatingPoolAdapter poolAdapter = + DefaultableDelegatingPoolAdapter.from(DelegatingPoolAdapter.from(resolvedPool)); + + setQueryService(poolAdapter.preferPool().getQueryService(queryService)); } return getQueryService(); @@ -308,7 +337,11 @@ public class ContinuousQueryListenerContainer implements BeanFactoryAware, BeanN } /** - * Initializes all the {@link CqQuery Continuous Queries} defined by the {@link ContinuousQueryDefinition defintions}. + * Initializes all the {@link CqQuery Continuous Queries} defined by + * the {@link ContinuousQueryDefinition Continuous Query Defintions}. + * + * @see #getContinuousQueryDefinitions() + * @see #initContinuousQueries(Set) */ private void initContinuousQueries() { initContinuousQueries(getContinuousQueryDefinitions()); @@ -317,17 +350,13 @@ public class ContinuousQueryListenerContainer implements BeanFactoryAware, BeanN private void initContinuousQueries(Set continuousQueryDefinitions) { // Stop the ContinuousQueryListenerContainer if currently running... - if (isRunning()) { - stop(); - } + stop(); // Close any existing continuous queries... closeQueries(); // Add current continuous queries based on the definitions from the configuration... - for (ContinuousQueryDefinition definition : continuousQueryDefinitions) { - addContinuousQuery(definition); - } + continuousQueryDefinitions.forEach(this::addContinuousQuery); } /** @@ -455,8 +484,11 @@ public class ContinuousQueryListenerContainer implements BeanFactoryAware, BeanN * @see #setContinuousQueryListenerContainerConfigurers(List) */ public void setContinuousQueryListenerContainerConfigurers(ContinuousQueryListenerContainerConfigurer... configurers) { - setContinuousQueryListenerContainerConfigurers(Arrays.asList( - ArrayUtils.nullSafeArray(configurers, ContinuousQueryListenerContainerConfigurer.class))); + + List configurerList = + Arrays.asList(ArrayUtils.nullSafeArray(configurers, ContinuousQueryListenerContainerConfigurer.class)); + + setContinuousQueryListenerContainerConfigurers(configurerList); } /** @@ -468,7 +500,7 @@ public class ContinuousQueryListenerContainer implements BeanFactoryAware, BeanN * @see org.springframework.data.gemfire.config.annotation.ContinuousQueryListenerContainerConfigurer */ public void setContinuousQueryListenerContainerConfigurers(List configurers) { - this.cqListenerContainerConfigurers = Optional.ofNullable(configurers).orElseGet(Collections::emptyList); + this.cqListenerContainerConfigurers = CollectionUtils.nullSafeList(configurers); } /** @@ -547,12 +579,35 @@ public class ContinuousQueryListenerContainer implements BeanFactoryAware, BeanN return this.poolName; } + /** + * Configures the {@link PoolResolver} to resolve {@link Pool} objects by {@link String name} + * from the Apache Geode cache. + * + * @param poolResolver the configured {@link PoolResolver} used to resolve {@link Pool} objects + * by {@link String name}. + * @see org.springframework.data.gemfire.client.PoolResolver + */ + public void setPoolResolver(PoolResolver poolResolver) { + this.poolResolver = poolResolver; + } + + /** + * Returns the configured {@link PoolResolver} used to resolve {@link Pool} object by {@link String name}. + * + * @return the configured {@link PoolResolver}. + * @see org.springframework.data.gemfire.client.PoolResolver + */ + public PoolResolver getPoolResolver() { + return this.poolResolver != null ? this.poolResolver : DEFAULT_POOL_RESOLVER; + } + /** * Attaches the given query definitions. * * @param queries set of queries */ public void setQueryListeners(Set queries) { + getContinuousQueryDefinitions().clear(); getContinuousQueryDefinitions().addAll(nullSafeSet(queries)); } @@ -630,8 +685,9 @@ public class ContinuousQueryListenerContainer implements BeanFactoryAware, BeanN CqAttributes attributes = definition.toCqAttributes(this::newCqListener); - CqQuery query = (definition.isNamed() ? newNamedContinuousQuery(definition, attributes) - : newUnnamedContinuousQuery(definition, attributes)); + CqQuery query = definition.isNamed() + ? newNamedContinuousQuery(definition, attributes) + : newUnnamedContinuousQuery(definition, attributes); return manage(query); } @@ -657,7 +713,9 @@ public class ContinuousQueryListenerContainer implements BeanFactoryAware, BeanN } private CqQuery manage(CqQuery query) { + getContinuousQueries().add(query); + return query; } @@ -669,8 +727,8 @@ public class ContinuousQueryListenerContainer implements BeanFactoryAware, BeanN doStart(); this.running = true; - if (logger.isDebugEnabled()) { - logger.debug("Started ContinuousQueryListenerContainer"); + if (this.logger.isDebugEnabled()) { + this.logger.debug("Started ContinuousQueryListenerContainer"); } } } @@ -737,22 +795,22 @@ public class ContinuousQueryListenerContainer implements BeanFactoryAware, BeanN boolean active = this.isActive(); - if (!active && logger.isDebugEnabled()) { - logger.debug("A CQ listener exception occurred after container shutdown; ErrorHandler will not be invoked", cause); + if (!active && this.logger.isDebugEnabled()) { + this.logger.debug("A CQ listener exception occurred after container shutdown; ErrorHandler will not be invoked", cause); } return active; }) .ifPresent(errorHandler -> errorHandler.handleError(cause)); - if (!getErrorHandler().isPresent() && logger.isWarnEnabled()) { - logger.warn("Execution of CQ listener failed; No ErrorHandler was configured", cause); + if (!getErrorHandler().isPresent() && this.logger.isWarnEnabled()) { + this.logger.warn("Execution of CQ listener failed; No ErrorHandler was configured", cause); } } @Override - @SuppressWarnings("all") public void stop(Runnable callback) { + stop(); callback.run(); } @@ -765,21 +823,20 @@ public class ContinuousQueryListenerContainer implements BeanFactoryAware, BeanN this.running = false; } - if (logger.isDebugEnabled()) { - logger.debug("Stopped ContinuousQueryListenerContainer"); + if (this.logger.isDebugEnabled()) { + this.logger.debug("Stopped ContinuousQueryListenerContainer"); } } void doStop() { getContinuousQueries().forEach(query -> { - try { query.stop(); } catch (Exception cause) { - if (logger.isWarnEnabled()) { - logger.warn(String.format("Cannot stop query [%1$s]; state is [%2$s]", + if (this.logger.isWarnEnabled()) { + this.logger.warn(String.format("Cannot stop query [%1$s]; state is [%2$s]", query.getName(), query.getState()), cause); } } @@ -787,26 +844,30 @@ public class ContinuousQueryListenerContainer implements BeanFactoryAware, BeanN } @Override - public void destroy() throws Exception { + public void destroy() { + stop(); closeQueries(); destroyExecutor(); + this.initialized = false; } private void closeQueries() { - getContinuousQueries().stream().filter(query -> !query.isClosed()).forEach(query -> { - try { - query.close(); - } - catch (Exception cause) { - if (logger.isWarnEnabled()) { - logger.warn(String.format("Cannot close query [%1$s]; state is [%2$s]", - query.getName(), query.getState()), cause); + getContinuousQueries().stream() + .filter(query -> !query.isClosed()) + .forEach(query -> { + try { + query.close(); } - } - }); + catch (Exception cause) { + if (logger.isWarnEnabled()) { + logger.warn(String.format("Cannot close query [%1$s]; state is [%2$s]", + query.getName(), query.getState()), cause); + } + } + }); getContinuousQueries().clear(); } @@ -815,17 +876,19 @@ public class ContinuousQueryListenerContainer implements BeanFactoryAware, BeanN Optional.ofNullable(getTaskExecutor()) .filter(it -> this.manageExecutor) - .filter(it -> it instanceof DisposableBean) + .filter(DisposableBean.class::isInstance) .ifPresent(it -> { try { + ((DisposableBean) it).destroy(); - if (logger.isDebugEnabled()) { - logger.debug("Stopped internally-managed TaskExecutor {}", it); + if (this.logger.isDebugEnabled()) { + this.logger.debug("Stopped internally-managed TaskExecutor {}", it); } } - catch (Exception ignore) { - logger.warn("Failed to properly destroy the managed TaskExecutor {}", it); + catch (Exception cause) { + this.logger.warn("Failed to properly destroy the managed TaskExecutor {}: {}", + it, cause.getMessage()); } }); } @@ -835,8 +898,10 @@ public class ContinuousQueryListenerContainer implements BeanFactoryAware, BeanN private final ContinuousQueryListener listener; protected EventDispatcherAdapter(ContinuousQueryListener listener) { - this.listener = Optional.ofNullable(listener) - .orElseThrow(() -> newIllegalArgumentException("ContinuousQueryListener is required")); + + Assert.notNull(listener, "ContinuousQueryListener is required"); + + this.listener = listener; } protected ContinuousQueryListener getListener() { @@ -851,7 +916,7 @@ public class ContinuousQueryListenerContainer implements BeanFactoryAware, BeanN dispatchEvent(getListener(), event); } - public void close() { - } + public void close() { } + } } diff --git a/spring-data-geode/src/main/java/org/springframework/data/gemfire/util/CollectionUtils.java b/spring-data-geode/src/main/java/org/springframework/data/gemfire/util/CollectionUtils.java index b0e613eb..89d86181 100644 --- a/spring-data-geode/src/main/java/org/springframework/data/gemfire/util/CollectionUtils.java +++ b/spring-data-geode/src/main/java/org/springframework/data/gemfire/util/CollectionUtils.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.gemfire.util; import static java.util.stream.StreamSupport.stream; diff --git a/spring-data-geode/src/main/java/org/springframework/data/gemfire/util/SpringUtils.java b/spring-data-geode/src/main/java/org/springframework/data/gemfire/util/SpringUtils.java index 0451ab02..2fb17b52 100644 --- a/spring-data-geode/src/main/java/org/springframework/data/gemfire/util/SpringUtils.java +++ b/spring-data-geode/src/main/java/org/springframework/data/gemfire/util/SpringUtils.java @@ -49,6 +49,23 @@ import org.springframework.util.StringUtils; @SuppressWarnings("unused") public abstract class SpringUtils { + /** + * Determines whether a given bean registered in the {@link BeanFactory Spring container} matches by + * both {@link String name} and {@link Class type}. + * + * @param beanFactory {@link BeanFactory Spring container} in which to resolve the bean. + * @param beanName {@link String name} of the bean. + * @param beanType {@link Class type} of the bean. + * @return a boolean value indicating whether the {@link BeanFactory Spring container} contains a bean + * matching by both {@link String name} as well as {@link Class type}. + * @see org.springframework.beans.factory.BeanFactory + * @see java.lang.Class + * @see java.lang.String + */ + public static boolean isMatchingBean(BeanFactory beanFactory, String beanName, Class beanType) { + return beanFactory.containsBean(beanName) && beanFactory.isTypeMatch(beanName, beanType); + } + public static BeanDefinition addDependsOn(BeanDefinition beanDefinition, String... beanNames) { List dependsOnList = new ArrayList<>(); diff --git a/spring-data-geode/src/test/java/org/springframework/data/gemfire/listener/ContinuousQueryListenerContainerUnitTests.java b/spring-data-geode/src/test/java/org/springframework/data/gemfire/listener/ContinuousQueryListenerContainerUnitTests.java index be8447e0..980a842f 100644 --- a/spring-data-geode/src/test/java/org/springframework/data/gemfire/listener/ContinuousQueryListenerContainerUnitTests.java +++ b/spring-data-geode/src/test/java/org/springframework/data/gemfire/listener/ContinuousQueryListenerContainerUnitTests.java @@ -22,7 +22,6 @@ import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isA; -import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; @@ -31,7 +30,7 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; import java.util.Arrays; @@ -53,13 +52,13 @@ import org.apache.geode.cache.query.CqQuery; import org.apache.geode.cache.query.CqState; import org.apache.geode.cache.query.QueryException; import org.apache.geode.cache.query.QueryService; -import org.apache.geode.internal.cache.PoolManagerImpl; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.data.gemfire.GemfireQueryException; import org.springframework.data.gemfire.GemfireUtils; +import org.springframework.data.gemfire.client.PoolResolver; import org.springframework.data.gemfire.config.xml.GemfireConstants; import org.springframework.util.ErrorHandler; @@ -80,6 +79,11 @@ public class ContinuousQueryListenerContainerUnitTests { private ContinuousQueryListenerContainer cqListenerContainer; + @Before + public void setup() { + this.cqListenerContainer = spy(new ContinuousQueryListenerContainer()); + } + private CqQuery mockCqQuery(String name, String query, CqAttributes attributes, boolean durable) { CqQuery mockQuery = mock(CqQuery.class); @@ -91,30 +95,27 @@ public class ContinuousQueryListenerContainerUnitTests { return mockQuery; } - @Before - public void setup() { - this.cqListenerContainer = spy(new ContinuousQueryListenerContainer()); - } @Test public void afterPropertiesSetIsAutoStart() { Pool mockPool = mock(Pool.class); + PoolResolver mockPoolResolver = mock(PoolResolver.class); + QueryService mockQueryService = mock(QueryService.class); - when(mockBeanFactory.containsBean(eq(GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME))).thenReturn(true); - when(mockBeanFactory.isTypeMatch(eq(GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME), eq(Pool.class))).thenReturn(true); - when(mockBeanFactory.getBean(eq(GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME), eq(Pool.class))).thenReturn(mockPool); - when(mockPool.getName()).thenReturn(GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME); + when(this.mockBeanFactory.containsBean(eq(GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME))).thenReturn(true); + when(this.mockBeanFactory.isTypeMatch(eq(GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME), eq(Pool.class))).thenReturn(true); + when(this.mockBeanFactory.getBean(eq(GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME), eq(Pool.class))).thenReturn(mockPool); + when(mockPoolResolver.resolve(eq(GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME))).thenReturn(mockPool); when(mockPool.getQueryService()).thenReturn(mockQueryService); + this.cqListenerContainer.setAutoStartup(true); + this.cqListenerContainer.setBeanFactory(this.mockBeanFactory); + this.cqListenerContainer.setPoolResolver(mockPoolResolver); + try { - - PoolManagerImpl.getPMI().register(mockPool); - - this.cqListenerContainer.setAutoStartup(true); - this.cqListenerContainer.setBeanFactory(this.mockBeanFactory); this.cqListenerContainer.afterPropertiesSet(); } finally { @@ -122,15 +123,16 @@ public class ContinuousQueryListenerContainerUnitTests { assertThat(this.cqListenerContainer.isActive()).isTrue(); assertThat(this.cqListenerContainer.isAutoStartup()).isTrue(); assertThat(this.cqListenerContainer.isRunning()).isFalse(); + assertThat(this.cqListenerContainer.getPoolResolver()).isEqualTo(mockPoolResolver); assertThat(this.cqListenerContainer.getQueryService()).isEqualTo(mockQueryService); assertThat(this.cqListenerContainer.getTaskExecutor()).isInstanceOf(Executor.class); verify(this.mockBeanFactory, times(2)).containsBean(eq(GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME)); - verify(this.mockBeanFactory, times(1)).isTypeMatch(eq(GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME), eq(Pool.class)); + verify(this.mockBeanFactory, times(2)).isTypeMatch(eq(GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME), eq(Pool.class)); verify(this.mockBeanFactory, times(1)).getBean(eq(GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME), eq(Pool.class)); - verify(mockPool, times(1)).getName(); + verify(mockPoolResolver, times(1)).resolve(eq(GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME)); verify(mockPool, times(1)).getQueryService(); - verifyZeroInteractions(mockQueryService); + verifyNoInteractions(mockQueryService); } } @@ -139,33 +141,44 @@ public class ContinuousQueryListenerContainerUnitTests { Executor mockExecutor = mock(Executor.class); - PoolManagerImpl poolManagerSpy = spy(PoolManagerImpl.getPMI()); + Pool mockPool = mock(Pool.class); + + PoolResolver mockPoolResolver = mock(PoolResolver.class); QueryService mockQueryService = mock(QueryService.class); - when(mockBeanFactory.containsBean(eq("TestPool"))).thenReturn(true); - when(mockBeanFactory.isTypeMatch(eq("TestPool"), eq(Pool.class))).thenReturn(true); + when(this.mockBeanFactory.containsBean(eq("TestPool"))).thenReturn(true); + when(this.mockBeanFactory.isTypeMatch(eq("TestPool"), eq(Pool.class))).thenReturn(true); + when(mockPoolResolver.resolve(eq("TestPool"))).thenReturn(mockPool); - cqListenerContainer.setAutoStartup(false); - cqListenerContainer.setBeanFactory(mockBeanFactory); - cqListenerContainer.setPoolName("TestPool"); - cqListenerContainer.setQueryService(mockQueryService); - cqListenerContainer.setTaskExecutor(mockExecutor); - cqListenerContainer.afterPropertiesSet(); + this.cqListenerContainer.setAutoStartup(false); + this.cqListenerContainer.setBeanFactory(this.mockBeanFactory); + this.cqListenerContainer.setPoolName("TestPool"); + this.cqListenerContainer.setPoolResolver(mockPoolResolver); + this.cqListenerContainer.setQueryService(mockQueryService); + this.cqListenerContainer.setTaskExecutor(mockExecutor); - assertThat(cqListenerContainer.isActive()).isTrue(); - assertThat(cqListenerContainer.isAutoStartup()).isFalse(); - assertThat(cqListenerContainer.isRunning()).isFalse(); - assertThat(cqListenerContainer.getBeanFactory()).isSameAs(mockBeanFactory); - assertThat(cqListenerContainer.getPoolName()).isEqualTo("TestPool"); - assertThat(cqListenerContainer.getQueryService()).isSameAs(mockQueryService); - assertThat(cqListenerContainer.getTaskExecutor()).isSameAs(mockExecutor); + try { + this.cqListenerContainer.afterPropertiesSet(); + } + finally { - verify(mockBeanFactory, times(1)).containsBean(eq("TestPool")); - verify(mockBeanFactory, times(1)).isTypeMatch(eq("TestPool"), eq(Pool.class)); - verify(mockBeanFactory, times(1)).getBean(eq("TestPool"), eq(Pool.class)); - verify(poolManagerSpy, never()).find(anyString()); - verifyZeroInteractions(mockQueryService); + assertThat(this.cqListenerContainer.isActive()).isTrue(); + assertThat(this.cqListenerContainer.isAutoStartup()).isFalse(); + assertThat(this.cqListenerContainer.isRunning()).isFalse(); + assertThat(this.cqListenerContainer.getBeanFactory()).isSameAs(this.mockBeanFactory); + assertThat(this.cqListenerContainer.getPoolName()).isEqualTo("TestPool"); + assertThat(this.cqListenerContainer.getPoolResolver()).isEqualTo(mockPoolResolver); + assertThat(this.cqListenerContainer.getQueryService()).isSameAs(mockQueryService); + assertThat(this.cqListenerContainer.getTaskExecutor()).isSameAs(mockExecutor); + + verify(this.mockBeanFactory, times(1)).containsBean(eq("TestPool")); + verify(this.mockBeanFactory, times(1)).isTypeMatch(eq("TestPool"), eq(Pool.class)); + verify(this.mockBeanFactory, times(1)).getBean(eq("TestPool"), eq(Pool.class)); + verify(mockPoolResolver, times(1)).resolve(eq("TestPool")); + verify(mockPool, times(1)).getQueryService(); + verifyNoInteractions(mockQueryService); + } } @Test(expected = IllegalStateException.class) @@ -198,63 +211,135 @@ public class ContinuousQueryListenerContainerUnitTests { } } + @Test + public void setAndGetPoolResolver() { + + PoolResolver mockPoolResolver = mock(PoolResolver.class); + + assertThat(this.cqListenerContainer.getPoolResolver()) + .isEqualTo(ContinuousQueryListenerContainer.DEFAULT_POOL_RESOLVER); + + this.cqListenerContainer.setPoolResolver(mockPoolResolver); + + assertThat(this.cqListenerContainer.getPoolResolver()).isEqualTo(mockPoolResolver); + + this.cqListenerContainer.setPoolResolver(null); + + assertThat(this.cqListenerContainer.getPoolResolver()) + .isEqualTo(ContinuousQueryListenerContainer.DEFAULT_POOL_RESOLVER); + + verifyNoInteractions(mockPoolResolver); + } + + @Test + public void resolvePoolCallsPoolResolverResolveReturnsNull() { + + PoolResolver mockPoolResolver = mock(PoolResolver.class); + + when(mockPoolResolver.resolve(anyString())).thenReturn(null); + + this.cqListenerContainer.setPoolResolver(mockPoolResolver); + + assertThat(this.cqListenerContainer.resolvePool("TestPool")).isNull(); + + verify(mockPoolResolver, times(1)).resolve(eq("TestPool")); + } + + @Test + public void resolvePoolCallsPoolResolverResolveReturnsPool() { + + Pool mockPool = mock(Pool.class); + + PoolResolver mockPoolResolver = mock(PoolResolver.class); + + when(mockPoolResolver.resolve(eq("TestPool"))).thenReturn(mockPool); + + this.cqListenerContainer.setPoolResolver(mockPoolResolver); + + assertThat(this.cqListenerContainer.resolvePool("TestPool")).isEqualTo(mockPool); + + verify(mockPoolResolver, times(1)).resolve(eq("TestPool")); + verifyNoInteractions(mockPool); + } + @Test public void resolvePoolNameReturnsConfiguredPoolName() { - cqListenerContainer.setPoolName("TestPool"); + this.cqListenerContainer.setPoolName("TestPool"); - assertThat(cqListenerContainer.resolvePoolName()).isEqualTo("TestPool"); + assertThat(this.cqListenerContainer.resolvePoolName()).isEqualTo("TestPool"); } @Test - public void resolvePoolNameReturnsGemFireDefaultPoolName() { + public void resolvePoolNameReturnsApacheGeodeDefaultPoolName() { - cqListenerContainer.setPoolName(null); + this.cqListenerContainer.setPoolName(null); - assertThat(cqListenerContainer.resolvePoolName()).isEqualTo(GemfireUtils.DEFAULT_POOL_NAME); + assertThat(this.cqListenerContainer.resolvePoolName()).isEqualTo(GemfireUtils.DEFAULT_POOL_NAME); } @Test - public void resolvePoolNameReturnsGemFireDefaultPoolNameWhenBeanFactoryDoesNotContainNamedPool() { + public void resolvePoolNameReturnsApacheGeodeDefaultPoolNameWhenBeanFactoryDoesNotContainNamedPool() { - when(mockBeanFactory.containsBean(anyString())).thenReturn(false); + when(this.mockBeanFactory.containsBean(anyString())).thenReturn(false); - cqListenerContainer.setBeanFactory(mockBeanFactory); - cqListenerContainer.setPoolName(""); + this.cqListenerContainer.setBeanFactory(this.mockBeanFactory); + this.cqListenerContainer.setPoolName(""); - assertThat(cqListenerContainer.resolvePoolName()).isEqualTo(GemfireUtils.DEFAULT_POOL_NAME); + assertThat(this.cqListenerContainer.resolvePoolName()).isEqualTo(GemfireUtils.DEFAULT_POOL_NAME); - verify(mockBeanFactory, times(1)) + verify(this.mockBeanFactory, times(1)) .containsBean(eq(GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME)); + verify(this.mockBeanFactory, never()).isTypeMatch(anyString(), any(Class.class)); + } + + @Test + public void resolvePoolNameReturnsApacheGeodeDefaultPoolNameWhenBeanFactoryContainsBeanWithNonMatchingPoolType() { + + when(this.mockBeanFactory.containsBean(anyString())).thenReturn(true); + when(this.mockBeanFactory.isTypeMatch(anyString(), eq(Pool.class))).thenReturn(false); + + this.cqListenerContainer.setBeanFactory(this.mockBeanFactory); + this.cqListenerContainer.setPoolName(""); + + assertThat(this.cqListenerContainer.resolvePoolName()).isEqualTo(GemfireUtils.DEFAULT_POOL_NAME); + + verify(this.mockBeanFactory, times(1)) + .containsBean(eq(GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME)); + verify(this.mockBeanFactory, times(1)) + .isTypeMatch(eq(GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME), any(Class.class)); } @Test public void resolvePoolNameReturnsSpringDataGemFireDefaultPoolName() { - when(mockBeanFactory.containsBean(eq(GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME))).thenReturn(true); + when(this.mockBeanFactory.containsBean(eq(GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME))).thenReturn(true); + when(this.mockBeanFactory.isTypeMatch(eq(GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME), eq(Pool.class))).thenReturn(true); - cqListenerContainer.setBeanFactory(mockBeanFactory); - cqListenerContainer.setPoolName(" "); + this.cqListenerContainer.setBeanFactory(this.mockBeanFactory); + this.cqListenerContainer.setPoolName(" "); - assertThat(cqListenerContainer.resolvePoolName()).isEqualTo(GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME); + assertThat(this.cqListenerContainer.resolvePoolName()).isEqualTo(GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME); - verify(mockBeanFactory, times(1)) + verify(this.mockBeanFactory, times(1)) .containsBean(eq(GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME)); + verify(this.mockBeanFactory, times(1)) + .isTypeMatch(eq(GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME), eq(Pool.class)); } @Test public void eagerlyInitializePoolWithGivenPoolName() { - when(mockBeanFactory.containsBean(eq("TestPool"))).thenReturn(true); - when(mockBeanFactory.isTypeMatch(eq("TestPool"), eq(Pool.class))).thenReturn(true); + when(this.mockBeanFactory.containsBean(eq("TestPool"))).thenReturn(true); + when(this.mockBeanFactory.isTypeMatch(eq("TestPool"), eq(Pool.class))).thenReturn(true); - cqListenerContainer.setBeanFactory(mockBeanFactory); + this.cqListenerContainer.setBeanFactory(this.mockBeanFactory); - assertThat(cqListenerContainer.eagerlyInitializePool("TestPool")).isEqualTo("TestPool"); + assertThat(this.cqListenerContainer.eagerlyInitializePool("TestPool")).isEqualTo("TestPool"); - verify(mockBeanFactory, times(1)).containsBean(eq("TestPool")); - verify(mockBeanFactory, times(1)).isTypeMatch(eq("TestPool"), eq(Pool.class)); - verify(mockBeanFactory, times(1)).getBean(eq("TestPool"), eq(Pool.class)); + verify(this.mockBeanFactory, times(1)).containsBean(eq("TestPool")); + verify(this.mockBeanFactory, times(1)).isTypeMatch(eq("TestPool"), eq(Pool.class)); + verify(this.mockBeanFactory, times(1)).getBean(eq("TestPool"), eq(Pool.class)); } @Test @@ -262,14 +347,15 @@ public class ContinuousQueryListenerContainerUnitTests { Pool mockPool = mock(Pool.class); + PoolResolver mockPoolResolver = mock(PoolResolver.class); + when(this.mockBeanFactory.containsBean(eq("TestPoolOne"))).thenReturn(false); - when(mockPool.getName()).thenReturn("TestPoolOne"); + when(mockPoolResolver.resolve(eq("TestPoolOne"))).thenReturn(mockPool); try { - PoolManagerImpl.getPMI().register(mockPool); - this.cqListenerContainer.setBeanFactory(this.mockBeanFactory); + this.cqListenerContainer.setPoolResolver(mockPoolResolver); assertThat(this.cqListenerContainer.eagerlyInitializePool("TestPoolOne")) .isEqualTo("TestPoolOne"); @@ -279,7 +365,8 @@ public class ContinuousQueryListenerContainerUnitTests { verify(this.mockBeanFactory, times(1)).containsBean(eq("TestPoolOne")); verify(this.mockBeanFactory, never()).isTypeMatch(anyString(), eq(Pool.class)); verify(this.mockBeanFactory, never()).getBean(anyString(), eq(Pool.class)); - verify(mockPool, atLeast(1)).getName(); + verify(mockPoolResolver, times(1)).resolve(eq("TestPoolOne")); + verifyNoInteractions(mockPool); } } @@ -288,18 +375,18 @@ public class ContinuousQueryListenerContainerUnitTests { Pool mockPool = mock(Pool.class); + PoolResolver mockPoolResolver = mock(PoolResolver.class); + when(this.mockBeanFactory.containsBean(eq("TestPoolTwo"))).thenReturn(true); when(this.mockBeanFactory.isTypeMatch(eq("TestPoolTwo"), eq(Pool.class))).thenReturn(true); when(this.mockBeanFactory.getBean(eq("TestPoolTwo"), eq(Pool.class))) .thenThrow(new NoSuchBeanDefinitionException("TEST")); - when(mockPool.getName()).thenReturn("TestPoolTwo"); + when(mockPoolResolver.resolve(eq("TestPoolTwo"))).thenReturn(mockPool); this.cqListenerContainer.setBeanFactory(this.mockBeanFactory); + this.cqListenerContainer.setPoolResolver(mockPoolResolver); try { - - PoolManagerImpl.getPMI().register(mockPool); - assertThat(this.cqListenerContainer.eagerlyInitializePool("TestPoolTwo")) .isEqualTo("TestPoolTwo"); } @@ -308,7 +395,8 @@ public class ContinuousQueryListenerContainerUnitTests { verify(this.mockBeanFactory, times(1)).containsBean(eq("TestPoolTwo")); verify(this.mockBeanFactory, times(1)).isTypeMatch(eq("TestPoolTwo"), eq(Pool.class)); verify(this.mockBeanFactory, times(1)).getBean(eq("TestPoolTwo"), eq(Pool.class)); - verify(mockPool, atLeast(1)).getName(); + verify(mockPoolResolver, times(1)).resolve(eq("TestPoolTwo")); + verifyNoInteractions(mockPool); } } @@ -345,7 +433,7 @@ public class ContinuousQueryListenerContainerUnitTests { assertThat(cqListenerContainer.initQueryService("TestPool")).isSameAs(mockQueryService); - verifyZeroInteractions(mockQueryService); + verifyNoInteractions(mockQueryService); } @Test @@ -358,23 +446,25 @@ public class ContinuousQueryListenerContainerUnitTests { Pool mockPool = mock(Pool.class); + PoolResolver mockPoolResolver = mock(PoolResolver.class); + QueryService mockQueryService = mock(QueryService.class); - when(mockPool.getName()).thenReturn("TestPoolFour"); + when(mockPoolResolver.resolve(eq("TestPoolFour"))).thenReturn(mockPool); when(mockPool.getQueryService()).thenReturn(mockQueryService); - try { + this.cqListenerContainer.setPoolResolver(mockPoolResolver); - PoolManagerImpl.getPMI().register(mockPool); + try { assertThat(this.cqListenerContainer.getQueryService()).isNull(); assertThat(this.cqListenerContainer.initQueryService("TestPoolFour")).isEqualTo(mockQueryService); } finally { - verify(mockPool, atLeast(1)).getName(); + verify(mockPoolResolver, times(1)).resolve(eq("TestPoolFour")); verify(mockPool, times(1)).getQueryService(); - verifyZeroInteractions(mockQueryService); + verifyNoInteractions(mockQueryService); } } @@ -383,28 +473,30 @@ public class ContinuousQueryListenerContainerUnitTests { Pool mockPool = mock(Pool.class); + PoolResolver mockPoolResolver = mock(PoolResolver.class); + QueryService mockQueryServiceOne = mock(QueryService.class); QueryService mockQueryServiceTwo = mock(QueryService.class); - when(mockPool.getName()).thenReturn("TestPoolFive"); + when(mockPoolResolver.resolve(eq("TestPoolFive"))).thenReturn(mockPool); when(mockPool.getQueryService()).thenReturn(mockQueryServiceOne); + this.cqListenerContainer.setPoolResolver(mockPoolResolver); + this.cqListenerContainer.setQueryService(mockQueryServiceTwo); + try { - PoolManagerImpl.getPMI().register(mockPool); - - this.cqListenerContainer.setQueryService(mockQueryServiceTwo); - + assertThat(this.cqListenerContainer.getPoolResolver()).isSameAs(mockPoolResolver); assertThat(this.cqListenerContainer.getQueryService()).isSameAs(mockQueryServiceTwo); assertThat(this.cqListenerContainer.initQueryService("TestPoolFive")) .isEqualTo(mockQueryServiceOne); } finally { - verify(mockPool, atLeast(1)).getName(); + verify(mockPoolResolver, times(1)).resolve(eq("TestPoolFive")); verify(mockPool, times(1)).getQueryService(); - verifyZeroInteractions(mockQueryServiceOne); - verifyZeroInteractions(mockQueryServiceTwo); + verifyNoInteractions(mockQueryServiceOne); + verifyNoInteractions(mockQueryServiceTwo); } } @@ -417,7 +509,7 @@ public class ContinuousQueryListenerContainerUnitTests { assertThat(cqListenerContainer.initExecutor()).isSameAs(mockExecutor); - verifyZeroInteractions(mockExecutor); + verifyNoInteractions(mockExecutor); } @Test @@ -454,7 +546,7 @@ public class ContinuousQueryListenerContainerUnitTests { assertThat(cqListenerContainer.initQueryService(null)).isEqualTo(mockQueryService); verify(mockRegionService, times(1)).getQueryService(); - verifyZeroInteractions(mockQueryService); + verifyNoInteractions(mockQueryService); } @Test diff --git a/spring-data-geode/src/test/java/org/springframework/data/gemfire/util/SpringUtilsUnitTests.java b/spring-data-geode/src/test/java/org/springframework/data/gemfire/util/SpringUtilsUnitTests.java index a7c2eea0..2fa06f84 100644 --- a/spring-data-geode/src/test/java/org/springframework/data/gemfire/util/SpringUtilsUnitTests.java +++ b/spring-data-geode/src/test/java/org/springframework/data/gemfire/util/SpringUtilsUnitTests.java @@ -17,6 +17,7 @@ package org.springframework.data.gemfire.util; 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; @@ -41,8 +42,11 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; +import org.apache.geode.cache.client.Pool; + import org.springframework.beans.MutablePropertyValues; import org.springframework.beans.PropertyValue; +import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.dao.InvalidDataAccessApiUsageException; @@ -65,6 +69,47 @@ public class SpringUtilsUnitTests { @Mock private BeanDefinition mockBeanDefinition; + @Test + public void isMatchingBeanReturnsTrue() { + + BeanFactory mockBeanFactory = mock(BeanFactory.class); + + when(mockBeanFactory.containsBean(anyString())).thenReturn(true); + when(mockBeanFactory.isTypeMatch(anyString(), any(Class.class))).thenReturn(true); + + assertThat(SpringUtils.isMatchingBean(mockBeanFactory, "TestPool", Pool.class)).isTrue(); + + verify(mockBeanFactory, times(1)).containsBean(eq("TestPool")); + verify(mockBeanFactory, times(1)).isTypeMatch(eq("TestPool"), eq(Pool.class)); + } + + @Test + public void isMatchingBeanReturnsFalseWhenBeanFactoryDoesNotContainBeanByName() { + + BeanFactory mockBeanFactory = mock(BeanFactory.class); + + when(mockBeanFactory.containsBean(anyString())).thenReturn(false); + + assertThat(SpringUtils.isMatchingBean(mockBeanFactory, "TestPool", Pool.class)).isFalse(); + + verify(mockBeanFactory, times(1)).containsBean(eq("TestPool")); + verify(mockBeanFactory, never()).isTypeMatch(anyString(), any(Class.class)); + } + + @Test + public void isMatchingBeanReturnsFalseWhenBeanIsNotATypeMatch() { + + BeanFactory mockBeanFactory = mock(BeanFactory.class); + + when(mockBeanFactory.containsBean(anyString())).thenReturn(true); + when(mockBeanFactory.isTypeMatch(anyString(), any(Class.class))).thenReturn(false); + + assertThat(SpringUtils.isMatchingBean(mockBeanFactory, "TestPool", Pool.class)).isFalse(); + + verify(mockBeanFactory, times(1)).containsBean(eq("TestPool")); + verify(mockBeanFactory, times(1)).isTypeMatch(eq("TestPool"), eq(Pool.class)); + } + @Test public void addDependsOnToExistingDependencies() {