Commit 82e18ae8 authored by Rafal Leszko's avatar Rafal Leszko Committed by Stephane Nicoll

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
parent b527d364
...@@ -79,7 +79,8 @@ class HazelcastClientConfiguration { ...@@ -79,7 +79,8 @@ class HazelcastClientConfiguration {
ConfigAvailableCondition() { ConfigAvailableCondition() {
super(CONFIG_SYSTEM_PROPERTY, "file:./hazelcast-client.xml", super(CONFIG_SYSTEM_PROPERTY, "file:./hazelcast-client.xml",
"classpath:/hazelcast-client.xml"); "classpath:/hazelcast-client.xml", "file:./hazelcast-client.yaml",
"classpath:/hazelcast-client.yaml");
} }
} }
......
...@@ -22,6 +22,7 @@ import java.net.URL; ...@@ -22,6 +22,7 @@ import java.net.URL;
import com.hazelcast.client.HazelcastClient; import com.hazelcast.client.HazelcastClient;
import com.hazelcast.client.config.ClientConfig; import com.hazelcast.client.config.ClientConfig;
import com.hazelcast.client.config.XmlClientConfigBuilder; import com.hazelcast.client.config.XmlClientConfigBuilder;
import com.hazelcast.client.config.YamlClientConfigBuilder;
import com.hazelcast.core.HazelcastInstance; import com.hazelcast.core.HazelcastInstance;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
...@@ -59,7 +60,14 @@ public class HazelcastClientFactory { ...@@ -59,7 +60,14 @@ public class HazelcastClientFactory {
private ClientConfig getClientConfig(Resource clientConfigLocation) private ClientConfig getClientConfig(Resource clientConfigLocation)
throws IOException { throws IOException {
URL configUrl = clientConfigLocation.getURL(); 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();
}
} }
/** /**
......
...@@ -21,6 +21,7 @@ import java.net.URL; ...@@ -21,6 +21,7 @@ import java.net.URL;
import com.hazelcast.config.Config; import com.hazelcast.config.Config;
import com.hazelcast.config.XmlConfigBuilder; import com.hazelcast.config.XmlConfigBuilder;
import com.hazelcast.config.YamlConfigBuilder;
import com.hazelcast.core.Hazelcast; import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.HazelcastInstance; import com.hazelcast.core.HazelcastInstance;
...@@ -61,7 +62,7 @@ public class HazelcastInstanceFactory { ...@@ -61,7 +62,7 @@ public class HazelcastInstanceFactory {
private Config getConfig(Resource configLocation) throws IOException { private Config getConfig(Resource configLocation) throws IOException {
URL configUrl = configLocation.getURL(); URL configUrl = configLocation.getURL();
Config config = new XmlConfigBuilder(configUrl).build(); Config config = createConfig(configUrl);
if (ResourceUtils.isFileURL(configUrl)) { if (ResourceUtils.isFileURL(configUrl)) {
config.setConfigurationFile(configLocation.getFile()); config.setConfigurationFile(configLocation.getFile());
} }
...@@ -71,6 +72,14 @@ public class HazelcastInstanceFactory { ...@@ -71,6 +72,14 @@ public class HazelcastInstanceFactory {
return config; 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}. * Get the {@link HazelcastInstance}.
* @return the {@link HazelcastInstance} * @return the {@link HazelcastInstance}
......
...@@ -77,7 +77,8 @@ class HazelcastServerConfiguration { ...@@ -77,7 +77,8 @@ class HazelcastServerConfiguration {
ConfigAvailableCondition() { ConfigAvailableCondition() {
super(CONFIG_SYSTEM_PROPERTY, "file:./hazelcast.xml", super(CONFIG_SYSTEM_PROPERTY, "file:./hazelcast.xml",
"classpath:/hazelcast.xml"); "classpath:/hazelcast.xml", "file:./hazelcast.yaml",
"classpath:/hazelcast.yaml");
} }
} }
......
...@@ -28,6 +28,7 @@ import org.junit.Test; ...@@ -28,6 +28,7 @@ import org.junit.Test;
import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.BeanCreationException;
import org.springframework.boot.autoconfigure.AutoConfigurations; 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.ApplicationContextRunner;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
...@@ -63,35 +64,58 @@ public class HazelcastAutoConfigurationClientTests { ...@@ -63,35 +64,58 @@ public class HazelcastAutoConfigurationClientTests {
.withConfiguration(AutoConfigurations.of(HazelcastAutoConfiguration.class)); .withConfiguration(AutoConfigurations.of(HazelcastAutoConfiguration.class));
@Test @Test
public void systemProperty() { public void systemPropertyWithXml() {
this.contextRunner systemProperty(HazelcastClientConfiguration.CONFIG_SYSTEM_PROPERTY
.withSystemProperties(HazelcastClientConfiguration.CONFIG_SYSTEM_PROPERTY + "=classpath:org/springframework/boot/autoconfigure/hazelcast/"
+ "=classpath:org/springframework/boot/autoconfigure/hazelcast/" + "hazelcast-client-specific.xml");
+ "hazelcast-client-specific.xml")
.run((context) -> assertThat(context).getBean(HazelcastInstance.class)
.isInstanceOf(HazelcastInstance.class)
.has(nameStartingWith("hz.client_")));
} }
@Test @Test
public void explicitConfigFile() { public void systemPropertyWithYaml() {
this.contextRunner systemProperty(HazelcastClientConfiguration.CONFIG_SYSTEM_PROPERTY
.withPropertyValues( + "=classpath:org/springframework/boot/autoconfigure/hazelcast/"
"spring.hazelcast.config=org/springframework/boot/autoconfigure/" + "hazelcast-client-specific.yaml");
+ "hazelcast/hazelcast-client-specific.xml") }
.run((context) -> assertThat(context).getBean(HazelcastInstance.class)
.isInstanceOf(HazelcastClientProxy.class) private void systemProperty(String systemProperty) {
.has(nameStartingWith("hz.client_"))); this.contextRunner.withSystemProperties(systemProperty)
.run((context) -> assertHazelcastClientSpecific(context));
} }
@Test @Test
public void explicitConfigUrl() { public void explicitConfigFileWithXml() {
this.contextRunner propertyValues("spring.hazelcast.config=org/springframework/boot/autoconfigure/"
.withPropertyValues( + "hazelcast/hazelcast-client-specific.xml");
"spring.hazelcast.config=hazelcast-client-default.xml") }
.run((context) -> assertThat(context).getBean(HazelcastInstance.class)
.isInstanceOf(HazelcastClientProxy.class) @Test
.has(nameStartingWith("hz.client_"))); 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 @Test
...@@ -111,9 +135,10 @@ public class HazelcastAutoConfigurationClientTests { ...@@ -111,9 +135,10 @@ public class HazelcastAutoConfigurationClientTests {
.isInstanceOf(HazelcastClientProxy.class)); .isInstanceOf(HazelcastClientProxy.class));
} }
private Condition<HazelcastInstance> nameStartingWith(String prefix) { private static Condition<HazelcastInstance> labelEqualTo(String label) {
return new Condition<>((o) -> o.getName().startsWith(prefix), return new Condition<>((o) -> ((HazelcastClientProxy) o).getClientConfig()
"Name starts with " + prefix); .getLabels().stream().anyMatch((e) -> e.equals(label)),
"Label equals to " + label);
} }
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
......
...@@ -27,6 +27,7 @@ import org.junit.runner.RunWith; ...@@ -27,6 +27,7 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.BeanCreationException;
import org.springframework.boot.autoconfigure.AutoConfigurations; 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.ApplicationContextRunner;
import org.springframework.boot.testsupport.runner.classpath.ClassPathExclusions; import org.springframework.boot.testsupport.runner.classpath.ClassPathExclusions;
import org.springframework.boot.testsupport.runner.classpath.ModifiedClassPathRunner; import org.springframework.boot.testsupport.runner.classpath.ModifiedClassPathRunner;
...@@ -59,39 +60,56 @@ public class HazelcastAutoConfigurationServerTests { ...@@ -59,39 +60,56 @@ public class HazelcastAutoConfigurationServerTests {
} }
@Test @Test
public void systemProperty() { public void systemPropertyWithXml() {
this.contextRunner systemProperty(HazelcastServerConfiguration.CONFIG_SYSTEM_PROPERTY
.withSystemProperties(HazelcastServerConfiguration.CONFIG_SYSTEM_PROPERTY + "=classpath:org/springframework/boot/autoconfigure/hazelcast/hazelcast-specific.xml");
+ "=classpath:org/springframework/boot/autoconfigure/hazelcast/hazelcast-specific.xml") }
.run((context) -> {
Config config = context.getBean(HazelcastInstance.class).getConfig(); @Test
assertThat(config.getQueueConfigs().keySet()).containsOnly("foobar"); 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 @Test
public void explicitConfigFile() { public void explicitConfigFileWithXml() {
this.contextRunner.withPropertyValues( propertyValues(
"spring.hazelcast.config=org/springframework/boot/autoconfigure/hazelcast/" "spring.hazelcast.config=org/springframework/boot/autoconfigure/hazelcast/"
+ "hazelcast-specific.xml") + "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());
});
} }
@Test @Test
public void explicitConfigUrl() { public void explicitConfigFileWithYaml() {
this.contextRunner propertyValues(
.withPropertyValues("spring.hazelcast.config=hazelcast-default.xml") "spring.hazelcast.config=org/springframework/boot/autoconfigure/hazelcast/"
.run((context) -> { + "hazelcast-specific.yaml");
Config config = context.getBean(HazelcastInstance.class).getConfig(); }
assertThat(config.getConfigurationUrl()).isEqualTo(
new ClassPathResource("hazelcast-default.xml").getURL()); @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 @Test
......
...@@ -39,6 +39,8 @@ public class HazelcastAutoConfigurationTests { ...@@ -39,6 +39,8 @@ public class HazelcastAutoConfigurationTests {
@Test @Test
public void defaultConfigFile() { public void defaultConfigFile() {
// no hazelcast-client.xml and hazelcast.xml is present in root classpath // 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) -> { this.contextRunner.run((context) -> {
Config config = context.getBean(HazelcastInstance.class).getConfig(); Config config = context.getBean(HazelcastInstance.class).getConfig();
assertThat(config.getConfigurationUrl()) assertThat(config.getConfigurationUrl())
......
...@@ -2,5 +2,8 @@ ...@@ -2,5 +2,8 @@
<hazelcast-client xmlns="http://www.hazelcast.com/schema/client-config" <hazelcast-client xmlns="http://www.hazelcast.com/schema/client-config"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.hazelcast.com/schema/client-config hazelcast-client-config-3.12.xsd"> xsi:schemaLocation="http://www.hazelcast.com/schema/client-config hazelcast-client-config-3.12.xsd">
<client-labels>
<label>configured-client</label>
</client-labels>
</hazelcast-client> </hazelcast-client>
hazelcast:
network:
join:
multicast:
enabled: false
map:
foobar:
time-to-live-seconds: 3600
max-idle-seconds: 600
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment