From 82e18ae88f7e40c1ce9f31a66a632765d0a7b7d7 Mon Sep 17 00:00:00 2001 From: Rafal Leszko Date: Tue, 16 Apr 2019 12:48:11 -0400 Subject: [PATCH] Add support for Hazelcast YAML configuration Since Hazlecast 3.12, YAML configuration format is supported in addition to XML. Therefore, this change makes Spring Boot automatically discover not only `hazelcast.xml` (and `hazelcast-client.xml`), but also `hazelcast.yaml` (and `hazelcast-client.yaml`). See gh-16632 --- .../HazelcastClientConfiguration.java | 3 +- .../hazelcast/HazelcastClientFactory.java | 10 ++- .../hazelcast/HazelcastInstanceFactory.java | 11 ++- .../HazelcastServerConfiguration.java | 3 +- ...HazelcastAutoConfigurationClientTests.java | 77 ++++++++++++------- ...HazelcastAutoConfigurationServerTests.java | 70 ++++++++++------- .../HazelcastAutoConfigurationTests.java | 2 + .../src/test/resources/hazelcast.yaml | 5 ++ .../hazelcast/hazelcast-client-specific.xml | 3 + .../hazelcast/hazelcast-client-specific.yaml | 3 + .../hazelcast/hazelcast-specific.yaml | 10 +++ 11 files changed, 141 insertions(+), 56 deletions(-) create mode 100644 spring-boot-project/spring-boot-autoconfigure/src/test/resources/hazelcast.yaml create mode 100644 spring-boot-project/spring-boot-autoconfigure/src/test/resources/org/springframework/boot/autoconfigure/hazelcast/hazelcast-client-specific.yaml create mode 100644 spring-boot-project/spring-boot-autoconfigure/src/test/resources/org/springframework/boot/autoconfigure/hazelcast/hazelcast-specific.yaml diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastClientConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastClientConfiguration.java index d0bfc57888..6d5ccf9165 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastClientConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastClientConfiguration.java @@ -79,7 +79,8 @@ class HazelcastClientConfiguration { ConfigAvailableCondition() { super(CONFIG_SYSTEM_PROPERTY, "file:./hazelcast-client.xml", - "classpath:/hazelcast-client.xml"); + "classpath:/hazelcast-client.xml", "file:./hazelcast-client.yaml", + "classpath:/hazelcast-client.yaml"); } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastClientFactory.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastClientFactory.java index 77a197b2ef..b8f9e3d3cf 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastClientFactory.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastClientFactory.java @@ -22,6 +22,7 @@ import java.net.URL; import com.hazelcast.client.HazelcastClient; import com.hazelcast.client.config.ClientConfig; import com.hazelcast.client.config.XmlClientConfigBuilder; +import com.hazelcast.client.config.YamlClientConfigBuilder; import com.hazelcast.core.HazelcastInstance; import org.springframework.core.io.Resource; @@ -59,7 +60,14 @@ public class HazelcastClientFactory { private ClientConfig getClientConfig(Resource clientConfigLocation) throws IOException { URL configUrl = clientConfigLocation.getURL(); - return new XmlClientConfigBuilder(configUrl).build(); + String configFileName = configUrl.getFile(); + + if (configFileName.endsWith(".xml")) { + return new XmlClientConfigBuilder(configUrl).build(); + } + else { + return new YamlClientConfigBuilder(configUrl).build(); + } } /** diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastInstanceFactory.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastInstanceFactory.java index 67430d09e6..551dcc29eb 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastInstanceFactory.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastInstanceFactory.java @@ -21,6 +21,7 @@ import java.net.URL; import com.hazelcast.config.Config; import com.hazelcast.config.XmlConfigBuilder; +import com.hazelcast.config.YamlConfigBuilder; import com.hazelcast.core.Hazelcast; import com.hazelcast.core.HazelcastInstance; @@ -61,7 +62,7 @@ public class HazelcastInstanceFactory { private Config getConfig(Resource configLocation) throws IOException { URL configUrl = configLocation.getURL(); - Config config = new XmlConfigBuilder(configUrl).build(); + Config config = createConfig(configUrl); if (ResourceUtils.isFileURL(configUrl)) { config.setConfigurationFile(configLocation.getFile()); } @@ -71,6 +72,14 @@ public class HazelcastInstanceFactory { return config; } + private static Config createConfig(URL configUrl) throws IOException { + String configFileName = configUrl.getFile(); + if (configFileName.endsWith(".xml")) { + return new XmlConfigBuilder(configUrl).build(); + } + return new YamlConfigBuilder(configUrl).build(); + } + /** * Get the {@link HazelcastInstance}. * @return the {@link HazelcastInstance} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastServerConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastServerConfiguration.java index 0ddf5fa158..2432a7f92d 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastServerConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastServerConfiguration.java @@ -77,7 +77,8 @@ class HazelcastServerConfiguration { ConfigAvailableCondition() { super(CONFIG_SYSTEM_PROPERTY, "file:./hazelcast.xml", - "classpath:/hazelcast.xml"); + "classpath:/hazelcast.xml", "file:./hazelcast.yaml", + "classpath:/hazelcast.yaml"); } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfigurationClientTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfigurationClientTests.java index 519247259e..735a1b7ed1 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfigurationClientTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfigurationClientTests.java @@ -28,6 +28,7 @@ import org.junit.Test; import org.springframework.beans.factory.BeanCreationException; import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.test.context.assertj.AssertableApplicationContext; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -63,35 +64,58 @@ public class HazelcastAutoConfigurationClientTests { .withConfiguration(AutoConfigurations.of(HazelcastAutoConfiguration.class)); @Test - public void systemProperty() { - this.contextRunner - .withSystemProperties(HazelcastClientConfiguration.CONFIG_SYSTEM_PROPERTY - + "=classpath:org/springframework/boot/autoconfigure/hazelcast/" - + "hazelcast-client-specific.xml") - .run((context) -> assertThat(context).getBean(HazelcastInstance.class) - .isInstanceOf(HazelcastInstance.class) - .has(nameStartingWith("hz.client_"))); + public void systemPropertyWithXml() { + systemProperty(HazelcastClientConfiguration.CONFIG_SYSTEM_PROPERTY + + "=classpath:org/springframework/boot/autoconfigure/hazelcast/" + + "hazelcast-client-specific.xml"); } @Test - public void explicitConfigFile() { - this.contextRunner - .withPropertyValues( - "spring.hazelcast.config=org/springframework/boot/autoconfigure/" - + "hazelcast/hazelcast-client-specific.xml") - .run((context) -> assertThat(context).getBean(HazelcastInstance.class) - .isInstanceOf(HazelcastClientProxy.class) - .has(nameStartingWith("hz.client_"))); + public void systemPropertyWithYaml() { + systemProperty(HazelcastClientConfiguration.CONFIG_SYSTEM_PROPERTY + + "=classpath:org/springframework/boot/autoconfigure/hazelcast/" + + "hazelcast-client-specific.yaml"); + } + + private void systemProperty(String systemProperty) { + this.contextRunner.withSystemProperties(systemProperty) + .run((context) -> assertHazelcastClientSpecific(context)); } @Test - public void explicitConfigUrl() { - this.contextRunner - .withPropertyValues( - "spring.hazelcast.config=hazelcast-client-default.xml") - .run((context) -> assertThat(context).getBean(HazelcastInstance.class) - .isInstanceOf(HazelcastClientProxy.class) - .has(nameStartingWith("hz.client_"))); + public void explicitConfigFileWithXml() { + propertyValues("spring.hazelcast.config=org/springframework/boot/autoconfigure/" + + "hazelcast/hazelcast-client-specific.xml"); + } + + @Test + public void explicitConfigFileWithYaml() { + propertyValues("spring.hazelcast.config=org/springframework/boot/autoconfigure/" + + "hazelcast/hazelcast-client-specific.yaml"); + } + + @Test + public void explicitConfigUrlWithXml() { + propertyValues("spring.hazelcast.config=classpath:org/springframework/" + + "boot/autoconfigure/hazelcast/hazelcast-client-specific.xml"); + } + + @Test + public void explicitConfigUrlWithYaml() { + propertyValues("spring.hazelcast.config=classpath:org/springframework/" + + "boot/autoconfigure/hazelcast/hazelcast-client-specific.yaml"); + } + + private void propertyValues(String propertyValues) { + this.contextRunner.withPropertyValues(propertyValues) + .run((context) -> assertHazelcastClientSpecific(context)); + } + + private static void assertHazelcastClientSpecific( + AssertableApplicationContext context) { + assertThat(context).getBean(HazelcastInstance.class) + .isInstanceOf(HazelcastInstance.class) + .has(labelEqualTo("configured-client")); } @Test @@ -111,9 +135,10 @@ public class HazelcastAutoConfigurationClientTests { .isInstanceOf(HazelcastClientProxy.class)); } - private Condition nameStartingWith(String prefix) { - return new Condition<>((o) -> o.getName().startsWith(prefix), - "Name starts with " + prefix); + private static Condition labelEqualTo(String label) { + return new Condition<>((o) -> ((HazelcastClientProxy) o).getClientConfig() + .getLabels().stream().anyMatch((e) -> e.equals(label)), + "Label equals to " + label); } @Configuration(proxyBeanMethods = false) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfigurationServerTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfigurationServerTests.java index 693807a7f3..e5fadb8e96 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfigurationServerTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfigurationServerTests.java @@ -27,6 +27,7 @@ import org.junit.runner.RunWith; import org.springframework.beans.factory.BeanCreationException; import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.test.context.assertj.AssertableApplicationContext; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.testsupport.runner.classpath.ClassPathExclusions; import org.springframework.boot.testsupport.runner.classpath.ModifiedClassPathRunner; @@ -59,39 +60,56 @@ public class HazelcastAutoConfigurationServerTests { } @Test - public void systemProperty() { - this.contextRunner - .withSystemProperties(HazelcastServerConfiguration.CONFIG_SYSTEM_PROPERTY - + "=classpath:org/springframework/boot/autoconfigure/hazelcast/hazelcast-specific.xml") - .run((context) -> { - Config config = context.getBean(HazelcastInstance.class).getConfig(); - assertThat(config.getQueueConfigs().keySet()).containsOnly("foobar"); - }); + public void systemPropertyWithXml() { + systemProperty(HazelcastServerConfiguration.CONFIG_SYSTEM_PROPERTY + + "=classpath:org/springframework/boot/autoconfigure/hazelcast/hazelcast-specific.xml"); + } + + @Test + public void systemPropertyWithYaml() { + systemProperty(HazelcastServerConfiguration.CONFIG_SYSTEM_PROPERTY + + "=classpath:org/springframework/boot/autoconfigure/hazelcast/hazelcast-specific.yaml"); + } + + private void systemProperty(String systemProperties) { + this.contextRunner.withSystemProperties(systemProperties) + .run((context) -> assertHazelcastSpecific(context)); } @Test - public void explicitConfigFile() { - this.contextRunner.withPropertyValues( + public void explicitConfigFileWithXml() { + propertyValues( "spring.hazelcast.config=org/springframework/boot/autoconfigure/hazelcast/" - + "hazelcast-specific.xml") - .run((context) -> { - Config config = context.getBean(HazelcastInstance.class).getConfig(); - assertThat(config.getConfigurationFile()) - .isEqualTo(new ClassPathResource( - "org/springframework/boot/autoconfigure/hazelcast" - + "/hazelcast-specific.xml").getFile()); - }); + + "hazelcast-specific.xml"); } @Test - public void explicitConfigUrl() { - this.contextRunner - .withPropertyValues("spring.hazelcast.config=hazelcast-default.xml") - .run((context) -> { - Config config = context.getBean(HazelcastInstance.class).getConfig(); - assertThat(config.getConfigurationUrl()).isEqualTo( - new ClassPathResource("hazelcast-default.xml").getURL()); - }); + public void explicitConfigFileWithYaml() { + propertyValues( + "spring.hazelcast.config=org/springframework/boot/autoconfigure/hazelcast/" + + "hazelcast-specific.yaml"); + } + + @Test + public void explicitConfigUrlWithXml() { + propertyValues("spring.hazelcast.config=classpath:org/springframework/" + + "boot/autoconfigure/hazelcast/hazelcast-specific.xml"); + } + + @Test + public void explicitConfigUrlWithYaml() { + propertyValues("spring.hazelcast.config=classpath:org/springframework/" + + "boot/autoconfigure/hazelcast/hazelcast-specific.yaml"); + } + + private void propertyValues(String propertyValues) { + this.contextRunner.withPropertyValues(propertyValues) + .run((context) -> assertHazelcastSpecific(context)); + } + + private static void assertHazelcastSpecific(AssertableApplicationContext context) { + Config config = context.getBean(HazelcastInstance.class).getConfig(); + assertThat(config.getMapConfigs().keySet()).containsOnly("foobar"); } @Test diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfigurationTests.java index 7337cadb63..a80b8bd2f7 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfigurationTests.java @@ -39,6 +39,8 @@ public class HazelcastAutoConfigurationTests { @Test public void defaultConfigFile() { // no hazelcast-client.xml and hazelcast.xml is present in root classpath + // this also asserts that XML has priority over YAML + // as both hazelcast.yaml and hazelcast.xml in test classpath. this.contextRunner.run((context) -> { Config config = context.getBean(HazelcastInstance.class).getConfig(); assertThat(config.getConfigurationUrl()) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/resources/hazelcast.yaml b/spring-boot-project/spring-boot-autoconfigure/src/test/resources/hazelcast.yaml new file mode 100644 index 0000000000..1616ba2e78 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/resources/hazelcast.yaml @@ -0,0 +1,5 @@ +hazelcast: + network: + join: + multicast: + enabled: false diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/resources/org/springframework/boot/autoconfigure/hazelcast/hazelcast-client-specific.xml b/spring-boot-project/spring-boot-autoconfigure/src/test/resources/org/springframework/boot/autoconfigure/hazelcast/hazelcast-client-specific.xml index 854d7d91a6..d7201e1162 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/resources/org/springframework/boot/autoconfigure/hazelcast/hazelcast-client-specific.xml +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/resources/org/springframework/boot/autoconfigure/hazelcast/hazelcast-client-specific.xml @@ -2,5 +2,8 @@ + + + diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/resources/org/springframework/boot/autoconfigure/hazelcast/hazelcast-client-specific.yaml b/spring-boot-project/spring-boot-autoconfigure/src/test/resources/org/springframework/boot/autoconfigure/hazelcast/hazelcast-client-specific.yaml new file mode 100644 index 0000000000..af2e67bc18 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/resources/org/springframework/boot/autoconfigure/hazelcast/hazelcast-client-specific.yaml @@ -0,0 +1,3 @@ +hazelcast-client: + client-labels: + - configured-client diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/resources/org/springframework/boot/autoconfigure/hazelcast/hazelcast-specific.yaml b/spring-boot-project/spring-boot-autoconfigure/src/test/resources/org/springframework/boot/autoconfigure/hazelcast/hazelcast-specific.yaml new file mode 100644 index 0000000000..614e99777a --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/resources/org/springframework/boot/autoconfigure/hazelcast/hazelcast-specific.yaml @@ -0,0 +1,10 @@ +hazelcast: + network: + join: + multicast: + enabled: false + + map: + foobar: + time-to-live-seconds: 3600 + max-idle-seconds: 600