Browse Source

Use ephemeral port for Hazelcast

When Hazelcast is started on a fixed port and that port is already in
use, it does not fail to start which makes the problem hard to
detect. A symptom of the problem is that clients will not be able to
connect and will either retry indefinitely or will timeout depending
on their configuration.

This commit updates the Hazelcast client tests to start the Hazelcast
instance on an ephemeral port and to customize the client
configuration with the instance's address before use. This should
allow the client tests to work reliably in an environment where
Hazelcast's default port is already in use.

Closes gh-35903
pull/35915/head
Andy Wilkinson 3 years ago
parent
commit
088006ff60
  1. 132
      spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfigurationClientTests.java
  2. 6
      spring-boot-project/spring-boot-autoconfigure/src/test/resources/org/springframework/boot/autoconfigure/hazelcast/hazelcast-client-instance.xml
  3. 6
      spring-boot-project/spring-boot-autoconfigure/src/test/resources/org/springframework/boot/autoconfigure/hazelcast/hazelcast-client-specific.xml
  4. 3
      spring-boot-project/spring-boot-autoconfigure/src/test/resources/org/springframework/boot/autoconfigure/hazelcast/hazelcast-client-specific.yaml
  5. 3
      spring-boot-project/spring-boot-autoconfigure/src/test/resources/org/springframework/boot/autoconfigure/hazelcast/hazelcast-client-specific.yml

132
spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfigurationClientTests.java

@ -16,10 +16,16 @@ @@ -16,10 +16,16 @@
package org.springframework.boot.autoconfigure.hazelcast;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.nio.file.Files;
import com.hazelcast.client.HazelcastClient;
import com.hazelcast.client.config.ClientConfig;
import com.hazelcast.client.config.ClientConnectionStrategyConfig;
import com.hazelcast.client.config.ConnectionRetryConfig;
import com.hazelcast.client.impl.clientside.HazelcastClientProxy;
import com.hazelcast.config.Config;
import com.hazelcast.core.Hazelcast;
@ -36,6 +42,7 @@ import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -36,6 +42,7 @@ 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;
import org.springframework.util.FileCopyUtils;
import static org.assertj.core.api.Assertions.assertThat;
@ -52,9 +59,15 @@ class HazelcastAutoConfigurationClientTests { @@ -52,9 +59,15 @@ class HazelcastAutoConfigurationClientTests {
*/
private static HazelcastInstance hazelcastServer;
private static String endpointAddress;
@BeforeAll
static void init() {
hazelcastServer = Hazelcast.newHazelcastInstance();
Config config = Config.load();
config.getNetworkConfig().setPort(0);
hazelcastServer = Hazelcast.newHazelcastInstance(config);
InetSocketAddress inetSocketAddress = (InetSocketAddress) hazelcastServer.getLocalEndpoint().getSocketAddress();
endpointAddress = inetSocketAddress.getHostString() + ":" + inetSocketAddress.getPort();
}
@AfterAll
@ -69,73 +82,52 @@ class HazelcastAutoConfigurationClientTests { @@ -69,73 +82,52 @@ class HazelcastAutoConfigurationClientTests {
@Test
void systemPropertyWithXml() {
File config = prepareConfiguration("src/test/resources/org/springframework/"
+ "boot/autoconfigure/hazelcast/hazelcast-client-specific.xml");
this.contextRunner
.withSystemProperties(HazelcastClientConfiguration.CONFIG_SYSTEM_PROPERTY
+ "=classpath:org/springframework/boot/autoconfigure/hazelcast/hazelcast-client-specific.xml")
.withSystemProperties(HazelcastClientConfiguration.CONFIG_SYSTEM_PROPERTY + "=" + config.getAbsolutePath())
.run(assertSpecificHazelcastClient("explicit-xml"));
}
@Test
void systemPropertyWithYaml() {
File config = prepareConfiguration("src/test/resources/org/springframework/"
+ "boot/autoconfigure/hazelcast/hazelcast-client-specific.yaml");
this.contextRunner
.withSystemProperties(HazelcastClientConfiguration.CONFIG_SYSTEM_PROPERTY
+ "=classpath:org/springframework/boot/autoconfigure/hazelcast/hazelcast-client-specific.yaml")
.withSystemProperties(HazelcastClientConfiguration.CONFIG_SYSTEM_PROPERTY + "=" + config.getAbsolutePath())
.run(assertSpecificHazelcastClient("explicit-yaml"));
}
@Test
void systemPropertyWithYml() {
File config = prepareConfiguration("src/test/resources/org/springframework/"
+ "boot/autoconfigure/hazelcast/hazelcast-client-specific.yml");
this.contextRunner
.withSystemProperties(HazelcastClientConfiguration.CONFIG_SYSTEM_PROPERTY
+ "=classpath:org/springframework/boot/autoconfigure/hazelcast/hazelcast-client-specific.yml")
.run(assertSpecificHazelcastClient("explicit-yml"));
}
@Test
void explicitConfigFileWithXml() {
this.contextRunner
.withPropertyValues("spring.hazelcast.config=org/springframework/boot/autoconfigure/"
+ "hazelcast/hazelcast-client-specific.xml")
.run(assertSpecificHazelcastClient("explicit-xml"));
}
@Test
void explicitConfigFileWithYaml() {
this.contextRunner
.withPropertyValues("spring.hazelcast.config=org/springframework/boot/autoconfigure/"
+ "hazelcast/hazelcast-client-specific.yaml")
.run(assertSpecificHazelcastClient("explicit-yaml"));
}
@Test
void explicitConfigFileWithYml() {
this.contextRunner
.withPropertyValues("spring.hazelcast.config=org/springframework/boot/autoconfigure/"
+ "hazelcast/hazelcast-client-specific.yml")
.withSystemProperties(HazelcastClientConfiguration.CONFIG_SYSTEM_PROPERTY + "=" + config.getAbsolutePath())
.run(assertSpecificHazelcastClient("explicit-yml"));
}
@Test
void explicitConfigUrlWithXml() {
this.contextRunner
.withPropertyValues("spring.hazelcast.config=classpath:org/springframework/"
+ "boot/autoconfigure/hazelcast/hazelcast-client-specific.xml")
void explicitConfigUrlWithXml() throws MalformedURLException {
File config = prepareConfiguration("src/test/resources/org/springframework/"
+ "boot/autoconfigure/hazelcast/hazelcast-client-specific.xml");
this.contextRunner.withPropertyValues("spring.hazelcast.config=" + config.toURI().toURL())
.run(assertSpecificHazelcastClient("explicit-xml"));
}
@Test
void explicitConfigUrlWithYaml() {
this.contextRunner
.withPropertyValues("spring.hazelcast.config=classpath:org/springframework/"
+ "boot/autoconfigure/hazelcast/hazelcast-client-specific.yaml")
void explicitConfigUrlWithYaml() throws MalformedURLException {
File config = prepareConfiguration("src/test/resources/org/springframework/"
+ "boot/autoconfigure/hazelcast/hazelcast-client-specific.yaml");
this.contextRunner.withPropertyValues("spring.hazelcast.config=" + config.toURI().toURL())
.run(assertSpecificHazelcastClient("explicit-yaml"));
}
@Test
void explicitConfigUrlWithYml() {
this.contextRunner
.withPropertyValues("spring.hazelcast.config=classpath:org/springframework/"
+ "boot/autoconfigure/hazelcast/hazelcast-client-specific.yml")
void explicitConfigUrlWithYml() throws MalformedURLException {
File config = prepareConfiguration("src/test/resources/org/springframework/"
+ "boot/autoconfigure/hazelcast/hazelcast-client-specific.yml");
this.contextRunner.withPropertyValues("spring.hazelcast.config=" + config.toURI().toURL())
.run(assertSpecificHazelcastClient("explicit-yml"));
}
@ -156,28 +148,26 @@ class HazelcastAutoConfigurationClientTests { @@ -156,28 +148,26 @@ class HazelcastAutoConfigurationClientTests {
}
@Test
void clientConfigWithInstanceNameCreatesClientIfNecessary() {
void clientConfigWithInstanceNameCreatesClientIfNecessary() throws MalformedURLException {
assertThat(HazelcastClient.getHazelcastClientByName("spring-boot")).isNull();
this.contextRunner
.withPropertyValues("spring.hazelcast.config=classpath:org/springframework/"
+ "boot/autoconfigure/hazelcast/hazelcast-client-instance.xml")
File config = prepareConfiguration("src/test/resources/org/springframework/"
+ "boot/autoconfigure/hazelcast/hazelcast-client-instance.xml");
this.contextRunner.withPropertyValues("spring.hazelcast.config=" + config.toURI().toURL())
.run((context) -> assertThat(context).getBean(HazelcastInstance.class)
.extracting(HazelcastInstance::getName)
.isEqualTo("spring-boot"));
}
@Test
void autoConfiguredClientConfigUsesApplicationClassLoader() {
this.contextRunner
.withPropertyValues("spring.hazelcast.config=org/springframework/boot/autoconfigure/"
+ "hazelcast/hazelcast-client-specific.xml")
.run((context) -> {
HazelcastInstance hazelcast = context.getBean(HazelcastInstance.class);
assertThat(hazelcast).isInstanceOf(HazelcastClientProxy.class);
ClientConfig clientConfig = ((HazelcastClientProxy) hazelcast).getClientConfig();
assertThat(clientConfig.getClassLoader())
.isSameAs(context.getSourceApplicationContext().getClassLoader());
});
void autoConfiguredClientConfigUsesApplicationClassLoader() throws MalformedURLException {
File config = prepareConfiguration("src/test/resources/org/springframework/"
+ "boot/autoconfigure/hazelcast/hazelcast-client-specific.xml");
this.contextRunner.withPropertyValues("spring.hazelcast.config=" + config.toURI().toURL()).run((context) -> {
HazelcastInstance hazelcast = context.getBean(HazelcastInstance.class);
assertThat(hazelcast).isInstanceOf(HazelcastClientProxy.class);
ClientConfig clientConfig = ((HazelcastClientProxy) hazelcast).getClientConfig();
assertThat(clientConfig.getClassLoader()).isSameAs(context.getSourceApplicationContext().getClassLoader());
});
}
private ContextConsumer<AssertableApplicationContext> assertSpecificHazelcastClient(String label) {
@ -193,6 +183,22 @@ class HazelcastAutoConfigurationClientTests { @@ -193,6 +183,22 @@ class HazelcastAutoConfigurationClientTests {
.anyMatch((e) -> e.equals(label)), "Label equals to " + label);
}
private File prepareConfiguration(String input) {
File configFile = new File(input);
try {
String config = FileCopyUtils.copyToString(new FileReader(configFile));
config = config.replace("${address}", endpointAddress);
System.out.println(config);
File outputFile = new File(Files.createTempDirectory(getClass().getSimpleName()).toFile(),
configFile.getName());
FileCopyUtils.copy(config, new FileWriter(outputFile));
return outputFile;
}
catch (IOException ex) {
throw new RuntimeException(ex);
}
}
@Configuration(proxyBeanMethods = false)
static class HazelcastServerAndClientConfig {
@ -203,8 +209,10 @@ class HazelcastAutoConfigurationClientTests { @@ -203,8 +209,10 @@ class HazelcastAutoConfigurationClientTests {
@Bean
ClientConfig clientConfig() {
return new ClientConfig().setConnectionStrategyConfig(new ClientConnectionStrategyConfig()
.setConnectionRetryConfig(new ConnectionRetryConfig().setClusterConnectTimeoutMillis(60000)));
ClientConfig config = new ClientConfig();
config.getConnectionStrategyConfig().getConnectionRetryConfig().setClusterConnectTimeoutMillis(60000);
config.getNetworkConfig().getAddresses().add(endpointAddress);
return config;
}
}

6
spring-boot-project/spring-boot-autoconfigure/src/test/resources/org/springframework/boot/autoconfigure/hazelcast/hazelcast-client-instance.xml

@ -10,5 +10,11 @@ @@ -10,5 +10,11 @@
<cluster-connect-timeout-millis>60000</cluster-connect-timeout-millis>
</connection-retry>
</connection-strategy>
<network>
<cluster-members>
<address>${address}</address>
</cluster-members>
</network>
</hazelcast-client>

6
spring-boot-project/spring-boot-autoconfigure/src/test/resources/org/springframework/boot/autoconfigure/hazelcast/hazelcast-client-specific.xml

@ -10,5 +10,9 @@ @@ -10,5 +10,9 @@
<cluster-connect-timeout-millis>60000</cluster-connect-timeout-millis>
</connection-retry>
</connection-strategy>
<network>
<cluster-members>
<address>${address}</address>
</cluster-members>
</network>
</hazelcast-client>

3
spring-boot-project/spring-boot-autoconfigure/src/test/resources/org/springframework/boot/autoconfigure/hazelcast/hazelcast-client-specific.yaml

@ -4,3 +4,6 @@ hazelcast-client: @@ -4,3 +4,6 @@ hazelcast-client:
connection-strategy:
connection-retry:
cluster-connect-timeout-millis: 60000
network:
cluster-members:
- ${address}

3
spring-boot-project/spring-boot-autoconfigure/src/test/resources/org/springframework/boot/autoconfigure/hazelcast/hazelcast-client-specific.yml

@ -4,3 +4,6 @@ hazelcast-client: @@ -4,3 +4,6 @@ hazelcast-client:
connection-strategy:
connection-retry:
cluster-connect-timeout-millis: 60000
network:
cluster-members:
- ${address}

Loading…
Cancel
Save