From 4eff04c5176d4c357ddb63c1eaf232f53af75336 Mon Sep 17 00:00:00 2001 From: John Blum Date: Tue, 24 Sep 2019 00:01:42 -0700 Subject: [PATCH] Refactor Cluster-aware Conditions to be CloudFoundry Environment-aware. Resolves gh-56. --- .../ContinuousQueryAutoConfiguration.java | 4 +- .../ClusterAvailableConfiguration.java | 23 ++++- .../ClusterNotAvailableConfiguration.java | 31 +++++- ...vailableConfigurationIntegrationTests.java | 98 +++++++++++++++++++ 4 files changed, 151 insertions(+), 5 deletions(-) create mode 100644 spring-geode/src/test/java/org/springframework/geode/config/annotation/CloudFoundryClusterAvailableConfigurationIntegrationTests.java diff --git a/spring-geode-autoconfigure/src/main/java/org/springframework/geode/boot/autoconfigure/ContinuousQueryAutoConfiguration.java b/spring-geode-autoconfigure/src/main/java/org/springframework/geode/boot/autoconfigure/ContinuousQueryAutoConfiguration.java index 80d3e405..1df975de 100644 --- a/spring-geode-autoconfigure/src/main/java/org/springframework/geode/boot/autoconfigure/ContinuousQueryAutoConfiguration.java +++ b/spring-geode-autoconfigure/src/main/java/org/springframework/geode/boot/autoconfigure/ContinuousQueryAutoConfiguration.java @@ -43,11 +43,11 @@ import org.springframework.geode.config.annotation.ClusterAvailableConfiguration * @see org.springframework.data.gemfire.config.annotation.ClientCacheConfigurer * @see org.springframework.data.gemfire.config.annotation.EnableContinuousQueries * @see org.springframework.geode.boot.autoconfigure.support.EnableSubscriptionConfiguration - * @see org.springframework.geode.config.annotation.ClusterAvailableConfiguration.ClusterAvailableCondition + * @see org.springframework.geode.config.annotation.ClusterAvailableConfiguration.AnyClusterAvailableCondition * @since 1.0.0 */ @Configuration -@Conditional(ClusterAvailableConfiguration.ClusterAvailableCondition.class) +@Conditional(ClusterAvailableConfiguration.AnyClusterAvailableCondition.class) @ConditionalOnBean(ClientCacheFactoryBean.class) @ConditionalOnMissingBean(name = "continuousQueryBeanPostProcessor", type = "org.springframework.data.gemfire.listener.ContinuousQueryListenerContainer") diff --git a/spring-geode/src/main/java/org/springframework/geode/config/annotation/ClusterAvailableConfiguration.java b/spring-geode/src/main/java/org/springframework/geode/config/annotation/ClusterAvailableConfiguration.java index bbb7d57d..260484ce 100644 --- a/spring-geode/src/main/java/org/springframework/geode/config/annotation/ClusterAvailableConfiguration.java +++ b/spring-geode/src/main/java/org/springframework/geode/config/annotation/ClusterAvailableConfiguration.java @@ -15,6 +15,9 @@ */ package org.springframework.geode.config.annotation; +import org.springframework.boot.autoconfigure.condition.AnyNestedCondition; +import org.springframework.boot.autoconfigure.condition.ConditionalOnCloudPlatform; +import org.springframework.boot.cloud.CloudPlatform; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.data.gemfire.config.annotation.EnableClusterConfiguration; @@ -24,16 +27,34 @@ import org.springframework.data.gemfire.config.annotation.EnableClusterConfigura * configuration when an Apache Geode or Pivotal GemFire cluster of servers are available. * * @author John Blum + * @see org.springframework.boot.autoconfigure.condition.AnyNestedCondition + * @see org.springframework.boot.autoconfigure.condition.ConditionalOnCloudPlatform + * @see org.springframework.boot.cloud.CloudPlatform * @see org.springframework.context.annotation.Conditional * @see org.springframework.context.annotation.Configuration * @see org.springframework.data.gemfire.config.annotation.EnableClusterConfiguration * @since 1.2.0 */ @Configuration -@Conditional(ClusterAvailableConfiguration.ClusterAvailableCondition.class) +@Conditional(ClusterAvailableConfiguration.AnyClusterAvailableCondition.class) @EnableClusterConfiguration(requireHttps = false, useHttp = true) +@SuppressWarnings("unused") public class ClusterAvailableConfiguration { + public static final class AnyClusterAvailableCondition extends AnyNestedCondition { + + public AnyClusterAvailableCondition() { + super(ConfigurationPhase.PARSE_CONFIGURATION); + } + + @ConditionalOnCloudPlatform(CloudPlatform.CLOUD_FOUNDRY) + static class IsCloudFoundryEnvironmentCondition { } + + @Conditional(ClusterAvailableCondition.class) + static class IsClusterAvailableCondition { } + + } + public static final class ClusterAvailableCondition extends ClusterAwareConfiguration.ClusterAwareCondition { } } diff --git a/spring-geode/src/main/java/org/springframework/geode/config/annotation/ClusterNotAvailableConfiguration.java b/spring-geode/src/main/java/org/springframework/geode/config/annotation/ClusterNotAvailableConfiguration.java index 9436a840..5d9f3f72 100644 --- a/spring-geode/src/main/java/org/springframework/geode/config/annotation/ClusterNotAvailableConfiguration.java +++ b/spring-geode/src/main/java/org/springframework/geode/config/annotation/ClusterNotAvailableConfiguration.java @@ -22,7 +22,10 @@ import org.apache.geode.cache.client.ClientRegionShortcut; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.boot.autoconfigure.condition.AllNestedConditions; +import org.springframework.boot.cloud.CloudPlatform; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; @@ -38,6 +41,8 @@ import org.springframework.lang.Nullable; * * @author John Blum * @see org.springframework.beans.factory.config.BeanPostProcessor + * @see org.springframework.boot.autoconfigure.condition.AllNestedConditions + * @see org.springframework.boot.cloud.CloudPlatform * @see org.springframework.context.annotation.Bean * @see org.springframework.context.annotation.Conditional * @see org.springframework.context.annotation.Configuration @@ -47,7 +52,7 @@ import org.springframework.lang.Nullable; * @since 1.2.0 */ @Configuration -@Conditional(ClusterNotAvailableConfiguration.CusterNotAvailableCondition.class) +@Conditional(ClusterNotAvailableConfiguration.AllClusterNotAvailableConditions.class) @SuppressWarnings("unused") public class ClusterNotAvailableConfiguration { @@ -97,11 +102,33 @@ public class ClusterNotAvailableConfiguration { return clientRegion; } - public static final class CusterNotAvailableCondition extends ClusterAwareConfiguration.ClusterAwareCondition { + public static final class AllClusterNotAvailableConditions extends AllNestedConditions { + + public AllClusterNotAvailableConditions() { + super(ConfigurationPhase.PARSE_CONFIGURATION); + } + + @Conditional(ClusterNotAvailableCondition.class) + static class IsClusterNotAvailableCondition { } + + @Conditional(NotCloudFoundryEnvironmentCondition.class) + static class IsNotCloudFoundryEnvironmentCondition { } + + } + + public static final class ClusterNotAvailableCondition extends ClusterAwareConfiguration.ClusterAwareCondition { @Override public synchronized boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { return !super.matches(context, metadata); } } + + public static final class NotCloudFoundryEnvironmentCondition implements Condition { + + @Override + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + return !CloudPlatform.CLOUD_FOUNDRY.isActive(context.getEnvironment()); + } + } } diff --git a/spring-geode/src/test/java/org/springframework/geode/config/annotation/CloudFoundryClusterAvailableConfigurationIntegrationTests.java b/spring-geode/src/test/java/org/springframework/geode/config/annotation/CloudFoundryClusterAvailableConfigurationIntegrationTests.java new file mode 100644 index 00000000..d2308aba --- /dev/null +++ b/spring-geode/src/test/java/org/springframework/geode/config/annotation/CloudFoundryClusterAvailableConfigurationIntegrationTests.java @@ -0,0 +1,98 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ +package org.springframework.geode.config.annotation; + +import static org.assertj.core.api.Assertions.assertThat; + +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.ClientRegionShortcut; + +import org.junit.AfterClass; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Bean; +import org.springframework.data.gemfire.client.ClientRegionFactoryBean; +import org.springframework.data.gemfire.config.annotation.ClientCacheApplication; +import org.springframework.data.gemfire.tests.integration.IntegrationTestsSupport; +import org.springframework.data.gemfire.tests.mock.annotation.EnableGemFireMockObjects; +import org.springframework.test.context.junit4.SpringRunner; + +/** + * Integration Tests for {@link EnableClusterAware} and {@link ClusterAvailableConfiguration.ClusterAvailableCondition} + * specifically when the Spring Boot application is run in CloudFoundry. + * + * @author John Blum + * @see org.junit.Test + * @see org.apache.geode.cache.DataPolicy + * @see org.apache.geode.cache.GemFireCache + * @see org.apache.geode.cache.Region + * @see org.springframework.boot.test.context.SpringBootTest + * @see org.springframework.context.annotation.Bean + * @see org.springframework.data.gemfire.client.ClientRegionFactoryBean + * @see org.springframework.data.gemfire.config.annotation.ClientCacheApplication + * @see org.springframework.data.gemfire.tests.integration.IntegrationTestsSupport + * @see org.springframework.data.gemfire.tests.mock.annotation.EnableGemFireMockObjects + * @see org.springframework.test.context.junit4.SpringRunner + * @since 1.2.0 + */ +@RunWith(SpringRunner.class) +@SpringBootTest( + webEnvironment = SpringBootTest.WebEnvironment.NONE, + properties = "VCAP_APPLICATION = {}" +) +@SuppressWarnings("unused") +public class CloudFoundryClusterAvailableConfigurationIntegrationTests extends IntegrationTestsSupport { + + @AfterClass + public static void tearDown() { + ClusterAwareConfiguration.ClusterAwareCondition.reset(); + } + + @Resource(name = "Example") + private Region example; + + @Test + public void exampleRegionConfigurationIsCorrect() { + + assertThat(this.example).isNotNull(); + assertThat(this.example.getName()).isEqualTo("Example"); + assertThat(this.example.getAttributes()).isNotNull(); + assertThat(this.example.getAttributes().getDataPolicy()).isEqualTo(DataPolicy.EMPTY); + } + + @EnableClusterAware + @EnableGemFireMockObjects + @ClientCacheApplication(name = "CloudFoundryClusterAvailableConfigurationIntegrationTests") + static class TestGeodeConfiguration { + + @Bean("Example") + public ClientRegionFactoryBean exampleRegion(GemFireCache gemfireCache) { + + ClientRegionFactoryBean exampleRegion = new ClientRegionFactoryBean<>(); + + exampleRegion.setCache(gemfireCache); + exampleRegion.setShortcut(ClientRegionShortcut.PROXY); + + return exampleRegion; + } + } +}