Skip to content

Commit 2b61912

Browse files
Add Hazelcast Example (#6117)
A simple Hazelcast example using both a single container and a cluster with two nodes. Fixes #6115
1 parent a25da3d commit 2b61912

File tree

5 files changed

+155
-0
lines changed

5 files changed

+155
-0
lines changed

docs/examples.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
Examples of different use cases provided by Testcontainers can be found below:
44

5+
- [Hazelcast](https://github.com/testcontainers/testcontainers-java/tree/main/examples/hazelcast)
56
- [Kafka Cluster with multiple brokers](https://github.com/testcontainers/testcontainers-java/tree/main/examples/kafka-cluster)
67
- [Linked containers](https://github.com/testcontainers/testcontainers-java/tree/main/examples/linked-container)
78
- [Neo4j](https://github.com/testcontainers/testcontainers-java/tree/main/examples/neo4j-container)

examples/hazelcast/build.gradle

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
plugins {
2+
id 'java'
3+
}
4+
5+
repositories {
6+
mavenCentral()
7+
}
8+
9+
dependencies {
10+
testImplementation 'org.testcontainers:testcontainers'
11+
testImplementation 'com.hazelcast:hazelcast:5.2.0'
12+
testImplementation 'ch.qos.logback:logback-classic:1.3.4'
13+
testImplementation 'org.assertj:assertj-core:3.23.1'
14+
}
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
package org.testcontainers.examples;
2+
3+
import com.hazelcast.client.HazelcastClient;
4+
import com.hazelcast.client.config.ClientConfig;
5+
import com.hazelcast.core.HazelcastInstance;
6+
import org.junit.After;
7+
import org.junit.Test;
8+
import org.testcontainers.containers.GenericContainer;
9+
import org.testcontainers.containers.Network;
10+
import org.testcontainers.containers.wait.strategy.Wait;
11+
import org.testcontainers.lifecycle.Startables;
12+
import org.testcontainers.utility.DockerImageName;
13+
14+
import java.util.concurrent.BlockingQueue;
15+
16+
import static org.assertj.core.api.Assertions.assertThat;
17+
18+
/**
19+
* Examples with Hazelcast using both a single container and a cluster with two containers.
20+
*/
21+
public class HazelcastTest {
22+
23+
// Hazelcast values
24+
private static final String HZ_IMAGE_NAME = "hazelcast/hazelcast:5.2.0";
25+
26+
private static final String HZ_CLUSTERNAME_ENV_NAME = "HZ_CLUSTERNAME";
27+
28+
private static final String HZ_NETWORK_JOIN_AZURE_ENABLED_ENV_NAME = "HZ_NETWORK_JOIN_AZURE_ENABLED";
29+
30+
private static final String HZ_NETWORK_JOIN_MULTICAST_ENABLED_ENV_NAME = "HZ_NETWORK_JOIN_MULTICAST_ENABLED";
31+
32+
private static final int DEFAULT_EXPOSED_PORT = 5701;
33+
34+
// Test values
35+
private static final String CLUSTER_STARTUP_LOG_MESSAGE_REGEX = ".*Members \\{size:2.*";
36+
37+
private static final String HOST_PORT_SEPARATOR = ":";
38+
39+
private static final String TEST_QUEUE_NAME = "test-queue";
40+
41+
private static final String TEST_CLUSTER_NAME = "test-cluster";
42+
43+
private static final String TEST_VALUE = "Hello!";
44+
45+
private static final String FALSE_VALUE = "false";
46+
47+
private static final String TRUE_VALUE = "true";
48+
49+
@After
50+
public void cleanUp() {
51+
HazelcastClient.shutdownAll();
52+
}
53+
54+
@Test
55+
public void singleHazelcastContainer() {
56+
try (
57+
GenericContainer<?> container = new GenericContainer<>(DockerImageName.parse(HZ_IMAGE_NAME))
58+
.withExposedPorts(DEFAULT_EXPOSED_PORT)
59+
) {
60+
container.start();
61+
assertThat(container.isRunning()).isTrue();
62+
63+
ClientConfig clientConfig = new ClientConfig();
64+
clientConfig
65+
.getNetworkConfig()
66+
.addAddress(container.getHost() + HOST_PORT_SEPARATOR + container.getFirstMappedPort());
67+
HazelcastInstance client = HazelcastClient.newHazelcastClient(clientConfig);
68+
69+
BlockingQueue<String> queue = client.getQueue(TEST_QUEUE_NAME);
70+
queue.put(TEST_VALUE);
71+
assertThat(queue.take()).isEqualTo(TEST_VALUE);
72+
} catch (InterruptedException e) {
73+
Thread.currentThread().interrupt();
74+
throw new RuntimeException("Interrupted during singleHazelcastContainer test", e);
75+
}
76+
}
77+
78+
@Test
79+
public void hazelcastCluster() {
80+
Network network = Network.newNetwork();
81+
try (
82+
GenericContainer<?> container1 = new GenericContainer<>(DockerImageName.parse(HZ_IMAGE_NAME))
83+
.withExposedPorts(DEFAULT_EXPOSED_PORT)
84+
.withEnv(HZ_CLUSTERNAME_ENV_NAME, TEST_CLUSTER_NAME)
85+
// Flags necessary to run on Github Actions which runs on an Azure VM
86+
.withEnv(HZ_NETWORK_JOIN_AZURE_ENABLED_ENV_NAME, FALSE_VALUE)
87+
.withEnv(HZ_NETWORK_JOIN_MULTICAST_ENABLED_ENV_NAME, TRUE_VALUE)
88+
.waitingFor(Wait.forLogMessage(CLUSTER_STARTUP_LOG_MESSAGE_REGEX, 1))
89+
.withNetwork(network);
90+
GenericContainer<?> container2 = new GenericContainer<>(DockerImageName.parse(HZ_IMAGE_NAME))
91+
.withExposedPorts(DEFAULT_EXPOSED_PORT)
92+
.withEnv(HZ_CLUSTERNAME_ENV_NAME, TEST_CLUSTER_NAME)
93+
// Flags necessary to run on Github Actions which runs on an Azure VM
94+
.withEnv(HZ_NETWORK_JOIN_AZURE_ENABLED_ENV_NAME, FALSE_VALUE)
95+
.withEnv(HZ_NETWORK_JOIN_MULTICAST_ENABLED_ENV_NAME, TRUE_VALUE)
96+
.waitingFor(Wait.forLogMessage(CLUSTER_STARTUP_LOG_MESSAGE_REGEX, 1))
97+
.withNetwork(network)
98+
) {
99+
Startables.deepStart(container1, container2).join();
100+
assertThat(container1.isRunning()).isTrue();
101+
assertThat(container2.isRunning()).isTrue();
102+
103+
ClientConfig clientConfig = new ClientConfig();
104+
clientConfig
105+
.setClusterName(TEST_CLUSTER_NAME)
106+
.getNetworkConfig()
107+
// Uncomment the next line to remove the "WARNING: ...Could not connect to member..." message
108+
//.setSmartRouting(false)
109+
.addAddress(container1.getHost() + HOST_PORT_SEPARATOR + container1.getFirstMappedPort())
110+
.addAddress(container2.getHost() + HOST_PORT_SEPARATOR + container2.getFirstMappedPort());
111+
112+
HazelcastInstance client = HazelcastClient.newHazelcastClient(clientConfig);
113+
114+
assertThat(client.getCluster().getMembers()).hasSize(2);
115+
116+
BlockingQueue<String> queue = client.getQueue(TEST_QUEUE_NAME);
117+
queue.put(TEST_VALUE);
118+
119+
assertThat(queue.take()).isEqualTo(TEST_VALUE);
120+
} catch (InterruptedException e) {
121+
Thread.currentThread().interrupt();
122+
throw new RuntimeException("Interrupted during hazelcastCluster test", e);
123+
}
124+
}
125+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<configuration>
2+
3+
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
4+
<!-- encoders are assigned the type
5+
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
6+
<encoder>
7+
<pattern>%d{HH:mm:ss.SSS} %-5level %logger - %msg%n</pattern>
8+
</encoder>
9+
</appender>
10+
11+
<root level="INFO">
12+
<appender-ref ref="STDOUT"/>
13+
</root>
14+
</configuration>

examples/settings.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ include 'cucumber'
3232
include 'spring-boot-kotlin-redis'
3333
include 'immudb'
3434
include 'zookeeper'
35+
include 'hazelcast'
3536

3637
ext.isCI = System.getenv("CI") != null
3738

0 commit comments

Comments
 (0)