Polish "Add service connection support for Hazelcast"

See gh-42416
This commit is contained in:
Moritz Halbritter 2024-09-26 14:30:42 +02:00
parent cee7439dbe
commit 33def6d6b4
9 changed files with 85 additions and 42 deletions

View File

@ -17,17 +17,12 @@
package org.springframework.boot.autoconfigure.hazelcast;
import com.hazelcast.client.HazelcastClient;
import com.hazelcast.client.config.ClientConfig;
import com.hazelcast.core.HazelcastInstance;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.io.ResourceLoader;
/**
* Configuration for Hazelcast client.
@ -38,34 +33,9 @@ import org.springframework.core.io.ResourceLoader;
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(HazelcastClient.class)
@ConditionalOnMissingBean(HazelcastInstance.class)
@Import(HazelcastClientInstanceConfiguration.class)
@Import({ HazelcastConnectionDetailsConfiguration.class, HazelcastClientInstanceConfiguration.class })
class HazelcastClientConfiguration {
static final String CONFIG_SYSTEM_PROPERTY = "hazelcast.client.config";
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean({ ClientConfig.class, HazelcastConnectionDetails.class })
@Conditional(HazelcastClientConfigAvailableCondition.class)
static class HazelcastClientConfigFileConfiguration {
@Bean
HazelcastConnectionDetails hazelcastConnectionDetails(HazelcastProperties properties,
ResourceLoader resourceLoader) {
return new PropertiesHazelcastConnectionDetails(properties, resourceLoader);
}
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(HazelcastConnectionDetails.class)
@ConditionalOnSingleCandidate(ClientConfig.class)
static class HazelcastClientConfigConfiguration {
@Bean
HazelcastConnectionDetails hazelcastConnectionDetails(ClientConfig config) {
return () -> config;
}
}
}

View File

@ -0,0 +1,62 @@
/*
* Copyright 2012-2024 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
*
* https://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.boot.autoconfigure.hazelcast;
import com.hazelcast.client.config.ClientConfig;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ResourceLoader;
/**
* {@link Configuration} for providing {@link HazelcastConnectionDetails}.
*
* @author Dmytro Nosan
* @author Moritz Halbritter
*/
@Configuration(proxyBeanMethods = false)
class HazelcastConnectionDetailsConfiguration {
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean({ ClientConfig.class, HazelcastConnectionDetails.class })
@Conditional(HazelcastClientConfigAvailableCondition.class)
static class HazelcastClientConfigFileConfiguration {
@Bean
HazelcastConnectionDetails hazelcastConnectionDetails(HazelcastProperties properties,
ResourceLoader resourceLoader) {
return new PropertiesHazelcastConnectionDetails(properties, resourceLoader);
}
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(HazelcastConnectionDetails.class)
@ConditionalOnSingleCandidate(ClientConfig.class)
static class HazelcastClientConfigConfiguration {
@Bean
HazelcastConnectionDetails hazelcastConnectionDetails(ClientConfig config) {
return () -> config;
}
}
}

View File

@ -19,7 +19,6 @@ dependencies {
dockerTestImplementation("org.junit.jupiter:junit-jupiter")
dockerTestImplementation("org.testcontainers:testcontainers")
dockerTestRuntimeOnly("com.microsoft.sqlserver:mssql-jdbc")
dockerTestRuntimeOnly("com.oracle.database.r2dbc:oracle-r2dbc")
dockerTestRuntimeOnly("io.r2dbc:r2dbc-mssql")
@ -31,11 +30,11 @@ dependencies {
optional(project(":spring-boot-project:spring-boot-autoconfigure"))
optional(project(":spring-boot-project:spring-boot-actuator-autoconfigure"))
optional("com.hazelcast:hazelcast")
optional("io.r2dbc:r2dbc-spi")
optional("org.mongodb:mongodb-driver-core")
optional("org.neo4j.driver:neo4j-java-driver")
optional("org.springframework.data:spring-data-r2dbc")
optional("com.hazelcast:hazelcast")
testImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support"))
testImplementation(project(":spring-boot-project:spring-boot-test"))

View File

@ -66,7 +66,9 @@ class HazelcastDockerComposeConnectionDetailsFactory
@Override
public ClientConfig getClientConfig() {
ClientConfig config = new ClientConfig();
this.environment.getClusterName().ifPresent(config::setClusterName);
if (this.environment.getClusterName() != null) {
config.setClusterName(this.environment.getClusterName());
}
config.getNetworkConfig().addAddress(this.host + ":" + this.port);
return config;
}

View File

@ -17,7 +17,6 @@
package org.springframework.boot.docker.compose.service.connection.hazelcast;
import java.util.Map;
import java.util.Optional;
/**
* Hazelcast environment details.
@ -32,8 +31,8 @@ class HazelcastEnvironment {
this.clusterName = env.get("HZ_CLUSTERNAME");
}
Optional<String> getClusterName() {
return Optional.ofNullable(this.clusterName);
String getClusterName() {
return this.clusterName;
}
}

View File

@ -33,13 +33,13 @@ class HazelcastEnvironmentTests {
@Test
void getClusterNameWhenHasNoHzClusterNameSet() {
HazelcastEnvironment environment = new HazelcastEnvironment(Collections.emptyMap());
assertThat(environment.getClusterName()).isEmpty();
assertThat(environment.getClusterName()).isNull();
}
@Test
void getClusterNameWhenHzClusterNameSet() {
HazelcastEnvironment environment = new HazelcastEnvironment(Map.of("HZ_CLUSTERNAME", "spring-boot"));
assertThat(environment.getClusterName()).isNotEmpty().hasValue("spring-boot");
assertThat(environment.getClusterName()).isEqualTo("spring-boot");
}
}

View File

@ -52,7 +52,7 @@ class CustomClusterNameHazelcastContainerConnectionDetailsFactoryIntegrationTest
@Container
@ServiceConnection
static final HazelcastContainer hazelcast = TestImage.container(HazelcastContainer.class)
.withEnv("HZ_CLUSTERNAME", "spring-boot");
.withClusterName("spring-boot");
@Autowired(required = false)
private HazelcastConnectionDetails connectionDetails;

View File

@ -17,7 +17,6 @@
package org.springframework.boot.testcontainers.service.connection.hazelcast;
import java.util.Map;
import java.util.Optional;
import com.hazelcast.client.config.ClientConfig;
import org.testcontainers.containers.Container;
@ -66,7 +65,10 @@ class HazelcastContainerConnectionDetailsFactory
ClientConfig config = new ClientConfig();
Container<?> container = getContainer();
Map<String, String> env = container.getEnvMap();
Optional.ofNullable(env.get(CLUSTER_NAME_ENV)).ifPresent(config::setClusterName);
String clusterName = env.get(CLUSTER_NAME_ENV);
if (clusterName != null) {
config.setClusterName(clusterName);
}
config.getNetworkConfig().addAddress(container.getHost() + ":" + container.getMappedPort(DEFAULT_PORT));
return config;
}

View File

@ -33,4 +33,13 @@ public final class HazelcastContainer extends GenericContainer<HazelcastContaine
addExposedPorts(DEFAULT_PORT);
}
/**
* Sets the cluster name.
* @param clusterName the cluster name
* @return this instance
*/
public HazelcastContainer withClusterName(String clusterName) {
return withEnv("HZ_CLUSTERNAME", clusterName);
}
}