From 71dd7b5d2fa2fd855ee2fffd58fc5363e597ae93 Mon Sep 17 00:00:00 2001 From: John Blum Date: Thu, 19 Sep 2019 20:40:03 -0700 Subject: [PATCH] DATAGEODE-231 - The 'gemfireDataSourcePostProcessor' bean should be a BeanPostProcessor. Also, under no circumstances should the BeanPostProcessor have a dependency on the GemFireCache! --- .../GemfireDataSourcePostProcessor.java | 108 ++++--- .../function/ListRegionsOnServerFunction.java | 5 +- .../ClusterDefinedRegionsConfiguration.java | 19 +- .../config/xml/GemfireDataSourceParser.java | 45 ++- ...mfireRepositoryConfigurationExtension.java | 14 +- .../support/GemfireRepositoryFactoryBean.java | 36 ++- .../GemFireDataSourceIntegrationTest.java | 5 +- .../GemFireDataSourceIntegrationTests.java | 6 +- ...onfiguredGemFireServerIntegrationTest.java | 2 - .../GemfireDataSourcePostProcessorTest.java | 285 +++++++++++------- ...ClusterDefinedRegionsIntegrationTests.java | 24 +- .../EnableClusterDefinedRegionsUnitTests.java | 47 ++- ...ryClientRegionIntegrationTests-context.xml | 28 +- 13 files changed, 422 insertions(+), 202 deletions(-) diff --git a/src/main/java/org/springframework/data/gemfire/client/GemfireDataSourcePostProcessor.java b/src/main/java/org/springframework/data/gemfire/client/GemfireDataSourcePostProcessor.java index 3eb7171f..cfe423f8 100644 --- a/src/main/java/org/springframework/data/gemfire/client/GemfireDataSourcePostProcessor.java +++ b/src/main/java/org/springframework/data/gemfire/client/GemfireDataSourcePostProcessor.java @@ -29,11 +29,15 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; +import org.springframework.beans.TypeMismatchException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.data.gemfire.client.function.ListRegionsOnServerFunction; import org.springframework.data.gemfire.function.execution.GemfireOnServersFunctionTemplate; -import org.springframework.util.Assert; +import org.springframework.lang.Nullable; import org.springframework.util.ObjectUtils; /** @@ -56,40 +60,43 @@ import org.springframework.util.ObjectUtils; * @see ListRegionsOnServerFunction * @since 1.2.0 */ -public class GemfireDataSourcePostProcessor implements BeanFactoryPostProcessor { +public class GemfireDataSourcePostProcessor implements BeanFactoryAware, BeanPostProcessor { private static final ClientRegionShortcut DEFAULT_CLIENT_REGION_SHORTCUT = ClientRegionShortcut.PROXY; - private final ClientCache clientCache; + private ClientRegionShortcut clientRegionShortcut; - private ClientRegionShortcut clientRegionShortcut = DEFAULT_CLIENT_REGION_SHORTCUT; + private ConfigurableBeanFactory beanFactory; private final Logger logger = LoggerFactory.getLogger(getClass()); /** - * Constructs an instance of the {@link GemfireDataSourcePostProcessor} {@link BeanFactoryPostProcessor} class - * initialized * with the specified {@link ClientCache} instance for creating client {@link Region Regions} - * for all data {@link Region Regions} configured in the cluster. + * Set a reference to the {@link BeanFactory}. * - * @param clientCache reference to the {@link ClientCache} instance. - * @throws IllegalArgumentException if {@link ClientCache} is {@literal null}. - * @see org.apache.geode.cache.client.ClientCache + * @param beanFactory reference to the {@link BeanFactory}. + * @throws BeansException if the {@link BeanFactory} is not a {@link ConfigurableBeanFactory}. + * @see org.springframework.beans.factory.config.ConfigurableBeanFactory + * @see org.springframework.beans.factory.BeanFactory */ - public GemfireDataSourcePostProcessor(ClientCache clientCache) { + @Override + public void setBeanFactory(BeanFactory beanFactory) throws BeansException { - Assert.notNull(clientCache, "ClientCache must not be null"); - - this.clientCache = clientCache; + if (beanFactory instanceof ConfigurableBeanFactory) { + this.beanFactory = (ConfigurableBeanFactory) beanFactory; + } + else { + throw new TypeMismatchException(beanFactory, ConfigurableBeanFactory.class); + } } /** - * Returns a reference to the {@link ClientCache}. + * Returns a reference to the configured {@link ConfigurableBeanFactory}. * - * @return a reference to the {@link ClientCache}. - * @see org.apache.geode.cache.client.ClientCache + * @return a reference to the configured {@link ConfigurableBeanFactory}. + * @see org.springframework.beans.factory.config.ConfigurableBeanFactory */ - protected ClientCache getClientCache() { - return this.clientCache; + public Optional getBeanFactory() { + return Optional.ofNullable(this.beanFactory); } /** @@ -115,6 +122,17 @@ public class GemfireDataSourcePostProcessor implements BeanFactoryPostProcessor return Optional.ofNullable(this.clientRegionShortcut); } + /** + * Resolves the {@link ClientRegionShortcut} used to configure and create client {@link Region Regions}. + * + * @return the resolved {@link ClientRegionShortcut}. + * @see org.apache.geode.cache.client.ClientRegionShortcut + * @see #getClientRegionShortcut() + */ + protected ClientRegionShortcut resolveClientRegionShortcut() { + return getClientRegionShortcut().orElse(DEFAULT_CLIENT_REGION_SHORTCUT); + } + /** * Returns a reference to the configured {@link Logger} used to log messages. * @@ -125,27 +143,31 @@ public class GemfireDataSourcePostProcessor implements BeanFactoryPostProcessor return this.logger; } - /* - * (non-Javadoc) - * @see org.springframework.beans.factory.config.BeanFactoryPostProcessor - * #postProcessBeanFactory(org.springframework.beans.factory.config.ConfigurableListableBeanFactory) - */ - @Override - public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { - createClientProxyRegions(beanFactory, regionNames()); + @Nullable @Override + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + + if (bean instanceof ClientCache) { + + ClientCache clientCache = (ClientCache) bean; + + getBeanFactory().ifPresent(it -> createClientProxyRegions(it, clientCache, regionNames(clientCache))); + } + + return bean; } + // TODO: remove this logic and delegate to o.s.d.g.config.remote.GemfireAdminOperations - Iterable regionNames() { + Iterable regionNames(ClientCache clientCache) { try { - return execute(new ListRegionsOnServerFunction()); + return execute(clientCache, new ListRegionsOnServerFunction()); } catch (Exception ignore) { try { - Object results = execute(new GetRegionsFunction()); + Object results = execute(clientCache, new GetRegionsFunction()); List regionNames = Collections.emptyList(); @@ -163,15 +185,14 @@ public class GemfireDataSourcePostProcessor implements BeanFactoryPostProcessor return regionNames; } catch (Exception cause) { - logDebug("Failed to determine the Regions available on the Server: %n%1$s", cause); + logDebug("Failed to determine the Regions available on the Server: %n%s", cause); return Collections.emptyList(); } } } - @SuppressWarnings("unchecked") - T execute(Function gemfireFunction, Object... arguments) { - return new GemfireOnServersFunctionTemplate(getClientCache()).executeAndExtract(gemfireFunction, arguments); + T execute(ClientCache clientCache, Function gemfireFunction, Object... arguments) { + return new GemfireOnServersFunctionTemplate(clientCache).executeAndExtract(gemfireFunction, arguments); } boolean containsRegionInformation(Object results) { @@ -180,15 +201,15 @@ public class GemfireDataSourcePostProcessor implements BeanFactoryPostProcessor && ((Object[]) results)[0] instanceof RegionInformation; } - void createClientProxyRegions(ConfigurableListableBeanFactory beanFactory, Iterable regionNames) { + void createClientProxyRegions(ConfigurableBeanFactory beanFactory, ClientCache clientCache, + Iterable regionNames) { if (regionNames.iterator().hasNext()) { - ClientRegionShortcut resolvedClientRegionShortcut = getClientRegionShortcut() - .orElse(DEFAULT_CLIENT_REGION_SHORTCUT); + ClientRegionShortcut resolvedClientRegionShortcut = resolveClientRegionShortcut(); ClientRegionFactory clientRegionFactory = - this.clientCache.createClientRegionFactory(resolvedClientRegionShortcut); + clientCache.createClientRegionFactory(resolvedClientRegionShortcut); for (String regionName : regionNames) { @@ -235,7 +256,16 @@ public class GemfireDataSourcePostProcessor implements BeanFactoryPostProcessor } public GemfireDataSourcePostProcessor using(ClientRegionShortcut clientRegionShortcut) { + setClientRegionShortcut(clientRegionShortcut); + + return this; + } + + public GemfireDataSourcePostProcessor using(BeanFactory beanFactory) { + + setBeanFactory(beanFactory); + return this; } } diff --git a/src/main/java/org/springframework/data/gemfire/client/function/ListRegionsOnServerFunction.java b/src/main/java/org/springframework/data/gemfire/client/function/ListRegionsOnServerFunction.java index 6a7607b8..c0667d23 100644 --- a/src/main/java/org/springframework/data/gemfire/client/function/ListRegionsOnServerFunction.java +++ b/src/main/java/org/springframework/data/gemfire/client/function/ListRegionsOnServerFunction.java @@ -45,8 +45,10 @@ public class ListRegionsOnServerFunction implements Function { * @see org.apache.geode.cache.execute.Function#execute(org.apache.geode.cache.execute.FunctionContext) */ @Override + @SuppressWarnings("unchecked") public void execute(FunctionContext functionContext) { - List regionNames = new ArrayList(); + + List regionNames = new ArrayList<>(); for (Region region : getCache().rootRegions()) { regionNames.add(region.getName()); @@ -55,7 +57,6 @@ public class ListRegionsOnServerFunction implements Function { functionContext.getResultSender().lastResult(regionNames); } - /* (non-Javadoc) */ Cache getCache() { return CacheFactory.getAnyInstance(); } diff --git a/src/main/java/org/springframework/data/gemfire/config/annotation/ClusterDefinedRegionsConfiguration.java b/src/main/java/org/springframework/data/gemfire/config/annotation/ClusterDefinedRegionsConfiguration.java index 0695b08c..e20f476a 100644 --- a/src/main/java/org/springframework/data/gemfire/config/annotation/ClusterDefinedRegionsConfiguration.java +++ b/src/main/java/org/springframework/data/gemfire/config/annotation/ClusterDefinedRegionsConfiguration.java @@ -23,15 +23,19 @@ import org.apache.geode.cache.Region; import org.apache.geode.cache.client.ClientCache; import org.apache.geode.cache.client.ClientRegionShortcut; +import org.apache.shiro.util.Assert; + import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.ImportAware; +import org.springframework.core.Ordered; import org.springframework.core.annotation.AnnotationAttributes; +import org.springframework.core.annotation.Order; import org.springframework.core.type.AnnotationMetadata; import org.springframework.data.gemfire.client.GemfireDataSourcePostProcessor; import org.springframework.data.gemfire.config.annotation.support.AbstractAnnotationConfigSupport; import org.springframework.data.gemfire.util.CacheUtils; -import org.springframework.util.Assert; +import org.springframework.util.ObjectUtils; /** * The {@link ClusterDefinedRegionsConfiguration} class configures client Proxy-based {@link Region Regions} @@ -83,10 +87,17 @@ public class ClusterDefinedRegionsConfiguration extends AbstractAnnotationConfig } @Bean - public GemfireDataSourcePostProcessor gemfireDataSourcePostProcessor(GemFireCache gemfireCache) { + @Order(Ordered.HIGHEST_PRECEDENCE + 1000000) + public GemfireDataSourcePostProcessor gemfireDataSourcePostProcessor() { + return new GemfireDataSourcePostProcessor().using(getBeanFactory()).using(resolveClientRegionShortcut()); + } - Assert.isTrue(CacheUtils.isClient(gemfireCache), "GemFireCache must be an instance of ClientCache"); + @Bean + Object nullCacheDependentBean(GemFireCache cache) { - return new GemfireDataSourcePostProcessor((ClientCache) gemfireCache).using(resolveClientRegionShortcut()); + Assert.isTrue(CacheUtils.isClient(cache), String.format("GemFireCache [%s] must be a %s", + ObjectUtils.nullSafeClassName(cache), ClientCache.class.getName())); + + return null; } } diff --git a/src/main/java/org/springframework/data/gemfire/config/xml/GemfireDataSourceParser.java b/src/main/java/org/springframework/data/gemfire/config/xml/GemfireDataSourceParser.java index d54be100..c579ade5 100644 --- a/src/main/java/org/springframework/data/gemfire/config/xml/GemfireDataSourceParser.java +++ b/src/main/java/org/springframework/data/gemfire/config/xml/GemfireDataSourceParser.java @@ -10,7 +10,6 @@ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ - package org.springframework.data.gemfire.config.xml; import org.slf4j.Logger; @@ -18,23 +17,33 @@ import org.slf4j.LoggerFactory; import org.w3c.dom.Element; import org.springframework.beans.MutablePropertyValues; +import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionReaderUtils; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.context.ConfigurableApplicationContext; import org.springframework.data.gemfire.client.GemfireDataSourcePostProcessor; +import org.springframework.lang.NonNull; +import org.springframework.lang.Nullable; /** * Bean definition parser for the <gfe-data:datasource> SDG XML namespace (XSD) element. * * @author David Turanski * @author John Blum + * @see org.w3c.dom.Element + * @see org.springframework.beans.factory.config.BeanDefinition + * @see org.springframework.beans.factory.support.AbstractBeanDefinition + * @see org.springframework.beans.factory.support.BeanDefinitionBuilder * @see org.springframework.beans.factory.xml.AbstractBeanDefinitionParser + * @see org.springframework.beans.factory.xml.ParserContext * @see org.springframework.data.gemfire.client.GemfireDataSourcePostProcessor - * @see ClientCacheParser - * @see PoolParser + * @see org.springframework.data.gemfire.config.xml.ClientCacheParser + * @see org.springframework.data.gemfire.config.xml.PoolParser */ class GemfireDataSourceParser extends AbstractBeanDefinitionParser { @@ -51,11 +60,12 @@ class GemfireDataSourceParser extends AbstractBeanDefinitionParser { parseAndRegisterClientCache(element, parserContext); parseAndRegisterPool(element, parserContext); - registerGemFireDataSourcePostProcessor(parserContext); + registerGemFireDataSourceBeanPostProcessor(parserContext); return null; } + @SuppressWarnings("all") private void parseAndRegisterClientCache(Element element, ParserContext parserContext) { BeanDefinition clientCacheDefinition = new ClientCacheParser().parse(element, parserContext); @@ -69,6 +79,7 @@ class GemfireDataSourceParser extends AbstractBeanDefinitionParser { } } + @SuppressWarnings("all") private void parseAndRegisterPool(Element element, ParserContext parserContext) { BeanDefinition poolDefinition = new PoolParser().parse(element, parserContext); @@ -82,13 +93,29 @@ class GemfireDataSourceParser extends AbstractBeanDefinitionParser { parserContext.getRegistry().registerBeanDefinition(GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME, poolDefinition); } - private void registerGemFireDataSourcePostProcessor(ParserContext parserContext) { + private void registerGemFireDataSourceBeanPostProcessor(@NonNull ParserContext parserContext) { - BeanDefinitionBuilder builder = - BeanDefinitionBuilder.genericBeanDefinition(GemfireDataSourcePostProcessor.class); + BeanFactory beanFactory = resolveBeanFactory(parserContext); - builder.addConstructorArgReference(GemfireConstants.DEFAULT_GEMFIRE_CACHE_NAME); + if (beanFactory != null) { - BeanDefinitionReaderUtils.registerWithGeneratedName(builder.getBeanDefinition(), parserContext.getRegistry()); + BeanDefinitionBuilder builder = + BeanDefinitionBuilder.genericBeanDefinition(GemfireDataSourcePostProcessor.class); + + builder.addPropertyValue("beanFactory", beanFactory); + + BeanDefinitionReaderUtils.registerWithGeneratedName(builder.getBeanDefinition(), parserContext.getRegistry()); + } + } + + private @Nullable BeanFactory resolveBeanFactory(@NonNull ParserContext parserContext) { + + BeanDefinitionRegistry registry = parserContext.getRegistry(); + + return registry instanceof ConfigurableApplicationContext + ? ((ConfigurableApplicationContext) registry).getBeanFactory() + : registry instanceof BeanFactory + ? (BeanFactory) registry + : null; } } diff --git a/src/main/java/org/springframework/data/gemfire/repository/config/GemfireRepositoryConfigurationExtension.java b/src/main/java/org/springframework/data/gemfire/repository/config/GemfireRepositoryConfigurationExtension.java index e15a5f99..05b228a7 100644 --- a/src/main/java/org/springframework/data/gemfire/repository/config/GemfireRepositoryConfigurationExtension.java +++ b/src/main/java/org/springframework/data/gemfire/repository/config/GemfireRepositoryConfigurationExtension.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.gemfire.repository.config; import java.lang.annotation.Annotation; @@ -23,6 +22,7 @@ import java.util.Collections; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.data.gemfire.config.xml.GemfireConstants; import org.springframework.data.gemfire.mapping.GemfireMappingContext; import org.springframework.data.gemfire.mapping.annotation.Region; import org.springframework.data.gemfire.repository.GemfireRepository; @@ -89,6 +89,18 @@ public class GemfireRepositoryConfigurationExtension extends RepositoryConfigura return GemfireRepositoryFactoryBean.class.getName(); } + /* + * (non-Javadoc) + * @see org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport#postProcess(BeanDefinitionBuilder, RepositoryConfigurationSource) + */ + @Override + public void postProcess(BeanDefinitionBuilder builder, RepositoryConfigurationSource source) { + + super.postProcess(builder, source); + + builder.addPropertyReference("cache", GemfireConstants.DEFAULT_GEMFIRE_CACHE_NAME); + } + /* * (non-Javadoc) * @see org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport#postProcess(org.springframework.beans.factory.support.BeanDefinitionBuilder, org.springframework.data.repository.config.AnnotationRepositoryConfigurationSource) diff --git a/src/main/java/org/springframework/data/gemfire/repository/support/GemfireRepositoryFactoryBean.java b/src/main/java/org/springframework/data/gemfire/repository/support/GemfireRepositoryFactoryBean.java index 8659fc25..f6a5f6b6 100644 --- a/src/main/java/org/springframework/data/gemfire/repository/support/GemfireRepositoryFactoryBean.java +++ b/src/main/java/org/springframework/data/gemfire/repository/support/GemfireRepositoryFactoryBean.java @@ -17,9 +17,11 @@ package org.springframework.data.gemfire.repository.support; import java.util.ArrayList; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Set; import java.util.WeakHashMap; import java.util.stream.Collectors; import java.util.stream.StreamSupport; @@ -28,6 +30,7 @@ import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.RequiredArgsConstructor; +import org.apache.geode.cache.GemFireCache; import org.apache.geode.cache.Region; import org.springframework.beans.BeansException; @@ -73,6 +76,8 @@ public class GemfireRepositoryFactoryBean, S, ID> private ApplicationContext applicationContext; + private GemFireCache cache; + private Iterable> regions; private MappingContext, GemfirePersistentProperty> mappingContext; @@ -96,14 +101,19 @@ public class GemfireRepositoryFactoryBean, S, ID> * @see org.springframework.context.ApplicationContext */ @Override - @SuppressWarnings({ "rawtypes", "unchecked" }) public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; - this.regions = Collections.unmodifiableSet(applicationContext.getBeansOfType(Region.class).entrySet().stream() + Map regionBeans = applicationContext.getBeansOfType(Region.class); + + Set> regions = new HashSet<>(Collections.unmodifiableSet(regionBeans.entrySet().stream() .>map(Map.Entry::getValue) - .collect(Collectors.toSet())); + .collect(Collectors.toSet()))); + + getCache().map(GemFireCache::rootRegions).ifPresent(regions::addAll); + + this.regions = regions; } /** @@ -117,6 +127,26 @@ public class GemfireRepositoryFactoryBean, S, ID> return Optional.ofNullable(this.applicationContext); } + /** + * Set a reference to the {@link GemFireCache}. + * + * @param cache reference to the {@link GemFireCache}. + * @see org.apache.geode.cache.GemFireCache + */ + public void setCache(GemFireCache cache) { + this.cache = cache; + } + + /** + * Returns an {@link Optional} reference to the configured {@link GemFireCache}. + * + * @return an {@link Optional} reference to the configured {@link GemFireCache}. + * @see org.apache.geode.cache.GemFireCache + */ + protected Optional getCache() { + return Optional.ofNullable(this.cache); + } + /** * Configures the {@link MappingContext} used to perform application domain object type to data store mappings. * diff --git a/src/test/java/org/springframework/data/gemfire/client/GemFireDataSourceIntegrationTest.java b/src/test/java/org/springframework/data/gemfire/client/GemFireDataSourceIntegrationTest.java index 0e5924e4..58465f5c 100644 --- a/src/test/java/org/springframework/data/gemfire/client/GemFireDataSourceIntegrationTest.java +++ b/src/test/java/org/springframework/data/gemfire/client/GemFireDataSourceIntegrationTest.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.gemfire.client; import static org.assertj.core.api.Assertions.assertThat; @@ -85,8 +84,7 @@ public class GemFireDataSourceIntegrationTest extends ClientServerIntegrationTes arguments.add(GemFireDataSourceIntegrationTest.class.getName() .replace(".", "/").concat("-server-context.xml")); - gemfireServer = run(serverWorkingDirectory, ServerProcess.class, - arguments.toArray(new String[arguments.size()])); + gemfireServer = run(serverWorkingDirectory, ServerProcess.class, arguments.toArray(new String[0])); waitForServerToStart(DEFAULT_HOSTNAME, availablePort); @@ -138,7 +136,6 @@ public class GemFireDataSourceIntegrationTest extends ClientServerIntegrationTes } @Test - @SuppressWarnings("unchecked") public void clientProxyRegionBeansExist() { assertRegion(clientOnlyRegion, "ClientOnlyRegion"); diff --git a/src/test/java/org/springframework/data/gemfire/client/GemFireDataSourceIntegrationTests.java b/src/test/java/org/springframework/data/gemfire/client/GemFireDataSourceIntegrationTests.java index 0d7e9086..1c9a3eb3 100644 --- a/src/test/java/org/springframework/data/gemfire/client/GemFireDataSourceIntegrationTests.java +++ b/src/test/java/org/springframework/data/gemfire/client/GemFireDataSourceIntegrationTests.java @@ -10,7 +10,6 @@ * 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.client; import static org.assertj.core.api.Assertions.assertThat; @@ -105,14 +104,11 @@ public class GemFireDataSourceIntegrationTests extends ClientServerIntegrationTe Pool pool = this.applicationContext.getBean("gemfirePool", Pool.class); assertThat(pool).isNotNull(); - assertThat(pool.getSubscriptionEnabled()).isTrue(); List regionList = Arrays.asList(this.applicationContext.getBeanNamesForType(Region.class)); assertThat(regionList).hasSize(3); - assertThat(regionList.contains("r1")).isTrue(); - assertThat(regionList.contains("r2")).isTrue(); - assertThat(regionList.contains("simple")).isTrue(); + assertThat(regionList).containsExactlyInAnyOrder("r1", "r2", "simple"); Region simple = this.applicationContext.getBean("simple", Region.class); diff --git a/src/test/java/org/springframework/data/gemfire/client/GemFireDataSourceUsingNonSpringConfiguredGemFireServerIntegrationTest.java b/src/test/java/org/springframework/data/gemfire/client/GemFireDataSourceUsingNonSpringConfiguredGemFireServerIntegrationTest.java index 0a0344c6..ef47fa64 100644 --- a/src/test/java/org/springframework/data/gemfire/client/GemFireDataSourceUsingNonSpringConfiguredGemFireServerIntegrationTest.java +++ b/src/test/java/org/springframework/data/gemfire/client/GemFireDataSourceUsingNonSpringConfiguredGemFireServerIntegrationTest.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.gemfire.client; import java.io.File; @@ -172,7 +171,6 @@ public class GemFireDataSourceUsingNonSpringConfiguredGemFireServerIntegrationTe } @Test - @SuppressWarnings("unchecked") public void clientProxyRegionBeansExist() { assertRegion(localRegion, "LocalRegion"); diff --git a/src/test/java/org/springframework/data/gemfire/client/GemfireDataSourcePostProcessorTest.java b/src/test/java/org/springframework/data/gemfire/client/GemfireDataSourcePostProcessorTest.java index 4cded477..39a85fd2 100644 --- a/src/test/java/org/springframework/data/gemfire/client/GemfireDataSourcePostProcessorTest.java +++ b/src/test/java/org/springframework/data/gemfire/client/GemfireDataSourcePostProcessorTest.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.gemfire.client; import static org.assertj.core.api.Assertions.assertThat; @@ -31,13 +30,13 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalArgumentException; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; import java.util.stream.StreamSupport; @@ -57,7 +56,9 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.TypeMismatchException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.data.gemfire.client.function.ListRegionsOnServerFunction; import org.springframework.data.gemfire.util.RegionUtils; @@ -68,9 +69,12 @@ import org.springframework.data.gemfire.util.RegionUtils; * @see org.junit.Test * @see org.mockito.Mockito * @see org.apache.geode.cache.Region + * @see org.apache.geode.cache.RegionAttributes * @see org.apache.geode.cache.client.ClientCache * @see org.apache.geode.cache.client.ClientRegionFactory - * @see org.springframework.beans.factory.config.ConfigurableListableBeanFactory + * @see org.apache.geode.cache.execute.Function + * @see org.springframework.beans.factory.BeanFactory + * @see org.springframework.beans.factory.config.ConfigurableBeanFactory * @see org.springframework.data.gemfire.client.GemfireDataSourcePostProcessor * @see org.springframework.data.gemfire.client.function.ListRegionsOnServerFunction * @since 1.7.0 @@ -78,6 +82,9 @@ import org.springframework.data.gemfire.util.RegionUtils; @RunWith(MockitoJUnitRunner.class) public class GemfireDataSourcePostProcessorTest { + @Mock + private ConfigurableBeanFactory mockBeanFactory; + @Mock private ClientCache mockClientCache; @@ -105,64 +112,144 @@ public class GemfireDataSourcePostProcessorTest { @Test public void constructGemfireDataSourcePostProcessor() { - GemfireDataSourcePostProcessor postProcessor = new GemfireDataSourcePostProcessor(mockClientCache); + GemfireDataSourcePostProcessor postProcessor = new GemfireDataSourcePostProcessor(); assertThat(postProcessor).isNotNull(); - assertThat(postProcessor.getClientCache()).isEqualTo(this.mockClientCache); - assertThat(postProcessor.getClientRegionShortcut().orElse(null)).isEqualTo(ClientRegionShortcut.PROXY); + assertThat(postProcessor.getClientRegionShortcut().orElse(null)).isNull(); + assertThat(postProcessor.resolveClientRegionShortcut()).isEqualTo(ClientRegionShortcut.PROXY); assertThat(postProcessor.getLogger()).isNotNull(); } + @Test + public void setAndGetBeanFactory() { + + GemfireDataSourcePostProcessor postProcessor = new GemfireDataSourcePostProcessor(); + + assertThat(postProcessor).isNotNull(); + assertThat(postProcessor.getBeanFactory().orElse(null)).isNull(); + + postProcessor.setBeanFactory(this.mockBeanFactory); + + assertThat(postProcessor.getBeanFactory().orElse(null)).isSameAs(this.mockBeanFactory); + } + + @Test(expected = TypeMismatchException.class) + public void setBeanFactoryToIncompatibleTypeThrowsBeansException() { + new GemfireDataSourcePostProcessor().setBeanFactory(mock(BeanFactory.class)); + } + + @Test(expected = TypeMismatchException.class) + public void setBeanFactoryToNullThrowsBeansException() { + new GemfireDataSourcePostProcessor().setBeanFactory(null); + } + @Test public void setAndGetClientRegionShortcut() { - GemfireDataSourcePostProcessor postProcessor = new GemfireDataSourcePostProcessor(this.mockClientCache); + GemfireDataSourcePostProcessor postProcessor = new GemfireDataSourcePostProcessor(); assertThat(postProcessor).isNotNull(); - assertThat(postProcessor.getClientRegionShortcut().orElse(null)).isEqualTo(ClientRegionShortcut.PROXY); + assertThat(postProcessor.getClientRegionShortcut().orElse(null)).isNull(); + assertThat(postProcessor.resolveClientRegionShortcut()).isEqualTo(ClientRegionShortcut.PROXY); postProcessor.setClientRegionShortcut(ClientRegionShortcut.CACHING_PROXY); assertThat(postProcessor.getClientRegionShortcut().orElse(null)) .isEqualTo(ClientRegionShortcut.CACHING_PROXY); + assertThat(postProcessor.resolveClientRegionShortcut()).isEqualTo(ClientRegionShortcut.CACHING_PROXY); postProcessor.setClientRegionShortcut(ClientRegionShortcut.LOCAL); - assertThat(postProcessor.getClientRegionShortcut().orElse(null)).isEqualTo(ClientRegionShortcut.LOCAL); + assertThat(postProcessor.getClientRegionShortcut().orElse(null)) + .isEqualTo(ClientRegionShortcut.LOCAL); + assertThat(postProcessor.resolveClientRegionShortcut()).isEqualTo(ClientRegionShortcut.LOCAL); postProcessor.setClientRegionShortcut(null); - assertThat(postProcessor.getClientRegionShortcut().isPresent()).isFalse(); + assertThat(postProcessor.getClientRegionShortcut().orElse(null)).isNull(); + assertThat(postProcessor.resolveClientRegionShortcut()).isEqualTo(ClientRegionShortcut.PROXY); } @Test - public void postProcessBeanFactoryCallsCreateClientRegionProxiesWithRegionNames() { + public void usingBeanFactory() { - AtomicBoolean createClientRegionProxiesCalled = new AtomicBoolean(false); + GemfireDataSourcePostProcessor postProcessor = spy(new GemfireDataSourcePostProcessor()); - ConfigurableListableBeanFactory mockBeanFactory = - mock(ConfigurableListableBeanFactory.class, "MockSpringBeanFactory"); + assertThat(postProcessor).isNotNull(); + assertThat(postProcessor.getBeanFactory().orElse(null)).isNull(); + assertThat(postProcessor.using(this.mockBeanFactory)).isSameAs(postProcessor); + assertThat(postProcessor.getBeanFactory().orElse(null)).isSameAs(this.mockBeanFactory); + + verify(postProcessor, times(1)).setBeanFactory(eq(this.mockBeanFactory)); + } + + @Test + public void usingClientRegionShortcut() { + + GemfireDataSourcePostProcessor postProcessor = spy(new GemfireDataSourcePostProcessor()) + .using(ClientRegionShortcut.LOCAL_PERSISTENT); + + assertThat(postProcessor).isNotNull(); + assertThat(postProcessor.getClientRegionShortcut().orElse(null)).isEqualTo(ClientRegionShortcut.LOCAL_PERSISTENT); + assertThat(postProcessor.resolveClientRegionShortcut()).isEqualTo(ClientRegionShortcut.LOCAL_PERSISTENT); + assertThat(postProcessor.using(ClientRegionShortcut.LOCAL_OVERFLOW)).isSameAs(postProcessor); + assertThat(postProcessor.getClientRegionShortcut().orElse(null)).isEqualTo(ClientRegionShortcut.LOCAL_OVERFLOW); + assertThat(postProcessor.resolveClientRegionShortcut()).isEqualTo(ClientRegionShortcut.LOCAL_OVERFLOW); + + verify(postProcessor, times(1)) + .setClientRegionShortcut(eq(ClientRegionShortcut.LOCAL_PERSISTENT)); + + verify(postProcessor, times(1)) + .setClientRegionShortcut(eq(ClientRegionShortcut.LOCAL_OVERFLOW)); + } + + @Test + @SuppressWarnings("unchecked") + public void postProcessAfterInitializationCallsCreateClientRegionProxiesWithRegionNames() { String[] testRegionNames = { "Test" }; - GemfireDataSourcePostProcessor postProcessor = new GemfireDataSourcePostProcessor(this.mockClientCache) { + GemfireDataSourcePostProcessor postProcessor = spy(new GemfireDataSourcePostProcessor()); - @Override - Iterable regionNames() { - return Arrays.asList(testRegionNames); - } + postProcessor.setBeanFactory(this.mockBeanFactory); - @Override - void createClientProxyRegions(ConfigurableListableBeanFactory beanFactory, Iterable regionNames) { - assertThat(beanFactory).isSameAs(mockBeanFactory); - assertThat(regionNames).containsExactly(testRegionNames); - createClientRegionProxiesCalled.compareAndSet(false, true); - } - }; + doReturn(Arrays.asList(testRegionNames)).when(postProcessor).regionNames(any(ClientCache.class)); - postProcessor.postProcessBeanFactory(mockBeanFactory); + doAnswer(invocation -> { - assertThat(createClientRegionProxiesCalled.get()).isTrue(); + ConfigurableBeanFactory beanFactory = invocation.getArgument(0); + ClientCache clientCache = invocation.getArgument(1); + Iterable regionNames = invocation.getArgument(2); + + assertThat(beanFactory).isSameAs(this.mockBeanFactory); + assertThat(clientCache).isSameAs(this.mockClientCache); + assertThat(regionNames).containsExactly(testRegionNames); + + return null; + + }).when(postProcessor) + .createClientProxyRegions(any(ConfigurableBeanFactory.class), any(ClientCache.class), any(Iterable.class)); + + postProcessor.postProcessAfterInitialization(this.mockClientCache, "mockClientCache"); + + verify(postProcessor, times(1)).regionNames(eq(this.mockClientCache)); + verify(postProcessor, times(1)) + .createClientProxyRegions(eq(this.mockBeanFactory), eq(this.mockClientCache), isA(Iterable.class)); + } + + @Test + @SuppressWarnings("unchecked") + public void postProcessAfterInitializationWithNoBeanFactoryDoesNothing() { + + GemfireDataSourcePostProcessor postProcessor = spy(new GemfireDataSourcePostProcessor()); + + assertThat(postProcessor.getBeanFactory().orElse(null)).isNull(); + + postProcessor.postProcessAfterInitialization(this.mockClientCache, "mockClientCache"); + + verify(postProcessor, never()).regionNames(any(ClientCache.class)); + verify(postProcessor, never()).createClientProxyRegions(any(ConfigurableBeanFactory.class), + any(ClientCache.class), any(Iterable.class)); } @Test @@ -170,28 +257,30 @@ public class GemfireDataSourcePostProcessorTest { String[] expectedRegionNames = { "ExampleOne", "ExampleTwo" }; - GemfireDataSourcePostProcessor postProcessor = spy(new GemfireDataSourcePostProcessor(this.mockClientCache)); + GemfireDataSourcePostProcessor postProcessor = spy(new GemfireDataSourcePostProcessor()); doReturn(Arrays.asList(expectedRegionNames)).when(postProcessor) - .execute(isA(ListRegionsOnServerFunction.class), any()); + .execute(isA(ClientCache.class), isA(ListRegionsOnServerFunction.class), any()); - Iterable actualRegionNames = postProcessor.regionNames(); + Iterable actualRegionNames = postProcessor.regionNames(this.mockClientCache); assertThat(actualRegionNames).containsExactly(expectedRegionNames); - verify(postProcessor, times(1)).execute(isA(ListRegionsOnServerFunction.class)); - verify(postProcessor, never()).execute(any(GetRegionsFunction.class)); + verify(postProcessor, times(1)) + .execute(eq(this.mockClientCache), isA(ListRegionsOnServerFunction.class)); + + verify(postProcessor, never()).execute(any(ClientCache.class), any(GetRegionsFunction.class)); } @Test - @SuppressWarnings("unchecked") public void regionNamesWithGetRegionsFunction() { String[] expectedRegionNames = { "ExampleOne", "ExampleTwo" }; - GemfireDataSourcePostProcessor postProcessor = spy(new GemfireDataSourcePostProcessor(this.mockClientCache)); + GemfireDataSourcePostProcessor postProcessor = spy(new GemfireDataSourcePostProcessor()); - doThrow(new RuntimeException("fail")).when(postProcessor).execute(isA(ListRegionsOnServerFunction.class), any()); + doThrow(new RuntimeException("FAIL")).when(postProcessor) + .execute(isA(ClientCache.class), isA(ListRegionsOnServerFunction.class), any()); doAnswer(invocation -> Arrays.stream(expectedRegionNames) @@ -199,103 +288,110 @@ public class GemfireDataSourcePostProcessorTest { .map(this::newRegionInformation) .collect(Collectors.toList()) .toArray() - ).when(postProcessor).execute(isA(GetRegionsFunction.class), any()); + ).when(postProcessor).execute(isA(ClientCache.class), isA(GetRegionsFunction.class), any()); List actualRegionNames = - StreamSupport.stream(postProcessor.regionNames().spliterator(), false).collect(Collectors.toList()); + StreamSupport.stream(postProcessor.regionNames(this.mockClientCache).spliterator(), false) + .collect(Collectors.toList()); assertThat(actualRegionNames).containsExactly(expectedRegionNames); - verify(postProcessor, times(1)).execute(isA(ListRegionsOnServerFunction.class)); - verify(postProcessor, times(1)).execute(isA(GetRegionsFunction.class)); + verify(postProcessor, times(1)) + .execute(eq(this.mockClientCache), isA(ListRegionsOnServerFunction.class)); + + verify(postProcessor, times(1)) + .execute(eq(this.mockClientCache), isA(GetRegionsFunction.class)); } @Test public void regionNamesWithGetRegionsFunctionReturningNoResults() { - GemfireDataSourcePostProcessor postProcessor = spy(new GemfireDataSourcePostProcessor(this.mockClientCache)); + GemfireDataSourcePostProcessor postProcessor = spy(new GemfireDataSourcePostProcessor()); - doThrow(new RuntimeException("fail")).when(postProcessor).execute(isA(ListRegionsOnServerFunction.class), any()); - doReturn(null).when(postProcessor).execute(isA(GetRegionsFunction.class), any()); + doThrow(new RuntimeException("FAIL")).when(postProcessor) + .execute(any(ClientCache.class), isA(ListRegionsOnServerFunction.class), any()); - Iterable actualRegionNames = postProcessor.regionNames(); + doReturn(null).when(postProcessor) + .execute(any(ClientCache.class), isA(GetRegionsFunction.class), any()); + + Iterable actualRegionNames = postProcessor.regionNames(this.mockClientCache); assertThat(actualRegionNames).isNotNull(); assertThat(actualRegionNames).isEmpty(); - verify(postProcessor, times(1)).execute(isA(ListRegionsOnServerFunction.class)); - verify(postProcessor, times(1)).execute(isA(GetRegionsFunction.class)); + verify(postProcessor, times(1)) + .execute(eq(this.mockClientCache), isA(ListRegionsOnServerFunction.class)); + + verify(postProcessor, times(1)) + .execute(eq(this.mockClientCache), isA(GetRegionsFunction.class)); } @Test public void regionNamesWithGetRegionsFunctionThrowingException() { - GemfireDataSourcePostProcessor postProcessor = spy(new GemfireDataSourcePostProcessor(this.mockClientCache)); + GemfireDataSourcePostProcessor postProcessor = spy(new GemfireDataSourcePostProcessor()); doAnswer(invocation -> { Function function = invocation.getArgument(0); - throw new IllegalArgumentException(String.format("Function [%1$s] with ID [%2$s] not registered", - function.getClass().getName(), function.getId())); + throw newIllegalArgumentException("Function [%1$s] with ID [%2$s] not registered", + function.getClass().getName(), function.getId()); - }).when(postProcessor).execute(any(Function.class), any()); + }).when(postProcessor).execute(any(ClientCache.class), any(Function.class), any()); - Iterable actualRegionNames = postProcessor.regionNames(); + Iterable actualRegionNames = postProcessor.regionNames(this.mockClientCache); assertThat(actualRegionNames).isNotNull(); assertThat(actualRegionNames).isEmpty(); - verify(postProcessor, times(1)).execute(isA(ListRegionsOnServerFunction.class)); - verify(postProcessor, times(1)).execute(isA(GetRegionsFunction.class)); + verify(postProcessor, times(1)) + .execute(eq(this.mockClientCache), isA(ListRegionsOnServerFunction.class)); + + verify(postProcessor, times(1)) + .execute(eq(this.mockClientCache), isA(GetRegionsFunction.class)); + verify(postProcessor, times(1)) .logDebug(startsWith("Failed to determine the Regions available on the Server:"), any()); } @Test public void containsRegionInformationIsTrue() { - assertThat(new GemfireDataSourcePostProcessor(this.mockClientCache) + assertThat(new GemfireDataSourcePostProcessor() .containsRegionInformation(new Object[] { newRegionInformation(mockRegion("Example")) })) .isTrue(); } @Test public void containsRegionInformationWithEmptyArrayIsFalse() { - assertThat(new GemfireDataSourcePostProcessor(this.mockClientCache) - .containsRegionInformation(new Object[0])) - .isFalse(); + assertThat(new GemfireDataSourcePostProcessor().containsRegionInformation(new Object[0])).isFalse(); } @Test public void containsRegionInformationWithListOfRegionInformationIsFalse() { - assertThat(new GemfireDataSourcePostProcessor(this.mockClientCache) + assertThat(new GemfireDataSourcePostProcessor() .containsRegionInformation(Collections.singletonList(newRegionInformation(mockRegion("Example"))))) .isFalse(); } @Test public void containsRegionInformationWithNonEmptyArrayContainingNonRegionInformationIsFalse() { - assertThat(new GemfireDataSourcePostProcessor(this.mockClientCache) - .containsRegionInformation(new Object[] { "test" })) - .isFalse(); + assertThat(new GemfireDataSourcePostProcessor().containsRegionInformation(new Object[] { "TEST" })).isFalse(); } @Test public void containsRegionInformationWithNullIsFalse() { - assertThat(new GemfireDataSourcePostProcessor(this.mockClientCache).containsRegionInformation(null)) - .isFalse(); + assertThat(new GemfireDataSourcePostProcessor().containsRegionInformation(null)).isFalse(); } @Test @SuppressWarnings("unchecked") public void createClientProxyRegionsIsSuccessful() { - ClientCache mockClientCache = mock(ClientCache.class, "MockGemFireClientCache"); + ClientRegionFactory mockClientRegionFactory = mock(ClientRegionFactory.class); - ClientRegionFactory mockClientRegionFactory = mock(ClientRegionFactory.class, "MockGemFireClientRegionFactory"); - - when(mockClientCache.createClientRegionFactory(eq(ClientRegionShortcut.PROXY))).thenReturn( - mockClientRegionFactory); + when(this.mockClientCache.createClientRegionFactory(eq(ClientRegionShortcut.PROXY))) + .thenReturn(mockClientRegionFactory); Region mockRegionOne = mock(Region.class, "MockGemFireRegionOne"); Region mockRegionTwo = mock(Region.class, "MockGemFireRegionTwo"); @@ -315,60 +411,39 @@ public class GemfireDataSourcePostProcessorTest { }).when(mockClientRegionFactory).create(any(String.class)); - ConfigurableListableBeanFactory mockBeanFactory = mock(ConfigurableListableBeanFactory.class, "MockSpringBeanFactory"); - when(mockBeanFactory.containsBean(any(String.class))).thenReturn(false); - GemfireDataSourcePostProcessor postProcessor = new GemfireDataSourcePostProcessor(mockClientCache); + GemfireDataSourcePostProcessor postProcessor = new GemfireDataSourcePostProcessor(); - postProcessor.createClientProxyRegions(mockBeanFactory, regionMap.keySet()); + postProcessor.createClientProxyRegions(this.mockBeanFactory, this.mockClientCache, regionMap.keySet()); - verify(mockClientCache, times(1)).createClientRegionFactory(eq(ClientRegionShortcut.PROXY)); + verify(this.mockClientCache, times(1)).createClientRegionFactory(eq(ClientRegionShortcut.PROXY)); verify(mockClientRegionFactory, times(1)).create(eq("RegionOne")); verify(mockClientRegionFactory, times(1)).create(eq("RegionTwo")); - verify(mockBeanFactory, times(1)).registerSingleton(eq("RegionOne"), same(mockRegionOne)); - verify(mockBeanFactory, times(1)).registerSingleton(eq("RegionTwo"), same(mockRegionTwo)); + verify(this.mockBeanFactory, times(1)).registerSingleton(eq("RegionOne"), same(mockRegionOne)); + verify(this.mockBeanFactory, times(1)).registerSingleton(eq("RegionTwo"), same(mockRegionTwo)); } @Test @SuppressWarnings("unchecked") public void createClientProxyRegionsWhenRegionBeanExists() { - ClientCache mockClientCache = mock(ClientCache.class, "MockGemFireClientCache"); + ClientRegionFactory mockClientRegionFactory = mock(ClientRegionFactory.class); - ClientRegionFactory mockClientRegionFactory = mock(ClientRegionFactory.class, "MockGemFireClientRegionFactory"); + when(this.mockClientCache.createClientRegionFactory(eq(ClientRegionShortcut.PROXY))) + .thenReturn(mockClientRegionFactory); - when(mockClientCache.createClientRegionFactory(eq(ClientRegionShortcut.PROXY))).thenReturn( - mockClientRegionFactory); + Region mockRegion = mock(Region.class); - Region mockRegion = mock(Region.class, "MockGemFireRegion"); + when(this.mockBeanFactory.containsBean(any(String.class))).thenReturn(true); + when(this.mockBeanFactory.getBean(eq("Example"))).thenReturn(mockRegion); - ConfigurableListableBeanFactory mockBeanFactory = mock(ConfigurableListableBeanFactory.class, "MockSpringBeanFactory"); + GemfireDataSourcePostProcessor postProcessor = new GemfireDataSourcePostProcessor(); - when(mockBeanFactory.containsBean(any(String.class))).thenReturn(true); - when(mockBeanFactory.getBean(eq("Example"))).thenReturn(mockRegion); + postProcessor.createClientProxyRegions(this.mockBeanFactory, this.mockClientCache, Collections.singletonList("Example")); - GemfireDataSourcePostProcessor postProcessor = new GemfireDataSourcePostProcessor(mockClientCache); - - postProcessor.createClientProxyRegions(mockBeanFactory, Collections.singletonList("Example")); - - verify(mockClientCache, times(1)).createClientRegionFactory(eq(ClientRegionShortcut.PROXY)); + verify(this.mockClientCache, times(1)).createClientRegionFactory(eq(ClientRegionShortcut.PROXY)); verify(mockClientRegionFactory, never()).create(any(String.class)); - verify(mockBeanFactory, never()).registerSingleton(any(String.class), any(Region.class)); - } - - @Test - public void usingIsCorrect() { - - GemfireDataSourcePostProcessor postProcessor = new GemfireDataSourcePostProcessor(this.mockClientCache) - .using(ClientRegionShortcut.LOCAL); - - assertThat(postProcessor).isNotNull(); - assertThat(postProcessor.getClientRegionShortcut().orElse(null)).isEqualTo(ClientRegionShortcut.LOCAL); - assertThat(postProcessor.using(ClientRegionShortcut.CACHING_PROXY)).isEqualTo(postProcessor); - assertThat(postProcessor.getClientRegionShortcut() - .orElse(null)).isEqualTo(ClientRegionShortcut.CACHING_PROXY); - assertThat(postProcessor.using(null)).isEqualTo(postProcessor); - assertThat(postProcessor.getClientRegionShortcut().isPresent()).isFalse(); + verify(this.mockBeanFactory, never()).registerSingleton(any(String.class), any(Region.class)); } } diff --git a/src/test/java/org/springframework/data/gemfire/config/annotation/EnableClusterDefinedRegionsIntegrationTests.java b/src/test/java/org/springframework/data/gemfire/config/annotation/EnableClusterDefinedRegionsIntegrationTests.java index 4819b4bd..6a207947 100644 --- a/src/test/java/org/springframework/data/gemfire/config/annotation/EnableClusterDefinedRegionsIntegrationTests.java +++ b/src/test/java/org/springframework/data/gemfire/config/annotation/EnableClusterDefinedRegionsIntegrationTests.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.gemfire.config.annotation; import static org.assertj.core.api.Assertions.assertThat; @@ -25,12 +24,16 @@ import javax.annotation.Resource; import org.apache.geode.cache.DataPolicy; import org.apache.geode.cache.GemFireCache; import org.apache.geode.cache.Region; +import org.apache.geode.cache.client.ClientCache; import org.junit.AfterClass; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; @@ -41,6 +44,7 @@ import org.springframework.data.gemfire.ReplicatedRegionFactoryBean; import org.springframework.data.gemfire.process.ProcessWrapper; import org.springframework.data.gemfire.support.ConnectionEndpoint; import org.springframework.data.gemfire.test.support.ClientServerIntegrationTestsSupport; +import org.springframework.data.gemfire.util.CacheUtils; import org.springframework.data.gemfire.util.RegionUtils; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; @@ -88,6 +92,9 @@ public class EnableClusterDefinedRegionsIntegrationTests extends ClientServerInt stop(gemfireServer); } + @Autowired + private ClientCache cache; + @Resource(name = "LocalRegion") private Region localClientProxyRegion; @@ -106,6 +113,13 @@ public class EnableClusterDefinedRegionsIntegrationTests extends ClientServerInt assertThat(region.getAttributes().getDataPolicy()).isEqualTo(DataPolicy.EMPTY); } + @Before + public void setup() { + + assertThat(this.cache).isNotNull(); + assertThat(CacheUtils.isClient(this.cache)); + } + @Test public void clusterRegionsExistOnClient() { @@ -130,10 +144,14 @@ public class EnableClusterDefinedRegionsIntegrationTests extends ClientServerInt return (bean, clientCacheFactoryBean) -> clientCacheFactoryBean.setServers( Collections.singletonList(new ConnectionEndpoint("localhost", port))); } + + @Bean("TestBean") + Object testBean(@Qualifier("LocalRegion") Region localRegion) { + return "TEST"; + } } - @CacheServerApplication(name = "EnableClusterDefinedRegionsIntegrationTests", - logLevel = GEMFIRE_LOG_LEVEL) + @CacheServerApplication(name = "EnableClusterDefinedRegionsIntegrationTests", logLevel = GEMFIRE_LOG_LEVEL) static class ServerTestConfiguration { public static void main(String[] args) { diff --git a/src/test/java/org/springframework/data/gemfire/config/annotation/EnableClusterDefinedRegionsUnitTests.java b/src/test/java/org/springframework/data/gemfire/config/annotation/EnableClusterDefinedRegionsUnitTests.java index 0d32cd0b..350b839b 100644 --- a/src/test/java/org/springframework/data/gemfire/config/annotation/EnableClusterDefinedRegionsUnitTests.java +++ b/src/test/java/org/springframework/data/gemfire/config/annotation/EnableClusterDefinedRegionsUnitTests.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.gemfire.config.annotation; import static org.assertj.core.api.Assertions.assertThat; @@ -24,11 +23,13 @@ import java.util.Collections; import java.util.Map; import org.apache.geode.cache.Cache; +import org.apache.geode.cache.GemFireCache; import org.apache.geode.cache.client.ClientCache; import org.apache.geode.cache.client.ClientRegionShortcut; import org.junit.Test; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.core.type.AnnotationMetadata; import org.springframework.data.gemfire.client.GemfireDataSourcePostProcessor; @@ -93,27 +94,33 @@ public class EnableClusterDefinedRegionsUnitTests { @Test public void configureGemfireDataSourcePostProcessor() { - ClientCache mockClientCache = mock(ClientCache.class); + ConfigurableBeanFactory mockBeanFactory = mock(ConfigurableBeanFactory.class); ClusterDefinedRegionsConfiguration configuration = new ClusterDefinedRegionsConfiguration(); + configuration.setBeanFactory(mockBeanFactory); configuration.setClientRegionShortcut(ClientRegionShortcut.CACHING_PROXY); - GemfireDataSourcePostProcessor postProcessor = configuration.gemfireDataSourcePostProcessor(mockClientCache); + GemfireDataSourcePostProcessor postProcessor = configuration.gemfireDataSourcePostProcessor(); + assertThat(postProcessor.getBeanFactory().orElse(null)).isEqualTo(mockBeanFactory); assertThat(postProcessor.getClientRegionShortcut().orElse(null)) .isEqualTo(ClientRegionShortcut.CACHING_PROXY); } @Test(expected = IllegalArgumentException.class) - public void configureGemfireDataSourcePostProcessorWithNullCache() { + public void configuresSpringApplicationWithGenericCache() { + + GemFireCache mockCache = mock(GemFireCache.class); try { - new ClusterDefinedRegionsConfiguration().gemfireDataSourcePostProcessor(null); + new ClusterDefinedRegionsConfiguration().nullCacheDependentBean(mockCache); } catch (IllegalArgumentException expected) { - assertThat(expected).hasMessage("GemFireCache must be an instance of ClientCache"); + assertThat(expected).hasMessage("GemFireCache [%s] must be a %s", + mockCache.getClass().getName(), ClientCache.class.getName()); + assertThat(expected).hasNoCause(); throw expected; @@ -121,17 +128,33 @@ public class EnableClusterDefinedRegionsUnitTests { } @Test(expected = IllegalArgumentException.class) - public void configureGemfireDataSourcePostProcessorWithPeerCache() { + public void configuresSpringApplicationWithNullCache() { try { - - Cache mockPeerCache = mock(Cache.class); - - new ClusterDefinedRegionsConfiguration().gemfireDataSourcePostProcessor(mockPeerCache); + new ClusterDefinedRegionsConfiguration().nullCacheDependentBean(null); } catch (IllegalArgumentException expected) { - assertThat(expected).hasMessage("GemFireCache must be an instance of ClientCache"); + assertThat(expected).hasMessage("GemFireCache [null] must be a %s", ClientCache.class.getName()); + assertThat(expected).hasNoCause(); + + throw expected; + } + } + + @Test(expected = IllegalArgumentException.class) + public void configuresSpringApplicationWithPeerCache() { + + Cache mockCache = mock(Cache.class); + + try { + new ClusterDefinedRegionsConfiguration().nullCacheDependentBean(mockCache); + } + catch (IllegalArgumentException expected) { + + assertThat(expected).hasMessage("GemFireCache [%s] must be a %s", + mockCache.getClass().getName(), ClientCache.class.getName()); + assertThat(expected).hasNoCause(); throw expected; diff --git a/src/test/resources/org/springframework/data/gemfire/repository/config/RepositoryClientRegionIntegrationTests-context.xml b/src/test/resources/org/springframework/data/gemfire/repository/config/RepositoryClientRegionIntegrationTests-context.xml index 35589ed2..1a2eb648 100644 --- a/src/test/resources/org/springframework/data/gemfire/repository/config/RepositoryClientRegionIntegrationTests-context.xml +++ b/src/test/resources/org/springframework/data/gemfire/repository/config/RepositoryClientRegionIntegrationTests-context.xml @@ -1,32 +1,34 @@ - - - - - - gemfire.log-level - warning - - - + + RepositoryClientRegionIntegrationTests + error + - - - + + + + + + +