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..d9535eabbf 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 @@ -1,5 +1,5 @@ /* - * Copyright 2012-2017 the original author or authors. + * Copyright 2012-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. @@ -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,6 +60,10 @@ public class HazelcastClientFactory { private ClientConfig getClientConfig(Resource clientConfigLocation) throws IOException { URL configUrl = clientConfigLocation.getURL(); + String configFileName = configUrl.getPath(); + if (configFileName.endsWith(".yaml")) { + return new YamlClientConfigBuilder(configUrl).build(); + } return new XmlClientConfigBuilder(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..be66d2dffb 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 @@ -1,5 +1,5 @@ /* - * Copyright 2012-2017 the original author or authors. + * Copyright 2012-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. @@ -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.getPath(); + if (configFileName.endsWith(".yaml")) { + return new YamlConfigBuilder(configUrl).build(); + } + return new XmlConfigBuilder(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..c45aed9163 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,7 +28,9 @@ 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.boot.test.context.runner.ContextConsumer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -63,35 +65,55 @@ public class HazelcastAutoConfigurationClientTests { .withConfiguration(AutoConfigurations.of(HazelcastAutoConfiguration.class)); @Test - public void systemProperty() { + public void systemPropertyWithXml() { 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_"))); + .run(assertSpecificHazelcastClient("explicit-xml")); } @Test - public void explicitConfigFile() { + public void systemPropertyWithYaml() { + this.contextRunner + .withSystemProperties(HazelcastClientConfiguration.CONFIG_SYSTEM_PROPERTY + + "=classpath:org/springframework/boot/autoconfigure/hazelcast/" + + "hazelcast-client-specific.yaml") + .run(assertSpecificHazelcastClient("explicit-yaml")); + } + + @Test + public void explicitConfigFileWithXml() { 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_"))); + .run(assertSpecificHazelcastClient("explicit-xml")); } @Test - public void explicitConfigUrl() { + public void explicitConfigFileWithYaml() { this.contextRunner .withPropertyValues( - "spring.hazelcast.config=hazelcast-client-default.xml") - .run((context) -> assertThat(context).getBean(HazelcastInstance.class) - .isInstanceOf(HazelcastClientProxy.class) - .has(nameStartingWith("hz.client_"))); + "spring.hazelcast.config=org/springframework/boot/autoconfigure/" + + "hazelcast/hazelcast-client-specific.yaml") + .run(assertSpecificHazelcastClient("explicit-yaml")); + } + + @Test + public void explicitConfigUrlWithXml() { + this.contextRunner.withPropertyValues( + "spring.hazelcast.config=classpath:org/springframework/" + + "boot/autoconfigure/hazelcast/hazelcast-client-specific.xml") + .run(assertSpecificHazelcastClient("explicit-xml")); + } + + @Test + public void explicitConfigUrlWithYaml() { + this.contextRunner.withPropertyValues( + "spring.hazelcast.config=classpath:org/springframework/" + + "boot/autoconfigure/hazelcast/hazelcast-client-specific.yaml") + .run(assertSpecificHazelcastClient("explicit-yaml")); } @Test @@ -111,9 +133,16 @@ public class HazelcastAutoConfigurationClientTests { .isInstanceOf(HazelcastClientProxy.class)); } - private Condition nameStartingWith(String prefix) { - return new Condition<>((o) -> o.getName().startsWith(prefix), - "Name starts with " + prefix); + private ContextConsumer assertSpecificHazelcastClient( + String label) { + return (context) -> assertThat(context).getBean(HazelcastInstance.class) + .isInstanceOf(HazelcastInstance.class).has(labelEqualTo(label)); + } + + 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..bf7ba98659 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,7 +27,9 @@ 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.test.context.runner.ContextConsumer; import org.springframework.boot.testsupport.runner.classpath.ClassPathExclusions; import org.springframework.boot.testsupport.runner.classpath.ModifiedClassPathRunner; import org.springframework.context.annotation.Bean; @@ -59,39 +61,71 @@ public class HazelcastAutoConfigurationServerTests { } @Test - public void systemProperty() { + public void systemPropertyWithXml() { 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"); + assertThat(config.getMapConfigs().keySet()).containsOnly("foobar"); }); } @Test - public void explicitConfigFile() { - this.contextRunner.withPropertyValues( - "spring.hazelcast.config=org/springframework/boot/autoconfigure/hazelcast/" - + "hazelcast-specific.xml") + public void systemPropertyWithYaml() { + this.contextRunner + .withSystemProperties(HazelcastServerConfiguration.CONFIG_SYSTEM_PROPERTY + + "=classpath:org/springframework/boot/autoconfigure/hazelcast/hazelcast-specific.yaml") .run((context) -> { Config config = context.getBean(HazelcastInstance.class).getConfig(); - assertThat(config.getConfigurationFile()) - .isEqualTo(new ClassPathResource( - "org/springframework/boot/autoconfigure/hazelcast" - + "/hazelcast-specific.xml").getFile()); + assertThat(config.getMapConfigs().keySet()).containsOnly("foobar"); }); } @Test - public void explicitConfigUrl() { + public void explicitConfigFileWithXml() { + this.contextRunner.withPropertyValues( + "spring.hazelcast.config=org/springframework/boot/autoconfigure/hazelcast/" + + "hazelcast-specific.xml") + .run(assertSpecificHazelcastServer( + "org/springframework/boot/autoconfigure/hazelcast/hazelcast-specific.xml")); + } + + @Test + public void explicitConfigFileWithYaml() { + this.contextRunner.withPropertyValues( + "spring.hazelcast.config=org/springframework/boot/autoconfigure/hazelcast/" + + "hazelcast-specific.yaml") + .run(assertSpecificHazelcastServer( + "org/springframework/boot/autoconfigure/hazelcast/hazelcast-specific.yaml")); + } + + @Test + public void explicitConfigUrlWithXml() { 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()); - }); + .withPropertyValues( + "spring.hazelcast.config=classpath:org/springframework/" + + "boot/autoconfigure/hazelcast/hazelcast-specific.xml") + .run(assertSpecificHazelcastServer( + "org/springframework/boot/autoconfigure/hazelcast/hazelcast-specific.xml")); + } + + @Test + public void explicitConfigUrlWithYaml() { + this.contextRunner + .withPropertyValues( + "spring.hazelcast.config=classpath:org/springframework/" + + "boot/autoconfigure/hazelcast/hazelcast-specific.yaml") + .run(assertSpecificHazelcastServer( + "org/springframework/boot/autoconfigure/hazelcast/hazelcast-specific.yaml")); + } + + private ContextConsumer assertSpecificHazelcastServer( + String location) { + return (context) -> { + Config config = context.getBean(HazelcastInstance.class).getConfig(); + assertThat(config.getConfigurationUrl()).asString().endsWith(location); + }; } @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..f73061c489 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 @@ -1,5 +1,5 @@ /* - * Copyright 2012-2018 the original author or authors. + * Copyright 2012-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. @@ -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..bf69f0902f 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..a6094ec52b --- /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: + - explicit-yaml 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 diff --git a/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc b/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc index c289788c68..32b79cb45d 100644 --- a/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc +++ b/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc @@ -6539,8 +6539,8 @@ If you define a `com.hazelcast.config.Config` bean, Spring Boot uses that. If yo configuration defines an instance name, Spring Boot tries to locate an existing instance rather than creating a new one. -You could also specify the `hazelcast.xml` configuration file to use through -configuration, as shown in the following example: +You could also specify the Hazelcast configuration file to use through configuration, as +shown in the following example: [source,properties,indent=0] ---- @@ -6548,8 +6548,9 @@ configuration, as shown in the following example: ---- Otherwise, Spring Boot tries to find the Hazelcast configuration from the default -locations: `hazelcast.xml` in the working directory or at the root of the classpath. We -also check if the `hazelcast.config` system property is set. See the +locations: `hazelcast.xml` in the working directory or at the root of the classpath, or +a `.yaml` counterpart in the same locations. We also check if the `hazelcast.config` +system property is set. See the https://docs.hazelcast.org/docs/latest/manual/html-single/[Hazelcast documentation] for more details. @@ -6560,6 +6561,7 @@ client by checking the following configuration options: * A configuration file defined by the `spring.hazelcast.config` property. * The presence of the `hazelcast.client.config` system property. * A `hazelcast-client.xml` in the working directory or at the root of the classpath. +* A `hazelcast-client.yaml` in the working directory or at the root of the classpath. NOTE: Spring Boot also has <>. If