23 changed files with 756 additions and 35 deletions
@ -0,0 +1,46 @@ |
|||||||
|
/* |
||||||
|
* 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.HazelcastClient; |
||||||
|
import com.hazelcast.client.config.ClientConfig; |
||||||
|
import com.hazelcast.core.HazelcastInstance; |
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; |
||||||
|
import org.springframework.context.annotation.Bean; |
||||||
|
import org.springframework.context.annotation.Configuration; |
||||||
|
import org.springframework.util.StringUtils; |
||||||
|
|
||||||
|
/** |
||||||
|
* Configuration for Hazelcast client instance. |
||||||
|
* |
||||||
|
* @author Dmytro Nosan |
||||||
|
*/ |
||||||
|
@Configuration(proxyBeanMethods = false) |
||||||
|
@ConditionalOnBean(HazelcastConnectionDetails.class) |
||||||
|
class HazelcastClientInstanceConfiguration { |
||||||
|
|
||||||
|
@Bean |
||||||
|
HazelcastInstance hazelcastInstance(HazelcastConnectionDetails hazelcastConnectionDetails) { |
||||||
|
ClientConfig config = hazelcastConnectionDetails.getClientConfig(); |
||||||
|
if (StringUtils.hasText(config.getInstanceName())) { |
||||||
|
return HazelcastClient.getOrCreateHazelcastClient(config); |
||||||
|
} |
||||||
|
return HazelcastClient.newHazelcastClient(config); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,37 @@ |
|||||||
|
/* |
||||||
|
* 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.service.connection.ConnectionDetails; |
||||||
|
|
||||||
|
/** |
||||||
|
* Details required to establish a client connection to a Hazelcast instance. |
||||||
|
* |
||||||
|
* @author Dmytro Nosan |
||||||
|
* @since 3.4.0 |
||||||
|
*/ |
||||||
|
public interface HazelcastConnectionDetails extends ConnectionDetails { |
||||||
|
|
||||||
|
/** |
||||||
|
* The {@link ClientConfig} for Hazelcast client. |
||||||
|
* @return the client config |
||||||
|
*/ |
||||||
|
ClientConfig getClientConfig(); |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,68 @@ |
|||||||
|
/* |
||||||
|
* 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 java.io.IOException; |
||||||
|
import java.io.UncheckedIOException; |
||||||
|
import java.net.URL; |
||||||
|
|
||||||
|
import com.hazelcast.client.config.ClientConfig; |
||||||
|
import com.hazelcast.client.config.XmlClientConfigBuilder; |
||||||
|
import com.hazelcast.client.config.YamlClientConfigBuilder; |
||||||
|
|
||||||
|
import org.springframework.core.io.Resource; |
||||||
|
import org.springframework.core.io.ResourceLoader; |
||||||
|
|
||||||
|
/** |
||||||
|
* Adapts {@link HazelcastProperties} to {@link HazelcastConnectionDetails}. |
||||||
|
* |
||||||
|
* @author Dmytro Nosan |
||||||
|
*/ |
||||||
|
class PropertiesHazelcastConnectionDetails implements HazelcastConnectionDetails { |
||||||
|
|
||||||
|
private final HazelcastProperties properties; |
||||||
|
|
||||||
|
private final ResourceLoader resourceLoader; |
||||||
|
|
||||||
|
PropertiesHazelcastConnectionDetails(HazelcastProperties properties, ResourceLoader resourceLoader) { |
||||||
|
this.properties = properties; |
||||||
|
this.resourceLoader = resourceLoader; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public ClientConfig getClientConfig() { |
||||||
|
Resource configLocation = this.properties.resolveConfigLocation(); |
||||||
|
ClientConfig config = (configLocation != null) ? loadClientConfig(configLocation) : ClientConfig.load(); |
||||||
|
config.setClassLoader(this.resourceLoader.getClassLoader()); |
||||||
|
return config; |
||||||
|
} |
||||||
|
|
||||||
|
private ClientConfig loadClientConfig(Resource configLocation) { |
||||||
|
try { |
||||||
|
URL configUrl = configLocation.getURL(); |
||||||
|
String configFileName = configUrl.getPath(); |
||||||
|
if (configFileName.endsWith(".yaml") || configFileName.endsWith(".yml")) { |
||||||
|
return new YamlClientConfigBuilder(configUrl).build(); |
||||||
|
} |
||||||
|
return new XmlClientConfigBuilder(configUrl).build(); |
||||||
|
} |
||||||
|
catch (IOException ex) { |
||||||
|
throw new UncheckedIOException("Failed to load Hazelcast config", ex); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,66 @@ |
|||||||
|
/* |
||||||
|
* 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.docker.compose.service.connection.hazelcast; |
||||||
|
|
||||||
|
import java.util.UUID; |
||||||
|
|
||||||
|
import com.hazelcast.client.HazelcastClient; |
||||||
|
import com.hazelcast.client.config.ClientConfig; |
||||||
|
import com.hazelcast.config.Config; |
||||||
|
import com.hazelcast.core.HazelcastInstance; |
||||||
|
import com.hazelcast.map.IMap; |
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.hazelcast.HazelcastConnectionDetails; |
||||||
|
import org.springframework.boot.docker.compose.service.connection.test.DockerComposeTest; |
||||||
|
import org.springframework.boot.testsupport.container.TestImage; |
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat; |
||||||
|
|
||||||
|
/** |
||||||
|
* Integration tests for {@link HazelcastDockerComposeConnectionDetailsFactory}. |
||||||
|
* |
||||||
|
* @author Dmytro Nosan |
||||||
|
*/ |
||||||
|
class HazelcastDockerComposeConnectionDetailsFactoryIntegrationTests { |
||||||
|
|
||||||
|
@DockerComposeTest(composeFile = "hazelcast-compose.yaml", image = TestImage.HAZELCAST) |
||||||
|
void runCreatesConnectionDetails(HazelcastConnectionDetails connectionDetails) { |
||||||
|
ClientConfig config = connectionDetails.getClientConfig(); |
||||||
|
assertThat(config.getClusterName()).isEqualTo(Config.DEFAULT_CLUSTER_NAME); |
||||||
|
verifyConnection(config); |
||||||
|
} |
||||||
|
|
||||||
|
@DockerComposeTest(composeFile = "hazelcast-cluster-name-compose.yaml", image = TestImage.HAZELCAST) |
||||||
|
void runCreatesConnectionDetailsCustomClusterName(HazelcastConnectionDetails connectionDetails) { |
||||||
|
ClientConfig config = connectionDetails.getClientConfig(); |
||||||
|
assertThat(config.getClusterName()).isEqualTo("spring-boot"); |
||||||
|
verifyConnection(config); |
||||||
|
} |
||||||
|
|
||||||
|
private static void verifyConnection(ClientConfig config) { |
||||||
|
HazelcastInstance hazelcastInstance = HazelcastClient.newHazelcastClient(config); |
||||||
|
try { |
||||||
|
IMap<String, String> map = hazelcastInstance.getMap(UUID.randomUUID().toString()); |
||||||
|
map.put("docker", "compose"); |
||||||
|
assertThat(map.get("docker")).isEqualTo("compose"); |
||||||
|
} |
||||||
|
finally { |
||||||
|
hazelcastInstance.shutdown(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,7 @@ |
|||||||
|
services: |
||||||
|
hazelcast: |
||||||
|
image: '{imageName}' |
||||||
|
environment: |
||||||
|
HZ_CLUSTERNAME: "spring-boot" |
||||||
|
ports: |
||||||
|
- '5701' |
||||||
@ -0,0 +1,5 @@ |
|||||||
|
services: |
||||||
|
hazelcast: |
||||||
|
image: '{imageName}' |
||||||
|
ports: |
||||||
|
- '5701' |
||||||
@ -0,0 +1,76 @@ |
|||||||
|
/* |
||||||
|
* 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.docker.compose.service.connection.hazelcast; |
||||||
|
|
||||||
|
import com.hazelcast.client.config.ClientConfig; |
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.hazelcast.HazelcastConnectionDetails; |
||||||
|
import org.springframework.boot.docker.compose.core.RunningService; |
||||||
|
import org.springframework.boot.docker.compose.service.connection.DockerComposeConnectionDetailsFactory; |
||||||
|
import org.springframework.boot.docker.compose.service.connection.DockerComposeConnectionSource; |
||||||
|
|
||||||
|
/** |
||||||
|
* {@link DockerComposeConnectionDetailsFactory} to create |
||||||
|
* {@link HazelcastConnectionDetails} for a {@code hazelcast} service. |
||||||
|
* |
||||||
|
* @author Dmytro Nosan |
||||||
|
*/ |
||||||
|
class HazelcastDockerComposeConnectionDetailsFactory |
||||||
|
extends DockerComposeConnectionDetailsFactory<HazelcastConnectionDetails> { |
||||||
|
|
||||||
|
private static final int DEFAULT_PORT = 5701; |
||||||
|
|
||||||
|
protected HazelcastDockerComposeConnectionDetailsFactory() { |
||||||
|
super("hazelcast/hazelcast", "com.hazelcast.client.config.ClientConfig"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected HazelcastConnectionDetails getDockerComposeConnectionDetails(DockerComposeConnectionSource source) { |
||||||
|
return new HazelcastDockerComposeConnectionDetails(source.getRunningService()); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* {@link HazelcastConnectionDetails} backed by a {@code hazelcast} |
||||||
|
* {@link RunningService}. |
||||||
|
*/ |
||||||
|
static class HazelcastDockerComposeConnectionDetails extends DockerComposeConnectionDetails |
||||||
|
implements HazelcastConnectionDetails { |
||||||
|
|
||||||
|
private final String host; |
||||||
|
|
||||||
|
private final int port; |
||||||
|
|
||||||
|
private final HazelcastEnvironment environment; |
||||||
|
|
||||||
|
HazelcastDockerComposeConnectionDetails(RunningService service) { |
||||||
|
super(service); |
||||||
|
this.host = service.host(); |
||||||
|
this.port = service.ports().get(DEFAULT_PORT); |
||||||
|
this.environment = new HazelcastEnvironment(service.env()); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public ClientConfig getClientConfig() { |
||||||
|
ClientConfig config = new ClientConfig(); |
||||||
|
this.environment.getClusterName().ifPresent(config::setClusterName); |
||||||
|
config.getNetworkConfig().addAddress(this.host + ":" + this.port); |
||||||
|
return config; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,39 @@ |
|||||||
|
/* |
||||||
|
* 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.docker.compose.service.connection.hazelcast; |
||||||
|
|
||||||
|
import java.util.Map; |
||||||
|
import java.util.Optional; |
||||||
|
|
||||||
|
/** |
||||||
|
* Hazelcast environment details. |
||||||
|
* |
||||||
|
* @author Dmytro Nosan |
||||||
|
*/ |
||||||
|
class HazelcastEnvironment { |
||||||
|
|
||||||
|
private final String clusterName; |
||||||
|
|
||||||
|
HazelcastEnvironment(Map<String, String> env) { |
||||||
|
this.clusterName = env.get("HZ_CLUSTERNAME"); |
||||||
|
} |
||||||
|
|
||||||
|
Optional<String> getClusterName() { |
||||||
|
return Optional.ofNullable(this.clusterName); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,20 @@ |
|||||||
|
/* |
||||||
|
* 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
/** |
||||||
|
* Auto-configuration for Docker Compose Hazelcast service connections. |
||||||
|
*/ |
||||||
|
package org.springframework.boot.docker.compose.service.connection.hazelcast; |
||||||
@ -0,0 +1,45 @@ |
|||||||
|
/* |
||||||
|
* 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.docker.compose.service.connection.hazelcast; |
||||||
|
|
||||||
|
import java.util.Collections; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test; |
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat; |
||||||
|
|
||||||
|
/** |
||||||
|
* Tests for {@link HazelcastEnvironment}. |
||||||
|
* |
||||||
|
* @author Dmytro Nosan |
||||||
|
*/ |
||||||
|
class HazelcastEnvironmentTests { |
||||||
|
|
||||||
|
@Test |
||||||
|
void getClusterNameWhenHasNoHzClusterNameSet() { |
||||||
|
HazelcastEnvironment environment = new HazelcastEnvironment(Collections.emptyMap()); |
||||||
|
assertThat(environment.getClusterName()).isEmpty(); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
void getClusterNameWhenHzClusterNameSet() { |
||||||
|
HazelcastEnvironment environment = new HazelcastEnvironment(Map.of("HZ_CLUSTERNAME", "spring-boot")); |
||||||
|
assertThat(environment.getClusterName()).isNotEmpty().hasValue("spring-boot"); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,86 @@ |
|||||||
|
/* |
||||||
|
* 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.testcontainers.service.connection.hazelcast; |
||||||
|
|
||||||
|
import java.util.UUID; |
||||||
|
import java.util.function.Consumer; |
||||||
|
|
||||||
|
import com.hazelcast.client.config.ClientConfig; |
||||||
|
import com.hazelcast.client.impl.clientside.HazelcastClientProxy; |
||||||
|
import com.hazelcast.core.HazelcastInstance; |
||||||
|
import com.hazelcast.map.IMap; |
||||||
|
import org.junit.jupiter.api.Test; |
||||||
|
import org.testcontainers.junit.jupiter.Container; |
||||||
|
import org.testcontainers.junit.jupiter.Testcontainers; |
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.boot.autoconfigure.ImportAutoConfiguration; |
||||||
|
import org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration; |
||||||
|
import org.springframework.boot.autoconfigure.hazelcast.HazelcastConnectionDetails; |
||||||
|
import org.springframework.boot.testcontainers.service.connection.ServiceConnection; |
||||||
|
import org.springframework.boot.testsupport.container.HazelcastContainer; |
||||||
|
import org.springframework.boot.testsupport.container.TestImage; |
||||||
|
import org.springframework.context.annotation.Configuration; |
||||||
|
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; |
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat; |
||||||
|
|
||||||
|
/** |
||||||
|
* Tests for {@link HazelcastContainerConnectionDetailsFactory} with a custom hazelcast |
||||||
|
* cluster name. |
||||||
|
* |
||||||
|
* @author Dmytro Nosan |
||||||
|
*/ |
||||||
|
@SpringJUnitConfig |
||||||
|
@Testcontainers(disabledWithoutDocker = true) |
||||||
|
class CustomClusterNameHazelcastContainerConnectionDetailsFactoryIntegrationTests { |
||||||
|
|
||||||
|
@Container |
||||||
|
@ServiceConnection |
||||||
|
static final HazelcastContainer hazelcast = TestImage.container(HazelcastContainer.class) |
||||||
|
.withEnv("HZ_CLUSTERNAME", "spring-boot"); |
||||||
|
|
||||||
|
@Autowired(required = false) |
||||||
|
private HazelcastConnectionDetails connectionDetails; |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private HazelcastInstance hazelcastInstance; |
||||||
|
|
||||||
|
@Test |
||||||
|
void connectionCanBeMadeToHazelcastContainer() { |
||||||
|
assertThat(this.connectionDetails).isNotNull(); |
||||||
|
assertThat(this.hazelcastInstance).satisfies(clusterName("spring-boot")); |
||||||
|
IMap<String, String> map = this.hazelcastInstance.getMap(UUID.randomUUID().toString()); |
||||||
|
map.put("test", "containers"); |
||||||
|
assertThat(map.get("test")).isEqualTo("containers"); |
||||||
|
} |
||||||
|
|
||||||
|
private static Consumer<HazelcastInstance> clusterName(String name) { |
||||||
|
return (hazelcastInstance) -> { |
||||||
|
assertThat(hazelcastInstance).isInstanceOf(HazelcastClientProxy.class); |
||||||
|
HazelcastClientProxy proxy = (HazelcastClientProxy) hazelcastInstance; |
||||||
|
assertThat(proxy.getClientConfig()).extracting(ClientConfig::getClusterName).isEqualTo(name); |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
@Configuration(proxyBeanMethods = false) |
||||||
|
@ImportAutoConfiguration(HazelcastAutoConfiguration.class) |
||||||
|
static class TestConfiguration { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,72 @@ |
|||||||
|
/* |
||||||
|
* 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.testcontainers.service.connection.hazelcast; |
||||||
|
|
||||||
|
import java.util.UUID; |
||||||
|
|
||||||
|
import com.hazelcast.core.HazelcastInstance; |
||||||
|
import com.hazelcast.map.IMap; |
||||||
|
import org.junit.jupiter.api.Test; |
||||||
|
import org.testcontainers.junit.jupiter.Container; |
||||||
|
import org.testcontainers.junit.jupiter.Testcontainers; |
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.boot.autoconfigure.ImportAutoConfiguration; |
||||||
|
import org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration; |
||||||
|
import org.springframework.boot.autoconfigure.hazelcast.HazelcastConnectionDetails; |
||||||
|
import org.springframework.boot.testcontainers.service.connection.ServiceConnection; |
||||||
|
import org.springframework.boot.testsupport.container.HazelcastContainer; |
||||||
|
import org.springframework.boot.testsupport.container.TestImage; |
||||||
|
import org.springframework.context.annotation.Configuration; |
||||||
|
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; |
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat; |
||||||
|
|
||||||
|
/** |
||||||
|
* Tests for {@link HazelcastContainerConnectionDetailsFactory}. |
||||||
|
* |
||||||
|
* @author Dmytro Nosan |
||||||
|
*/ |
||||||
|
@SpringJUnitConfig |
||||||
|
@Testcontainers(disabledWithoutDocker = true) |
||||||
|
class HazelcastContainerConnectionDetailsFactoryIntegrationTests { |
||||||
|
|
||||||
|
@Container |
||||||
|
@ServiceConnection |
||||||
|
static final HazelcastContainer hazelcast = TestImage.container(HazelcastContainer.class); |
||||||
|
|
||||||
|
@Autowired(required = false) |
||||||
|
private HazelcastConnectionDetails connectionDetails; |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private HazelcastInstance hazelcastInstance; |
||||||
|
|
||||||
|
@Test |
||||||
|
void connectionCanBeMadeToHazelcastContainer() { |
||||||
|
assertThat(this.connectionDetails).isNotNull(); |
||||||
|
IMap<String, String> map = this.hazelcastInstance.getMap(UUID.randomUUID().toString()); |
||||||
|
map.put("test", "containers"); |
||||||
|
assertThat(map.get("test")).isEqualTo("containers"); |
||||||
|
} |
||||||
|
|
||||||
|
@Configuration(proxyBeanMethods = false) |
||||||
|
@ImportAutoConfiguration(HazelcastAutoConfiguration.class) |
||||||
|
static class TestConfiguration { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,76 @@ |
|||||||
|
/* |
||||||
|
* 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.testcontainers.service.connection.hazelcast; |
||||||
|
|
||||||
|
import java.util.Map; |
||||||
|
import java.util.Optional; |
||||||
|
|
||||||
|
import com.hazelcast.client.config.ClientConfig; |
||||||
|
import org.testcontainers.containers.Container; |
||||||
|
import org.testcontainers.containers.GenericContainer; |
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.hazelcast.HazelcastConnectionDetails; |
||||||
|
import org.springframework.boot.testcontainers.service.connection.ContainerConnectionDetailsFactory; |
||||||
|
import org.springframework.boot.testcontainers.service.connection.ContainerConnectionSource; |
||||||
|
import org.springframework.boot.testcontainers.service.connection.ServiceConnection; |
||||||
|
|
||||||
|
/** |
||||||
|
* {@link ContainerConnectionDetailsFactory} to create {@link HazelcastConnectionDetails} |
||||||
|
* from a {@link ServiceConnection @ServiceConnection}-annotated {@link GenericContainer} |
||||||
|
* using the {@code "hazelcast/hazelcast"} image. |
||||||
|
* |
||||||
|
* @author Dmytro Nosan |
||||||
|
*/ |
||||||
|
class HazelcastContainerConnectionDetailsFactory |
||||||
|
extends ContainerConnectionDetailsFactory<Container<?>, HazelcastConnectionDetails> { |
||||||
|
|
||||||
|
private static final int DEFAULT_PORT = 5701; |
||||||
|
|
||||||
|
private static final String CLUSTER_NAME_ENV = "HZ_CLUSTERNAME"; |
||||||
|
|
||||||
|
HazelcastContainerConnectionDetailsFactory() { |
||||||
|
super("hazelcast/hazelcast", "com.hazelcast.client.config.ClientConfig"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected HazelcastConnectionDetails getContainerConnectionDetails(ContainerConnectionSource<Container<?>> source) { |
||||||
|
return new HazelcastContainerConnectionDetails(source); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* {@link HazelcastConnectionDetails} backed by a {@link ContainerConnectionSource}. |
||||||
|
*/ |
||||||
|
private static final class HazelcastContainerConnectionDetails extends ContainerConnectionDetails<Container<?>> |
||||||
|
implements HazelcastConnectionDetails { |
||||||
|
|
||||||
|
private HazelcastContainerConnectionDetails(ContainerConnectionSource<Container<?>> source) { |
||||||
|
super(source); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public ClientConfig getClientConfig() { |
||||||
|
ClientConfig config = new ClientConfig(); |
||||||
|
Container<?> container = getContainer(); |
||||||
|
Map<String, String> env = container.getEnvMap(); |
||||||
|
Optional.ofNullable(env.get(CLUSTER_NAME_ENV)).ifPresent(config::setClusterName); |
||||||
|
config.getNetworkConfig().addAddress(container.getHost() + ":" + container.getMappedPort(DEFAULT_PORT)); |
||||||
|
return config; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,20 @@ |
|||||||
|
/* |
||||||
|
* 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
/** |
||||||
|
* Support for testcontainers Hazelcast service connections. |
||||||
|
*/ |
||||||
|
package org.springframework.boot.testcontainers.service.connection.hazelcast; |
||||||
@ -0,0 +1,36 @@ |
|||||||
|
/* |
||||||
|
* 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.testsupport.container; |
||||||
|
|
||||||
|
import org.testcontainers.containers.GenericContainer; |
||||||
|
import org.testcontainers.utility.DockerImageName; |
||||||
|
|
||||||
|
/** |
||||||
|
* A {@link GenericContainer} for Hazelcast. |
||||||
|
* |
||||||
|
* @author Dmytro Nosan |
||||||
|
*/ |
||||||
|
public final class HazelcastContainer extends GenericContainer<HazelcastContainer> { |
||||||
|
|
||||||
|
private static final int DEFAULT_PORT = 5701; |
||||||
|
|
||||||
|
public HazelcastContainer(DockerImageName dockerImageName) { |
||||||
|
super(dockerImageName); |
||||||
|
addExposedPorts(DEFAULT_PORT); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
Loading…
Reference in new issue