From 5bfbb47eed28d1f87e39f3da9e20d06db54408f2 Mon Sep 17 00:00:00 2001 From: John Blum Date: Tue, 29 May 2018 17:27:41 -0700 Subject: [PATCH] Add annotation configuration support to set the Apache Geode/Pivotal GemFire distributed system member's name. --- .../annotation/MemberNameConfiguration.java | 109 ++++++++++++++++++ .../config/annotation/UseMemberName.java | 64 ++++++++++ ...mberNameConfigurationIntegrationTests.java | 63 ++++++++++ 3 files changed, 236 insertions(+) create mode 100644 geode-spring-boot-starter/src/main/java/org/springframework/geode/config/annotation/MemberNameConfiguration.java create mode 100644 geode-spring-boot-starter/src/main/java/org/springframework/geode/config/annotation/UseMemberName.java create mode 100644 geode-spring-boot-starter/src/test/java/org/springframework/geode/config/annotation/MemberNameConfigurationIntegrationTests.java diff --git a/geode-spring-boot-starter/src/main/java/org/springframework/geode/config/annotation/MemberNameConfiguration.java b/geode-spring-boot-starter/src/main/java/org/springframework/geode/config/annotation/MemberNameConfiguration.java new file mode 100644 index 00000000..6d06c566 --- /dev/null +++ b/geode-spring-boot-starter/src/main/java/org/springframework/geode/config/annotation/MemberNameConfiguration.java @@ -0,0 +1,109 @@ +/* + * Copyright 2018 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 + * + * http://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 java.lang.annotation.Annotation; +import java.util.Optional; + +import org.apache.geode.cache.Cache; +import org.apache.geode.cache.client.ClientCache; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.ImportAware; +import org.springframework.core.annotation.AnnotationAttributes; +import org.springframework.core.type.AnnotationMetadata; +import org.springframework.data.gemfire.CacheFactoryBean; +import org.springframework.data.gemfire.config.annotation.ClientCacheConfigurer; +import org.springframework.data.gemfire.config.annotation.PeerCacheConfigurer; +import org.springframework.data.gemfire.config.annotation.support.AbstractAnnotationConfigSupport; +import org.springframework.util.StringUtils; + +/** + * The {@link MemberNameConfiguration} class is a Spring {@link Configuration} class used to set + * an Apache Geode or Pivotal GemFire's name in the distributed system, whether the member + * is a {@link ClientCache client} in the client/server topology or a {@link Cache peer} member + * of the cluster. + * + * @author John Blum + * @see org.apache.geode.cache.Cache + * @see org.apache.geode.cache.client.ClientCache + * @see org.springframework.context.annotation.Bean + * @see org.springframework.context.annotation.Configuration + * @see org.springframework.context.annotation.ImportAware + * @see org.springframework.data.gemfire.config.annotation.ClientCacheConfigurer + * @see org.springframework.data.gemfire.config.annotation.PeerCacheConfigurer + * @see org.springframework.data.gemfire.config.annotation.support.AbstractAnnotationConfigSupport + * @see org.springframework.geode.config.annotation.UseMemberName + * @since 1.0.0 + */ +@Configuration +@SuppressWarnings("unused") +public class MemberNameConfiguration extends AbstractAnnotationConfigSupport implements ImportAware { + + private static final String GEMFIRE_NAME_PROPERTY = "name"; + + private String memberName; + + @Override + protected Class getAnnotationType() { + return UseMemberName.class; + } + + @Override + public void setImportMetadata(AnnotationMetadata importMetadata) { + + if (isAnnotationPresent(importMetadata)) { + + AnnotationAttributes memberNameAttributes = getAnnotationAttributes(importMetadata); + + setMemberNameIfNotSet(memberNameAttributes.containsKey("name") + ? memberNameAttributes.getString("name") : null); + + setMemberNameIfNotSet(memberNameAttributes.containsKey("value") + ? memberNameAttributes.getString("value") : null); + } + } + + protected void setMemberName(String memberName) { + this.memberName = memberName; + } + + protected void setMemberNameIfNotSet(String memberName) { + setMemberName(this.memberName != null ? this.memberName : memberName); + } + + protected Optional getMemberName() { + + return Optional.ofNullable(this.memberName) + .filter(StringUtils::hasText); + } + + @Bean + ClientCacheConfigurer clientCacheMemberNameConfigurer() { + return (beaName, clientCacheFactoryBean) -> configureMemberName(clientCacheFactoryBean); + } + + @Bean + PeerCacheConfigurer peerCacheMemberNameConfigurer() { + return (beaName, peerCacheFactoryBean) -> configureMemberName(peerCacheFactoryBean); + } + + private void configureMemberName(CacheFactoryBean cacheFactoryBean) { + getMemberName().ifPresent(memberName -> + cacheFactoryBean.getProperties().setProperty(GEMFIRE_NAME_PROPERTY, memberName)); + } +} diff --git a/geode-spring-boot-starter/src/main/java/org/springframework/geode/config/annotation/UseMemberName.java b/geode-spring-boot-starter/src/main/java/org/springframework/geode/config/annotation/UseMemberName.java new file mode 100644 index 00000000..bd985b03 --- /dev/null +++ b/geode-spring-boot-starter/src/main/java/org/springframework/geode/config/annotation/UseMemberName.java @@ -0,0 +1,64 @@ +/* + * Copyright 2018 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 + * + * http://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 java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.apache.geode.cache.Cache; +import org.apache.geode.cache.client.ClientCache; +import org.springframework.context.annotation.Import; +import org.springframework.core.annotation.AliasFor; + +/** + * The {@link UseMemberName} annotation configures the {@literal name} of the member in the Apache Geode + * or Pivotal GemFire distributed system, whether the member is a {@link ClientCache client} in + * the client/server topology or a {@link Cache peer} member of the cluster. + * + * @author John Blum + * @see org.apache.geode.cache.Cache + * @see org.apache.geode.cache.client.ClientCache + * @see org.springframework.context.annotation.Import + * @see org.springframework.geode.config.annotation.MemberNameConfiguration + * @since 1.0.0 + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Inherited +@Documented +@Import(MemberNameConfiguration.class) +public @interface UseMemberName { + + /** + * {@link String Name} used for the Apache Geode/Pivotal GemFire distributed system member. + * @see #name() + */ + @AliasFor("name") + String value() default ""; + + /** + * Alias for the {@link String name} of the Apache Geode/Pivotal GemFire distributed system member. + * @see #value() + */ + @AliasFor("value") + String name() default ""; + +} diff --git a/geode-spring-boot-starter/src/test/java/org/springframework/geode/config/annotation/MemberNameConfigurationIntegrationTests.java b/geode-spring-boot-starter/src/test/java/org/springframework/geode/config/annotation/MemberNameConfigurationIntegrationTests.java new file mode 100644 index 00000000..e7122bf4 --- /dev/null +++ b/geode-spring-boot-starter/src/test/java/org/springframework/geode/config/annotation/MemberNameConfigurationIntegrationTests.java @@ -0,0 +1,63 @@ +/* + * Copyright 2018 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 + * + * http://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 org.apache.geode.cache.GemFireCache; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.gemfire.config.annotation.ClientCacheApplication; +import org.springframework.data.gemfire.tests.mock.annotation.EnableGemFireMockObjects; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +/** + * Integration tests for {@link UseMemberName} and {@link MemberNameConfiguration}. + * + * @author John Blum + * @see org.springframework.data.gemfire.config.annotation.ClientCacheApplication + * @see org.springframework.data.gemfire.tests.mock.annotation.EnableGemFireMockObjects + * @see org.springframework.test.context.ContextConfiguration + * @see org.springframework.test.context.junit4.SpringRunner + * @since 1.0.0 + */ +@RunWith(SpringRunner.class) +@ContextConfiguration +@SuppressWarnings("unused") +public class MemberNameConfigurationIntegrationTests { + + @Autowired + private GemFireCache gemfireCache; + + @Test + public void memberNameIsCorrect() { + + assertThat(this.gemfireCache).isNotNull(); + assertThat(this.gemfireCache.getDistributedSystem()).isNotNull(); + assertThat(this.gemfireCache.getDistributedSystem().getProperties()).isNotNull(); + assertThat(this.gemfireCache.getDistributedSystem().getProperties().getProperty("name")) + .isEqualTo("TestClient"); + } + + @ClientCacheApplication + @EnableGemFireMockObjects + @UseMemberName("TestClient") + static class TestConfiguration { } + +}