DATAGEODE-325 - Add FactoryBean for CacheResolver.

This commit is contained in:
John Blum
2020-04-08 14:30:49 -07:00
parent 6045f86da1
commit 9e2abf781e
3 changed files with 1470 additions and 0 deletions

View File

@@ -0,0 +1,394 @@
/*
* Copyright 2020 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.support;
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalStateException;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import org.apache.geode.cache.Cache;
import org.apache.geode.cache.CacheFactory;
import org.apache.geode.cache.GemFireCache;
import org.apache.geode.cache.client.ClientCache;
import org.apache.geode.cache.client.ClientCacheFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.gemfire.CacheResolver;
import org.springframework.data.gemfire.client.support.ClientCacheFactoryCacheResolver;
import org.springframework.data.gemfire.util.CacheUtils;
import org.springframework.data.gemfire.util.CollectionUtils;
import org.springframework.data.gemfire.util.SpringUtils;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* Spring {@link FactoryBean} used to construct a custom, determined {@link CacheResolver} that strategically
* and lazily resolves a cache instance.
*
* @author John Blum
* @see org.apache.geode.cache.Cache
* @see org.apache.geode.cache.GemFireCache
* @see org.apache.geode.cache.client.ClientCache
* @see org.springframework.beans.factory.BeanFactory
* @see org.springframework.beans.factory.FactoryBean
* @see org.springframework.beans.factory.InitializingBean
* @see org.springframework.data.gemfire.CacheResolver
* @see org.springframework.data.gemfire.support.AbstractFactoryBeanSupport
* @since 2.3.0
*/
@SuppressWarnings({ "rawtypes", "unused" })
public class SmartCacheResolverFactoryBean extends AbstractFactoryBeanSupport<CacheResolver<GemFireCache>>
implements InitializingBean {
/**
* Factory method used to construct a new instance of the {@link SmartCacheResolverFactoryBean}.
*
* @return a new instance of {@link SmartCacheResolverFactoryBean}.
* @see org.springframework.data.gemfire.support.SmartCacheResolverFactoryBean
*/
public static @NonNull SmartCacheResolverFactoryBean create() {
return new SmartCacheResolverFactoryBean();
}
private CacheResolver<GemFireCache> cacheResolver;
private CompositionStrategy compositionStrategy = CompositionStrategy.DEFAULT;
private GemFireCache cache;
private List<CacheResolver> configuredCacheResolvers;
private String cacheBeanName;
/**
* Initializes the {@link CacheResolver} [composition] created by this {@link FactoryBean}.
*
* @see org.springframework.data.gemfire.support.SmartCacheResolverFactoryBean.CompositionStrategy#use(SmartCacheResolverFactoryBean)
* @see #getCompositionStrategy()
*/
@Override
public void afterPropertiesSet() {
this.cacheResolver = getCompositionStrategy().use(this);
Assert.state(this.cacheResolver != null,
() -> String.format("No CacheResolver was composed with CompositionStrategy [%s]",
getCompositionStrategy()));
}
/**
* Returns a reference to the constructed {@link CacheResolver} instance created by this {@link FactoryBean}.
*
* @return a reference to the constructed {@link CacheResolver} instance created by this {@link FactoryBean}.
* @see org.springframework.data.gemfire.CacheResolver
* @see org.apache.geode.cache.GemFireCache
*/
CacheResolver<GemFireCache> getCacheResolver() {
return this.cacheResolver;
}
/**
* Returns the fully constructed and initialized instance of the {@link CacheResolver}
* created by this {@link FactoryBean}.
*
* If the {@link #afterPropertiesSet()} method has not yet been called, then this method returns a {@literal Proxy}
* to the {@link CacheResolver} instance that will eventually be created by this {@link FactoryBean}.
*
* @return the {@link CacheResolver} instance constructed and initialized by this {@link FactoryBean}.
* @see org.springframework.beans.factory.FactoryBean#getObject()
* @see CacheResolverProxy
*/
@NonNull
public CacheResolver<GemFireCache> getObject() {
return new CacheResolverProxy();
}
/**
* Returns the {@link Class type} of the {@link CacheResolver} returned by this {@link FactoryBean}.
*
* @return the {@link Class type} of the {@link CacheResolver} returned by this {@link FactoryBean}.
* @see org.springframework.beans.factory.FactoryBean#getObjectType()
* @see java.lang.Class
*/
@Nullable @Override
public Class<?> getObjectType() {
CacheResolver<?> cacheResolver = getCacheResolver();
return cacheResolver != null ? cacheResolver.getClass() : CacheResolver.class;
}
/**
* Constructs a {@link CacheResolver} capable of resolving a cache instance from the Spring {@link BeanFactory}.
*
* Returns {@literal null} if the {@link BeanFactory} reference is {@literal null} (i.e. not configured).
*
* @return a {@link CacheResolver} capable of resolving a cache instance from the Spring {@link BeanFactory}.
* @see org.springframework.data.gemfire.support.BeanFactoryCacheResolver
* @see org.springframework.data.gemfire.CacheResolver
* @see #getBeanFactory()
*/
protected @Nullable CacheResolver newBeanFactoryCacheResolver() {
// Depending on the application context, there may or may not be a Spring ApplicationContext...
// Think Spring on the GemFire/Geode server-side with no Spring container
return Optional.ofNullable(getBeanFactory())
.map(BeanFactoryCacheResolver::new)
.map(cacheResolver -> {
getCacheBeanName().ifPresent(cacheResolver::setCacheBeanName);
return cacheResolver;
})
.orElse(null);
}
/**
* Constructs a {@link CacheResolver} capable of resolving a {@link ClientCache} instance using
* the Apache Geode {@link ClientCacheFactory} API.
*
* @return a {@link CacheResolver} resolving a {@link ClientCache} instance.
* @see org.springframework.data.gemfire.client.support.ClientCacheFactoryCacheResolver
* @see org.springframework.data.gemfire.CacheResolver
*/
protected @NonNull CacheResolver newClientCacheFactoryCacheResolver() {
return new ClientCacheFactoryCacheResolver();
}
/**
* Constructs a {@link CacheResolver} capable of resolving a {@literal peer} {@link Cache} instance using
* the Apache Geode {@link CacheFactory} API.
*
* @return a {@link CacheResolver} resolving a {@literal peer} {@link Cache} instance.
* @see org.springframework.data.gemfire.support.CacheFactoryCacheResolver
* @see org.springframework.data.gemfire.CacheResolver
*/
protected @NonNull CacheResolver newPeerCacheFactoryCacheResolver() {
return new CacheFactoryCacheResolver();
}
/**
* Constructs a {@link CacheResolver} capable of resolving a single, configured cache instance.
*
* Returns {@literal null} if a cache instance was not {@link #setCache(GemFireCache) configured}
* on this {@link FactoryBean}.
*
* @return a {@link CacheResolver} capable of resolving a single, configured cache instance.
* @see org.springframework.data.gemfire.support.SingleCacheCacheResolver
* @see org.springframework.data.gemfire.CacheResolver
* @see #getCache()
*/
protected @Nullable CacheResolver newSingleCacheCacheResolver() {
return getCache()
.map(this::newSingleCacheCacheResolver)
.orElse(null);
}
private @NonNull CacheResolver newSingleCacheCacheResolver(@NonNull GemFireCache cache) {
return CacheUtils.isClient(cache)
? SingleCacheCacheResolver.from((ClientCache) cache)
: SingleCacheCacheResolver.from((Cache) cache);
}
public final void setCache(@Nullable GemFireCache cache) {
this.cache = cache;
}
protected Optional<GemFireCache> getCache() {
return Optional.ofNullable(this.cache);
}
public final void setCacheBeanName(@Nullable String cacheBeanName) {
this.cacheBeanName = cacheBeanName;
}
protected Optional<String> getCacheBeanName() {
return Optional.ofNullable(this.cacheBeanName)
.filter(StringUtils::hasText);
}
public final void setCompositionStrategy(CompositionStrategy compositionStrategy) {
this.compositionStrategy = compositionStrategy;
}
protected CompositionStrategy getCompositionStrategy() {
return this.compositionStrategy != null ? this.compositionStrategy : CompositionStrategy.DEFAULT;
}
@Autowired(required = false)
public final void setConfiguredCacheResolvers(List<CacheResolver> cacheResolvers) {
// NOTE: Be careful not to add the CacheResolverProxy from this SmartCacheResolverFactoryBean
this.configuredCacheResolvers = CollectionUtils.nullSafeList(cacheResolvers).stream()
.filter(Objects::nonNull)
.filter(this::isNotCacheResolverProxyForThisFactoryBean)
.collect(Collectors.toList());
}
protected List<CacheResolver> getConfiguredCacheResolvers() {
return this.configuredCacheResolvers;
}
private boolean isCacheResolverProxyForThisFactoryBean(CacheResolver<?> cacheResolver) {
return cacheResolver instanceof CacheResolverProxy
&& ((CacheResolverProxy) cacheResolver).getCacheResolverFactoryBean().equals(this);
}
private boolean isNotCacheResolverProxyForThisFactoryBean(CacheResolver<?> cacheResolver) {
return !isCacheResolverProxyForThisFactoryBean(cacheResolver);
}
private List<CacheResolver> resolveCacheResolvers() {
BeanFactory beanFactory = getBeanFactory();
Assert.state(beanFactory != null,
() -> String.format("A Spring context is not present and is required to use [%1$s.%2$s.%3$s]",
CompositionStrategy.class.getEnclosingClass().getSimpleName(),
CompositionStrategy.class.getSimpleName(), CompositionStrategy.USER_DEFINED.name()));
List<CacheResolver> orderedCacheResolvers =
SpringUtils.getOrderedStreamOfBeansByType(beanFactory, CacheResolver.class)
.collect(Collectors.toList());
setConfiguredCacheResolvers(orderedCacheResolvers);
return orderedCacheResolvers;
}
public SmartCacheResolverFactoryBean withCache(GemFireCache cache) {
setCache(cache);
return this;
}
public SmartCacheResolverFactoryBean withCacheBeanName(String cacheBeanName) {
setCacheBeanName(cacheBeanName);
return this;
}
public SmartCacheResolverFactoryBean usingCompositionStrategy(CompositionStrategy compositionStrategy) {
setCompositionStrategy(compositionStrategy);
return this;
}
class CacheResolverProxy implements CacheResolver<GemFireCache> {
Optional<CacheResolver<GemFireCache>> getCacheResolver() {
return Optional.ofNullable(getCacheResolverFactoryBean().getCacheResolver());
}
SmartCacheResolverFactoryBean getCacheResolverFactoryBean() {
return SmartCacheResolverFactoryBean.this;
}
@Override
public GemFireCache resolve() {
return getCacheResolver()
.map(CacheResolver::resolve)
.orElseThrow(() -> newIllegalStateException("CacheResolver was not initialized"));
}
}
/**
* Specifies the declaration of the algorithm to use to compose {@link CacheResolver CacheResolvers}
* into a composition functioning as a single, complete and cohesive cache resolution strategy.
*/
enum CompositionStrategy {
DEFAULT {
@Override @SuppressWarnings("unchecked")
<T extends GemFireCache> CacheResolver<T> use(SmartCacheResolverFactoryBean factoryBean) {
return ComposableCacheResolver.compose(
factoryBean.newSingleCacheCacheResolver(),
factoryBean.newBeanFactoryCacheResolver(),
factoryBean.newClientCacheFactoryCacheResolver(),
factoryBean.newPeerCacheFactoryCacheResolver());
}
},
GEODE {
@Override @SuppressWarnings("unchecked")
<T extends GemFireCache> CacheResolver<T> use(SmartCacheResolverFactoryBean factoryBean) {
return ComposableCacheResolver.compose(
factoryBean.newSingleCacheCacheResolver(),
factoryBean.newClientCacheFactoryCacheResolver(),
factoryBean.newPeerCacheFactoryCacheResolver()
);
}
},
SPRING {
@Override @SuppressWarnings("unchecked")
<T extends GemFireCache> CacheResolver<T> use(SmartCacheResolverFactoryBean factoryBean) {
return ComposableCacheResolver.compose(
factoryBean.newSingleCacheCacheResolver(),
factoryBean.newBeanFactoryCacheResolver()
);
}
},
USER_DEFINED {
@Override @SuppressWarnings("unchecked")
<T extends GemFireCache> CacheResolver<T> use(SmartCacheResolverFactoryBean factoryBean) {
List<CacheResolver> cacheResolvers = computeIfAbsent(factoryBean);
Assert.state(isNotEmpty(cacheResolvers), "No CacheResolver beans were defined");
CacheResolver<T> current = null;
for (CacheResolver<T> cacheResolver : cacheResolvers) {
current = ComposableCacheResolver.compose(current, cacheResolver);
}
return current;
}
private synchronized List<CacheResolver> computeIfAbsent(SmartCacheResolverFactoryBean factoryBean) {
return Optional.ofNullable(factoryBean.getConfiguredCacheResolvers())
.filter(this::isNotEmpty)
.orElseGet(factoryBean::resolveCacheResolvers);
}
private boolean isNotEmpty(List<?> list) {
return !(list == null || list.isEmpty());
}
};
abstract <T extends GemFireCache> CacheResolver<T> use(SmartCacheResolverFactoryBean factoryBean);
}
}

View File

@@ -0,0 +1,245 @@
/*
* Copyright 2020 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.support;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.when;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InOrder;
import org.apache.geode.cache.CacheClosedException;
import org.apache.geode.cache.GemFireCache;
import org.apache.geode.cache.client.ClientCache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.data.gemfire.CacheResolver;
import org.springframework.data.gemfire.support.SmartCacheResolverFactoryBean.CacheResolverProxy;
import org.springframework.data.gemfire.support.SmartCacheResolverFactoryBean.CompositionStrategy;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
/**
* Integration Tests for {@link SmartCacheResolverFactoryBean}.
*
* @author John Blum
* @see org.junit.Test
* @see org.mockito.Mockito
* @see org.apache.geode.cache.client.ClientCache
* @see org.springframework.context.ApplicationContext
* @see org.springframework.context.annotation.Bean
* @see org.springframework.context.annotation.Configuration
* @see org.springframework.core.annotation.Order
* @see org.springframework.data.gemfire.CacheResolver
* @see org.springframework.data.gemfire.support.SmartCacheResolverFactoryBean
* @see org.springframework.test.context.ContextConfiguration
* @see org.springframework.test.context.junit4.SpringRunner
* @since 2.3.0
*/
@RunWith(SpringRunner.class)
@ContextConfiguration
@SuppressWarnings({ "rawtypes", "unused" })
public class SmartCacheResolverFactoryBeanIntegrationTests {
@Autowired
private ApplicationContext applicationContext;
@Autowired
// Primary (SUT)
private CacheResolver cacheResolver;
@Autowired
@Qualifier("A")
private CacheResolver a;
@Autowired
@Qualifier("B")
private CacheResolver b;
@Autowired
@Qualifier("C")
private CacheResolver c;
@Autowired
@Qualifier("D")
private CacheResolver d;
@Autowired
@Qualifier("U")
private CacheResolver u;
@Autowired
@Qualifier("X")
private CacheResolver x;
@Autowired
@Qualifier("Y")
private CacheResolver y;
@Autowired
@Qualifier("Z")
private CacheResolver z;
@Autowired
private CacheResolver[] cacheResolvers;
@Autowired
private ClientCache clientCache;
@Test
public void cacheResolversAreInjectedInOrder() {
assertThat(this.cacheResolvers).containsExactly(this.y, this.x, this.z, this.b, this.c, this.a, this.d,
this.cacheResolver, this.u);
}
@Test
public void resolvesCache() {
assertThat(this.cacheResolver).isInstanceOf(CacheResolverProxy.class);
assertThat(((CacheResolverProxy) this.cacheResolver).getCacheResolver().orElse(null))
.isInstanceOf(ComposableCacheResolver.class);
assertThat(this.cacheResolver.resolve()).isEqualTo(this.clientCache);
InOrder inOrder = inOrder(this.a, this.b, this.c, this.d, this.u, this.x, this.y, this.z);
inOrder.verify(this.y, times(1)).resolve();
inOrder.verify(this.x, times(1)).resolve();
inOrder.verify(this.z, times(1)).resolve();
inOrder.verify(this.b, atLeastOnce()).resolve();
inOrder.verify(this.c, times(1)).resolve();
inOrder.verify(this.a, times(1)).resolve();
inOrder.verify(this.d, never()).resolve();
inOrder.verify(this.u, never()).resolve();
}
@Configuration
static class TestConfiguration {
@Bean
ClientCache mockClientCache() {
return mock(ClientCache.class);
}
@Primary
@Bean("SmartCacheResolver")
SmartCacheResolverFactoryBean smartCacheResolver() {
return SmartCacheResolverFactoryBean.create()
.usingCompositionStrategy(CompositionStrategy.USER_DEFINED);
}
@Bean("A")
@Order(3)
CacheResolver a(ClientCache clientCache) {
CacheResolver mockCacheResolver = mock(CacheResolver.class, "A");
when(mockCacheResolver.resolve()).thenReturn(clientCache);
return mockCacheResolver;
}
@Bean("B")
@Order(1)
CacheResolver b() {
CacheResolver mockCacheResolver = mock(CacheResolver.class, "B");
when(mockCacheResolver.resolve()).thenThrow(new CacheClosedException("TEST"));
return mockCacheResolver;
}
@Bean("C")
@Order(2)
CacheResolver c() {
return mock(CacheResolver.class, "C");
}
@Bean("D")
@Order(4)
CacheResolver d() {
return mock(CacheResolver.class, "D");
}
@Bean("U")
CacheResolver unorderedCacheResolver() {
return mock(CacheResolver.class, "U");
}
@Bean("X")
CacheResolver x() {
return spy(new AtOrderCacheResolver());
}
@Bean("Y")
CacheResolver y() {
return spy(new OrderedCacheResolver());
}
@Bean("Z")
CacheResolver z() {
return spy(new Z());
}
}
@Order(-1)
static class AtOrderCacheResolver implements CacheResolver<GemFireCache> {
@Override
public GemFireCache resolve() {
return null;
}
}
static class OrderedCacheResolver implements CacheResolver<GemFireCache>, Ordered {
@Override
public int getOrder() {
return -2;
}
@Override
public GemFireCache resolve() {
return null;
}
}
@Order(0)
static abstract class ZeroOrderedCacheResolver implements CacheResolver<GemFireCache> {
@Override
public GemFireCache resolve() {
return null;
}
}
static class Z extends ZeroOrderedCacheResolver { }
}

View File

@@ -0,0 +1,831 @@
/*
* Copyright 2020 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.support;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
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.verifyNoInteractions;
import static org.mockito.Mockito.when;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
import org.junit.Test;
import org.mockito.ArgumentMatchers;
import org.mockito.InOrder;
import org.apache.geode.cache.Cache;
import org.apache.geode.cache.CacheClosedException;
import org.apache.geode.cache.GemFireCache;
import org.apache.geode.cache.client.ClientCache;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.annotation.Order;
import org.springframework.data.gemfire.CacheResolver;
import org.springframework.data.gemfire.client.support.ClientCacheFactoryCacheResolver;
import org.springframework.data.gemfire.support.SmartCacheResolverFactoryBean.CacheResolverProxy;
import org.springframework.data.gemfire.support.SmartCacheResolverFactoryBean.CompositionStrategy;
/**
* Unit Tests for {@link SmartCacheResolverFactoryBean}.
*
* @author John Blum
* @see org.junit.Test
* @see org.mockito.Mockito
* @see org.apache.geode.cache.Cache
* @see org.apache.geode.cache.GemFireCache
* @see org.apache.geode.cache.client.ClientCache
* @see org.springframework.data.gemfire.CacheResolver
* @see org.springframework.data.gemfire.support.SmartCacheResolverFactoryBean
* @since 2.3.0
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public class SmartCacheResolverFactoryBeanUnitTests {
private CacheResolver<GemFireCache> resolveCacheResolverFromProxy(CacheResolver<GemFireCache> cacheResolver) {
return cacheResolver instanceof CacheResolverProxy
? ((CacheResolverProxy) cacheResolver).getCacheResolver().orElse(null)
: null;
}
@Test
public void factoryBeanUsingDefaultCompositionStrategyIsFullyLoaded() {
BeanFactory mockBeanFactory = mock(BeanFactory.class);
ClientCache mockClientCache = mock(ClientCache.class);
SmartCacheResolverFactoryBean factoryBean = new SmartCacheResolverFactoryBean();
factoryBean.setBeanFactory(mockBeanFactory);
factoryBean.setCache(mockClientCache);
factoryBean.setCacheBeanName("TestCacheBeanName");
assertThat(factoryBean.getBeanFactory()).isEqualTo(mockBeanFactory);
assertThat(factoryBean.getCache().orElse(null)).isEqualTo(mockClientCache);
assertThat(factoryBean.getCacheBeanName().orElse(null)).isEqualTo("TestCacheBeanName");
assertThat(factoryBean.getCompositionStrategy()).isEqualTo(CompositionStrategy.DEFAULT);
factoryBean.afterPropertiesSet();
CacheResolver<?> cacheResolver = resolveCacheResolverFromProxy(factoryBean.getObject());
assertThat(cacheResolver).isNotNull();
assertThat(cacheResolver).isInstanceOf(ComposableCacheResolver.class);
ComposableCacheResolver<?> composed = (ComposableCacheResolver<?>) cacheResolver;
CacheResolver<?> one = composed.getCacheResolverOne();
CacheResolver<?> two = composed.getCacheResolverTwo();
assertThat(one).isInstanceOf(ComposableCacheResolver.class);
assertThat(two).isInstanceOf(CacheFactoryCacheResolver.class);
two = ((ComposableCacheResolver<?>) one).getCacheResolverTwo();
one = ((ComposableCacheResolver<?>) one).getCacheResolverOne();
assertThat(one).isInstanceOf(ComposableCacheResolver.class);
assertThat(two).isInstanceOf(ClientCacheFactoryCacheResolver.class);
two = ((ComposableCacheResolver<?>) one).getCacheResolverTwo();
one = ((ComposableCacheResolver<?>) one).getCacheResolverOne();
assertThat(one.getClass().getName()).startsWith(SingleCacheCacheResolver.class.getName());
assertThat(one.resolve()).isEqualTo(mockClientCache);
assertThat(two).isInstanceOf(BeanFactoryCacheResolver.class);
assertThat(((BeanFactoryCacheResolver) two).getBeanFactory()).isEqualTo(mockBeanFactory);
assertThat(((BeanFactoryCacheResolver) two).getCacheBeanName().orElse(null)).isEqualTo("TestCacheBeanName");
}
@Test
public void factoryBeanUsingDefaultCompositionStrategyIsConditionallyComposed() {
SmartCacheResolverFactoryBean factoryBean = new SmartCacheResolverFactoryBean();
assertThat(factoryBean.getBeanFactory()).isNull();
assertThat(factoryBean.getCache().orElse(null)).isNull();
assertThat(factoryBean.getCacheBeanName().orElse(null)).isNull();
factoryBean.afterPropertiesSet();
CacheResolver<?> cacheResolver = resolveCacheResolverFromProxy(factoryBean.getObject());
assertThat(cacheResolver).isNotNull();
assertThat(cacheResolver).isInstanceOf(ComposableCacheResolver.class);
assertThat(((ComposableCacheResolver) cacheResolver).getCacheResolverOne())
.isInstanceOf(ClientCacheFactoryCacheResolver.class);
assertThat(((ComposableCacheResolver) cacheResolver).getCacheResolverTwo())
.isInstanceOf(CacheFactoryCacheResolver.class);
}
@Test
public void factoryBeanUsingDefaultCompositionStrategyResolvesCacheInOrder() {
BeanFactory mockBeanFactory = mock(BeanFactory.class);
Cache mockPeerCache = mock(Cache.class);
CacheResolver mockBeanFactoryCacheResolver = mock(CacheResolver.class);
CacheResolver mockClientCacheFactoryCacheResolver = mock(CacheResolver.class);
CacheResolver mockPeerCacheFactoryCacheResolver = mock(CacheResolver.class);
CacheResolver mockSingleCacheCacheResolver = mock(CacheResolver.class);
SmartCacheResolverFactoryBean factoryBean = spy(new SmartCacheResolverFactoryBean());
doReturn(mockBeanFactoryCacheResolver).when(factoryBean).newBeanFactoryCacheResolver();
doReturn(mockClientCacheFactoryCacheResolver).when(factoryBean).newClientCacheFactoryCacheResolver();
doReturn(mockPeerCacheFactoryCacheResolver).when(factoryBean).newPeerCacheFactoryCacheResolver();
doReturn(mockSingleCacheCacheResolver).when(factoryBean).newSingleCacheCacheResolver();
doThrow(new NoSuchBeanDefinitionException("TEST")).when(mockBeanFactoryCacheResolver).resolve();
doReturn(mockPeerCache).when(mockPeerCacheFactoryCacheResolver).resolve();
factoryBean.setBeanFactory(mockBeanFactory);
factoryBean.setCache(mockPeerCache);
factoryBean.setCacheBeanName("TestCacheBeanName");
assertThat(factoryBean.getBeanFactory()).isEqualTo(mockBeanFactory);
assertThat(factoryBean.getCache().orElse(null)).isEqualTo(mockPeerCache);
assertThat(factoryBean.getCacheBeanName().orElse(null)).isEqualTo("TestCacheBeanName");
assertThat(factoryBean.getCompositionStrategy()).isEqualTo(CompositionStrategy.DEFAULT);
factoryBean.afterPropertiesSet();
CacheResolver<?> cacheResolver = resolveCacheResolverFromProxy(factoryBean.getObject());
assertThat(cacheResolver).isNotNull();
assertThat(cacheResolver.resolve()).isEqualTo(mockPeerCache);
InOrder inOrder = inOrder(mockBeanFactoryCacheResolver, mockClientCacheFactoryCacheResolver,
mockPeerCacheFactoryCacheResolver, mockSingleCacheCacheResolver);
inOrder.verify(mockSingleCacheCacheResolver, times(1)).resolve();
inOrder.verify(mockBeanFactoryCacheResolver, atLeastOnce()).resolve();
inOrder.verify(mockClientCacheFactoryCacheResolver, times(1)).resolve();
inOrder.verify(mockPeerCacheFactoryCacheResolver, times(1)).resolve();
}
@Test
public void factoryBeanUsingGeodeCompositionStrategyIsFullyLoaded() {
BeanFactory mockBeanFactory = mock(BeanFactory.class);
ClientCache mockClientCache = mock(ClientCache.class);
SmartCacheResolverFactoryBean factoryBean = new SmartCacheResolverFactoryBean();
factoryBean.setBeanFactory(mockBeanFactory);
factoryBean.setCache(mockClientCache);
factoryBean.setCompositionStrategy(CompositionStrategy.GEODE);
assertThat(factoryBean.getBeanFactory()).isEqualTo(mockBeanFactory);
assertThat(factoryBean.getCache().orElse(null)).isEqualTo(mockClientCache);
assertThat(factoryBean.getCompositionStrategy()).isEqualTo(CompositionStrategy.GEODE);
factoryBean.afterPropertiesSet();
CacheResolver<?> cacheResolver = resolveCacheResolverFromProxy(factoryBean.getObject());
assertThat(cacheResolver).isNotNull();
assertThat(cacheResolver).isInstanceOf(ComposableCacheResolver.class);
CacheResolver<?> one = ((ComposableCacheResolver) cacheResolver).getCacheResolverOne();
CacheResolver<?> two = ((ComposableCacheResolver) cacheResolver).getCacheResolverTwo();
assertThat(one).isInstanceOf(ComposableCacheResolver.class);
assertThat(two).isInstanceOf(CacheFactoryCacheResolver.class);
two = ((ComposableCacheResolver) one).getCacheResolverTwo();
one = ((ComposableCacheResolver) one).getCacheResolverOne();
assertThat(one.getClass().getName()).startsWith(SingleCacheCacheResolver.class.getName());
assertThat(two).isInstanceOf(ClientCacheFactoryCacheResolver.class);
}
@Test
public void factoryBeanUsingGeodeCompositionStrategyIsConditionallyComposed() {
SmartCacheResolverFactoryBean factoryBean = new SmartCacheResolverFactoryBean();
factoryBean.setCompositionStrategy(CompositionStrategy.GEODE);
assertThat(factoryBean.getCache().orElse(null)).isNull();
assertThat(factoryBean.getCompositionStrategy()).isEqualTo(CompositionStrategy.GEODE);
factoryBean.afterPropertiesSet();
CacheResolver<?> cacheResolver = resolveCacheResolverFromProxy(factoryBean.getObject());
assertThat(cacheResolver).isNotNull();
assertThat(cacheResolver).isInstanceOf(ComposableCacheResolver.class);
CacheResolver<?> one = ((ComposableCacheResolver) cacheResolver).getCacheResolverOne();
CacheResolver<?> two = ((ComposableCacheResolver) cacheResolver).getCacheResolverTwo();
assertThat(one).isInstanceOf(ClientCacheFactoryCacheResolver.class);
assertThat(two).isInstanceOf(CacheFactoryCacheResolver.class);
}
@Test
public void factoryBeanUsingGeodeCompositionStrategyResolvesCacheInOrder() {
Cache mockPeerCache = mock(Cache.class);
CacheResolver mockClientCacheFactoryCacheResolver = mock(CacheResolver.class);
CacheResolver mockPeerCacheFactoryCacheResolver = mock(CacheResolver.class);
CacheResolver mockSingleCacheCacheResolver = mock(CacheResolver.class);
SmartCacheResolverFactoryBean factoryBean = spy(new SmartCacheResolverFactoryBean());
doReturn(mockClientCacheFactoryCacheResolver).when(factoryBean).newClientCacheFactoryCacheResolver();
doReturn(mockPeerCacheFactoryCacheResolver).when(factoryBean).newPeerCacheFactoryCacheResolver();
doReturn(mockSingleCacheCacheResolver).when(factoryBean).newSingleCacheCacheResolver();
doThrow(new CacheClosedException("TEST")).when(mockClientCacheFactoryCacheResolver).resolve();
doReturn(mockPeerCache).when(mockPeerCacheFactoryCacheResolver).resolve();
factoryBean.setCache(mockPeerCache);
factoryBean.setCompositionStrategy(CompositionStrategy.GEODE);
assertThat(factoryBean.getCache().orElse(null)).isEqualTo(mockPeerCache);
assertThat(factoryBean.getCompositionStrategy()).isEqualTo(CompositionStrategy.GEODE);
factoryBean.afterPropertiesSet();
CacheResolver<?> cacheResolver = resolveCacheResolverFromProxy(factoryBean.getObject());
assertThat(cacheResolver.resolve()).isEqualTo(mockPeerCache);
InOrder inOrder = inOrder(mockClientCacheFactoryCacheResolver,
mockPeerCacheFactoryCacheResolver, mockSingleCacheCacheResolver);
inOrder.verify(mockSingleCacheCacheResolver, times(1)).resolve();
inOrder.verify(mockClientCacheFactoryCacheResolver, atLeastOnce()).resolve();
inOrder.verify(mockPeerCacheFactoryCacheResolver, times(1)).resolve();
}
@Test
public void factoryBeanUsingSpringCompositionStrategyIsFullyLoaded() {
BeanFactory mockBeanFactory = mock(BeanFactory.class);
ClientCache mockClientCache = mock(ClientCache.class);
SmartCacheResolverFactoryBean factoryBean = new SmartCacheResolverFactoryBean();
factoryBean.setBeanFactory(mockBeanFactory);
factoryBean.setCache(mockClientCache);
factoryBean.setCacheBeanName("TestCacheBeanName");
factoryBean.setCompositionStrategy(CompositionStrategy.SPRING);
assertThat(factoryBean.getBeanFactory()).isEqualTo(mockBeanFactory);
assertThat(factoryBean.getCache().orElse(null)).isEqualTo(mockClientCache);
assertThat(factoryBean.getCacheBeanName().orElse(null)).isEqualTo("TestCacheBeanName");
assertThat(factoryBean.getCompositionStrategy()).isEqualTo(CompositionStrategy.SPRING);
factoryBean.afterPropertiesSet();
CacheResolver<?> cacheResolver = resolveCacheResolverFromProxy(factoryBean.getObject());
assertThat(cacheResolver).isNotNull();
assertThat(cacheResolver).isInstanceOf(ComposableCacheResolver.class);
CacheResolver<?> one = ((ComposableCacheResolver) cacheResolver).getCacheResolverOne();
CacheResolver<?> two = ((ComposableCacheResolver) cacheResolver).getCacheResolverTwo();
assertThat(one.getClass().getName()).startsWith(SingleCacheCacheResolver.class.getName());
assertThat(two).isInstanceOf(BeanFactoryCacheResolver.class);
assertThat(((BeanFactoryCacheResolver) two).getCacheBeanName().orElse(null))
.isEqualTo("TestCacheBeanName");
}
@Test
public void factoryBeanUsingSpringCompositionStrategyIsConditionallyComposedWithBeanFactoryCacheLoader() {
BeanFactory mockBeanFactory = mock(BeanFactory.class);
SmartCacheResolverFactoryBean factoryBean = new SmartCacheResolverFactoryBean();
factoryBean.setBeanFactory(mockBeanFactory);
factoryBean.setCompositionStrategy(CompositionStrategy.SPRING);
assertThat(factoryBean.getBeanFactory()).isEqualTo(mockBeanFactory);
assertThat(factoryBean.getCache().orElse(null)).isNull();
assertThat(factoryBean.getCacheBeanName().orElse(null)).isNull();
assertThat(factoryBean.getCompositionStrategy()).isEqualTo(CompositionStrategy.SPRING);
factoryBean.afterPropertiesSet();
CacheResolver<?> cacheResolver = resolveCacheResolverFromProxy(factoryBean.getObject());
assertThat(cacheResolver).isInstanceOf(BeanFactoryCacheResolver.class);
assertThat(((BeanFactoryCacheResolver) cacheResolver).getCacheBeanName().orElse(null)).isNull();
}
@Test
public void factoryBeanUsingSpringCompositionStrategyIsConditionallyComposedWithSingleCacheCacheLoader() {
ClientCache mockClientCache = mock(ClientCache.class);
SmartCacheResolverFactoryBean factoryBean = new SmartCacheResolverFactoryBean();
factoryBean.setCache(mockClientCache);
factoryBean.setCacheBeanName("TestCacheBeanName");
factoryBean.setCompositionStrategy(CompositionStrategy.SPRING);
assertThat(factoryBean.getBeanFactory()).isNull();
assertThat(factoryBean.getCache().orElse(null)).isEqualTo(mockClientCache);
assertThat(factoryBean.getCacheBeanName().orElse(null)).isEqualTo("TestCacheBeanName");
assertThat(factoryBean.getCompositionStrategy()).isEqualTo(CompositionStrategy.SPRING);
factoryBean.afterPropertiesSet();
CacheResolver<?> cacheResolver = resolveCacheResolverFromProxy(factoryBean.getObject());
assertThat(cacheResolver).isNotNull();
assertThat(cacheResolver.getClass().getName()).startsWith(SingleCacheCacheResolver.class.getName());
}
@Test(expected = IllegalStateException.class)
public void factoryBeanUsingSpringCompositionStrategyComposesNoCacheResolverThrowsIllegalStateException() {
SmartCacheResolverFactoryBean factoryBean = new SmartCacheResolverFactoryBean();
factoryBean.setCacheBeanName("TestCacheBeanName");
factoryBean.setCompositionStrategy(CompositionStrategy.SPRING);
assertThat(factoryBean.getBeanFactory()).isNull();
assertThat(factoryBean.getCache().orElse(null)).isNull();
assertThat(factoryBean.getCacheBeanName().orElse(null)).isEqualTo("TestCacheBeanName");
assertThat(factoryBean.getCompositionStrategy()).isEqualTo(CompositionStrategy.SPRING);
try {
factoryBean.afterPropertiesSet();
}
catch (IllegalStateException expected) {
assertThat(expected).hasMessage("No CacheResolver was composed with CompositionStrategy [%s]",
CompositionStrategy.SPRING);
assertThat(expected).hasNoCause();
throw expected;
}
finally {
assertThat(resolveCacheResolverFromProxy(factoryBean.getObject())).isNull();
}
}
@Test
public void factoryBeanUsingSpringCompositionStrategyResolvesCacheInOrder() {
Cache mockCache = mock(Cache.class);
CacheResolver mockBeanFactoryCacheResolver = mock(CacheResolver.class);
CacheResolver mockSingleCacheCacheResolver = mock(CacheResolver.class);
doReturn(mockCache).when(mockBeanFactoryCacheResolver).resolve();
SmartCacheResolverFactoryBean factoryBean = spy(new SmartCacheResolverFactoryBean());
doReturn(mockBeanFactoryCacheResolver).when(factoryBean).newBeanFactoryCacheResolver();
doReturn(mockSingleCacheCacheResolver).when(factoryBean).newSingleCacheCacheResolver();
factoryBean.setCompositionStrategy(CompositionStrategy.SPRING);
assertThat(factoryBean.getCompositionStrategy()).isEqualTo(CompositionStrategy.SPRING);
factoryBean.afterPropertiesSet();
CacheResolver<?> cacheResolver = resolveCacheResolverFromProxy(factoryBean.getObject());
assertThat(cacheResolver).isInstanceOf(ComposableCacheResolver.class);
assertThat(cacheResolver.resolve()).isEqualTo(mockCache);
InOrder inOrder = inOrder(mockBeanFactoryCacheResolver, mockSingleCacheCacheResolver);
inOrder.verify(mockSingleCacheCacheResolver, times(1)).resolve();
inOrder.verify(mockBeanFactoryCacheResolver, times(1)).resolve();
}
@Test
public void factoryBeanUsingUserDefinedCompositionStrategy() {
// Questionable?? Simulate Spring container behavior (i.e. BeanFactory.getBeanProvider(..).orderedStream())
// by returning an ordered (sorted) Stream based on @Order annotation/Ordered interface.
Stream<CacheResolver<? extends GemFireCache>> cacheResolverStream = Stream.of(spy(new A()), spy(new B()))
.sorted(AnnotationAwareOrderComparator.INSTANCE);
ObjectProvider<CacheResolver<? extends GemFireCache>> mockObjectProvider = mock(ObjectProvider.class);
BeanFactory mockBeanFactory = mock(BeanFactory.class);
when(mockObjectProvider.orderedStream()).thenReturn(cacheResolverStream);
when(mockBeanFactory.getBeanProvider(ArgumentMatchers.<Class>any())).thenReturn(mockObjectProvider);
SmartCacheResolverFactoryBean factoryBean = new SmartCacheResolverFactoryBean();
factoryBean.setBeanFactory(mockBeanFactory);
factoryBean.setCompositionStrategy(CompositionStrategy.USER_DEFINED);
assertThat(factoryBean.getBeanFactory()).isEqualTo(mockBeanFactory);
assertThat(factoryBean.getCompositionStrategy()).isEqualTo(CompositionStrategy.USER_DEFINED);
factoryBean.afterPropertiesSet();
CacheResolver<?> cacheResolver = resolveCacheResolverFromProxy(factoryBean.getObject());
assertThat(cacheResolver).isNotNull();
assertThat(cacheResolver).isInstanceOf(ComposableCacheResolver.class);
CacheResolver<?> one = ((ComposableCacheResolver) cacheResolver).getCacheResolverOne();
CacheResolver<?> two = ((ComposableCacheResolver) cacheResolver).getCacheResolverTwo();
assertThat(one).isInstanceOf(B.class);
assertThat(two).isInstanceOf(A.class);
assertThat(cacheResolver.resolve()).isEqualTo(B.MOCK_CACHE);
InOrder inOrder = inOrder(one, two);
inOrder.verify(one, times(1)).resolve();
inOrder.verify(two, never()).resolve();
verify(mockBeanFactory, times(1)).getBeanProvider(eq(CacheResolver.class));
verify(mockObjectProvider, times(1)).orderedStream();
}
@Test(expected = IllegalStateException.class)
public void factoryBeanUsingUserDefinedCompositionStrategyWithNoBeanFactory() {
SmartCacheResolverFactoryBean factoryBean = new SmartCacheResolverFactoryBean();
factoryBean.setCompositionStrategy(CompositionStrategy.USER_DEFINED);
assertThat(factoryBean.getBeanFactory()).isNull();
assertThat(factoryBean.getCompositionStrategy()).isEqualTo(CompositionStrategy.USER_DEFINED);
try {
factoryBean.afterPropertiesSet();
}
catch (IllegalStateException expected) {
String expectedMessage = "A Spring context is not present and is required to use [%1$s.%2$s.%3$s]";
assertThat(expected).hasMessage(expectedMessage, SmartCacheResolverFactoryBean.class.getSimpleName(),
CompositionStrategy.class.getSimpleName(), CompositionStrategy.USER_DEFINED);
assertThat(expected).hasNoCause();
throw expected;
}
finally {
assertThat(resolveCacheResolverFromProxy(factoryBean.getObject())).isNull();
}
}
@Test(expected = IllegalStateException.class)
public void factoryBeanUsingUserDefinedCompositionStrategyWithNoCacheResolverBeans() {
Stream<CacheResolver> mockStream = mock(Stream.class);
ObjectProvider mockBeanProvider = mock(ObjectProvider.class);
BeanFactory mockBeanFactory = mock(BeanFactory.class);
when(mockBeanProvider.orderedStream()).thenReturn(mockStream);
when(mockBeanFactory.getBeanProvider(eq(CacheResolver.class))).thenReturn(mockBeanProvider);
SmartCacheResolverFactoryBean factoryBean = new SmartCacheResolverFactoryBean();
factoryBean.setBeanFactory(mockBeanFactory);
factoryBean.setCompositionStrategy(CompositionStrategy.USER_DEFINED);
assertThat(factoryBean.getBeanFactory()).isEqualTo(mockBeanFactory);
assertThat(factoryBean.getCompositionStrategy()).isEqualTo(CompositionStrategy.USER_DEFINED);
try {
factoryBean.afterPropertiesSet();
}
catch (IllegalStateException expected) {
assertThat(expected).hasMessage("No CacheResolver beans were defined");
assertThat(expected).hasNoCause();
throw expected;
}
finally {
assertThat(resolveCacheResolverFromProxy(factoryBean.getObject())).isNull();
verify(mockBeanFactory, times(1)).getBeanProvider(eq(CacheResolver.class));
verify(mockBeanProvider, times(1)).orderedStream();
}
}
@Test
public void getObjectReturnsProxy() {
CacheResolver mockCacheResolver = mock(CacheResolver.class);
SmartCacheResolverFactoryBean factoryBean = spy(new SmartCacheResolverFactoryBean());
CacheResolver cacheResolver = factoryBean.getObject();
assertThat(cacheResolver).isNotNull();
assertThat(cacheResolver).isInstanceOf(CacheResolverProxy.class);
assertThat(((CacheResolverProxy) cacheResolver).getCacheResolver().orElse(null)).isNull();
assertThat(((CacheResolverProxy) cacheResolver).getCacheResolverFactoryBean()).isSameAs(factoryBean);
doReturn(mockCacheResolver).when(factoryBean).getCacheResolver();
assertThat(((CacheResolverProxy) cacheResolver).getCacheResolver().orElse(null))
.isEqualTo(mockCacheResolver);
}
@Test
public void getObjectTypeReturnsCacheResolverClassType() {
SmartCacheResolverFactoryBean factoryBean = spy(new SmartCacheResolverFactoryBean());
doReturn(null).when(factoryBean).getCacheResolver();
assertThat(factoryBean.getObjectType()).isEqualTo(CacheResolver.class);
verify(factoryBean, never()).getObject();
}
@Test
public void getObjectTypeReturnsCacheResolverInstanceType() {
CacheResolver mockCacheResolver = mock(CacheResolver.class);
SmartCacheResolverFactoryBean factoryBean = spy(new SmartCacheResolverFactoryBean());
doReturn(mockCacheResolver).when(factoryBean).getCacheResolver();
assertThat(factoryBean.getObjectType()).isEqualTo(mockCacheResolver.getClass());
verify(factoryBean, never()).getObject();
}
@Test
public void newBeanFactoryCacheResolverWithCacheBeanName() {
BeanFactory mockBeanFactory = mock(BeanFactory.class);
SmartCacheResolverFactoryBean factoryBean = new SmartCacheResolverFactoryBean();
factoryBean.setBeanFactory(mockBeanFactory);
factoryBean.setCacheBeanName("TestCacheBeanName");
assertThat(factoryBean.getBeanFactory()).isEqualTo(mockBeanFactory);
assertThat(factoryBean.getCacheBeanName().orElse(null)).isEqualTo("TestCacheBeanName");
CacheResolver beanFactoryCacheResolver = factoryBean.newBeanFactoryCacheResolver();
assertThat(beanFactoryCacheResolver).isInstanceOf(BeanFactoryCacheResolver.class);
assertThat(((BeanFactoryCacheResolver) beanFactoryCacheResolver).getCacheBeanName().orElse(null))
.isEqualTo("TestCacheBeanName");
verifyNoInteractions(mockBeanFactory);
}
@Test
public void newBeanFactoryCacheResolverWithNoCacheBeanName() {
BeanFactory mockBeanFactory = mock(BeanFactory.class);
SmartCacheResolverFactoryBean factoryBean = new SmartCacheResolverFactoryBean();
factoryBean.setBeanFactory(mockBeanFactory);
assertThat(factoryBean.getBeanFactory()).isEqualTo(mockBeanFactory);
assertThat(factoryBean.getCacheBeanName().orElse(null)).isNull();
CacheResolver beanFactoryCacheResolver = factoryBean.newBeanFactoryCacheResolver();
assertThat(beanFactoryCacheResolver).isInstanceOf(BeanFactoryCacheResolver.class);
assertThat(((BeanFactoryCacheResolver) beanFactoryCacheResolver).getCacheBeanName().orElse(null)).isNull();
verifyNoInteractions(mockBeanFactory);
}
@Test
public void newBeanFactoryCacheResolverWithNullBeanFactory() {
SmartCacheResolverFactoryBean factoryBean = new SmartCacheResolverFactoryBean();
assertThat(factoryBean.getBeanFactory()).isNull();
assertThat(factoryBean.newBeanFactoryCacheResolver()).isNull();
}
@Test
public void newClientCacheFactoryCacheResolverIsNotNull() {
assertThat(new SmartCacheResolverFactoryBean().newClientCacheFactoryCacheResolver())
.isInstanceOf(ClientCacheFactoryCacheResolver.class);
}
@Test
public void newPeerCacheFactoryCacheResolverIsNotNull() {
assertThat(new SmartCacheResolverFactoryBean().newPeerCacheFactoryCacheResolver())
.isInstanceOf(CacheFactoryCacheResolver.class);
}
@Test
public void newSingleCacheCacheResolverWithClientCache() {
ClientCache mockClientCache = mock(ClientCache.class);
SmartCacheResolverFactoryBean factoryBean = new SmartCacheResolverFactoryBean();
factoryBean.setCache(mockClientCache);
assertThat(factoryBean.getCache().orElse(null)).isEqualTo(mockClientCache);
assertThat(factoryBean.newSingleCacheCacheResolver().getClass().getName())
.startsWith(SingleCacheCacheResolver.class.getName());
}
@Test
public void newSingleCacheCacheResolverWithPeerCache() {
Cache mockPeerCache = mock(Cache.class);
SmartCacheResolverFactoryBean factoryBean = new SmartCacheResolverFactoryBean();
factoryBean.setCache(mockPeerCache);
assertThat(factoryBean.getCache().orElse(null)).isEqualTo(mockPeerCache);
assertThat(factoryBean.newSingleCacheCacheResolver().getClass().getName())
.startsWith(SingleCacheCacheResolver.class.getName());
}
@Test
public void newSingleCacheCacheResolverWithNullCache() {
SmartCacheResolverFactoryBean factoryBean = new SmartCacheResolverFactoryBean();
assertThat(factoryBean.getCache().orElse(null)).isNull();
assertThat(factoryBean.newSingleCacheCacheResolver()).isNull();
}
@Test
public void setAndGetCache() {
GemFireCache mockCache = mock(GemFireCache.class);
SmartCacheResolverFactoryBean factoryBean = new SmartCacheResolverFactoryBean();
assertThat(factoryBean.getCache().orElse(null)).isNull();
factoryBean.setCache(mockCache);
assertThat(factoryBean.getCache().orElse(null)).isEqualTo(mockCache);
factoryBean.setCache(null);
assertThat(factoryBean.getCache().orElse(null)).isNull();
}
@Test
public void setAndGetCacheBeanName() {
SmartCacheResolverFactoryBean factoryBean = new SmartCacheResolverFactoryBean();
assertThat(factoryBean.getCacheBeanName().orElse(null)).isNull();
factoryBean.setCacheBeanName("TestCache");
assertThat(factoryBean.getCacheBeanName().orElse(null)).isEqualTo("TestCache");
factoryBean.setCacheBeanName(" ");
assertThat(factoryBean.getCacheBeanName().orElse(null)).isNull();
factoryBean.setCacheBeanName("");
assertThat(factoryBean.getCacheBeanName().orElse(null)).isNull();
factoryBean.setCacheBeanName(null);
assertThat(factoryBean.getCacheBeanName().orElse(null)).isNull();
}
@Test
public void setAndGetCompositionStrategy() {
SmartCacheResolverFactoryBean factoryBean = new SmartCacheResolverFactoryBean();
assertThat(factoryBean.getCompositionStrategy()).isEqualTo(CompositionStrategy.DEFAULT);
factoryBean.setCompositionStrategy(CompositionStrategy.SPRING);
assertThat(factoryBean.getCompositionStrategy()).isEqualTo(CompositionStrategy.SPRING);
factoryBean.setCompositionStrategy(null);
assertThat(factoryBean.getCompositionStrategy()).isEqualTo(CompositionStrategy.DEFAULT);
}
@Test
public void setAndGetConfiguredCacheResolvers() {
CacheResolver a = mock(CacheResolver.class);
CacheResolver b = mock(CacheResolver.class);
CacheResolver c = mock(CacheResolver.class);
List<CacheResolver> cacheResolvers = Arrays.asList(a, null, b, c, null, null);
SmartCacheResolverFactoryBean factoryBean = new SmartCacheResolverFactoryBean();
assertThat(factoryBean.getConfiguredCacheResolvers()).isNull();
factoryBean.setConfiguredCacheResolvers(cacheResolvers);
assertThat(factoryBean.getConfiguredCacheResolvers()).containsExactly(a, b, c);
}
@Test
public void setAndGetConfiguredCacheResolversWithDifferentFactoryBeanCacheResolverReference() {
SmartCacheResolverFactoryBean factoryBeanOne = new SmartCacheResolverFactoryBean();
CacheResolver a = mock(CacheResolver.class);
CacheResolver b = mock(CacheResolver.class);
CacheResolver c = factoryBeanOne.getObject();
SmartCacheResolverFactoryBean factoryBeanTwo = new SmartCacheResolverFactoryBean();
List<CacheResolver> cacheResolvers = Arrays.asList(a, b, c);
factoryBeanTwo.setConfiguredCacheResolvers(cacheResolvers);
assertThat(factoryBeanTwo.getConfiguredCacheResolvers()).containsExactly(a, b, c);
}
@Test
public void setAndGetConfiguredCacheResolversWithSelfReference() {
CacheResolver a = mock(CacheResolver.class);
CacheResolver b = mock(CacheResolver.class);
SmartCacheResolverFactoryBean factoryBean = new SmartCacheResolverFactoryBean();
List<CacheResolver> cacheResolvers = Arrays.asList(a, b, factoryBean.getObject());
factoryBean.setConfiguredCacheResolvers(cacheResolvers);
assertThat(factoryBean.getConfiguredCacheResolvers()).containsExactly(a, b);
}
static class A implements CacheResolver<ClientCache>, Ordered {
@Override
public ClientCache resolve() {
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public int getOrder() {
return 2;
}
}
@Order(1)
static class B implements CacheResolver<Cache> {
static final Cache MOCK_CACHE = mock(Cache.class);
@Override
public Cache resolve() {
return MOCK_CACHE;
}
}
}