Skip to content

Commit a88446f

Browse files
authored
Merge pull request #123 from TomaszGaweda/refresh-2025
Refresh of the guide [DEX-296]
2 parents a7b3bc5 + 21eee7c commit a88446f

File tree

12 files changed

+158
-81
lines changed

12 files changed

+158
-81
lines changed

.github/workflows/build.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
runs-on: ubuntu-latest
1313
strategy:
1414
matrix:
15-
java: [ '8' ]
15+
java: [ '17', '23' ]
1616
architecture: [ 'x64' ]
1717
name: Build with JDK ${{ matrix.java }} on ${{ matrix.architecture }}
1818
steps:
@@ -30,5 +30,5 @@ jobs:
3030
restore-keys: ${{ runner.os }}-maven-
3131

3232
- name: Run Tests
33-
run: mvn verify -Ptests
33+
run: mvn verify
3434

.run/Template JUnit.run.xml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<component name="ProjectRunConfigurationManager">
2+
<configuration default="true" type="JUnit" factoryName="JUnit">
3+
<module name="hazelcast-embedded-springboot" />
4+
<option name="MAIN_CLASS_NAME" value="" />
5+
<option name="METHOD_NAME" value="" />
6+
<option name="TEST_OBJECT" value="class" />
7+
<option name="VM_PARAMETERS" value="-ea -Djava.net.preferIPv4Stack=true" />
8+
<method v="2">
9+
<option name="Make" enabled="true" />
10+
</method>
11+
</configuration>
12+
</component>

docs/modules/ROOT/pages/hazelcast-embedded-springboot.adoc

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,58 +30,75 @@ If Hazelcast is on the classpath and a suitable configuration is found, Spring B
3030
include::ROOT:example$hazelcast-embedded-springboot/pom.xml[tag=hazelcast-dep]
3131
----
3232

33-
Hazelcast configuration (`hazelcast.yaml`) is placed in the `src/main/resources/` directory. You only need to auto-wire the `HazelcastInstance` bean in the `CommandController` and use it to access to Hazelcast data structures:
33+
Hazelcast configuration (`hazelcast.yaml`) is placed in the `src/main/resources/` directory. You only need to define `map` bean, if you want to autowire the IMap instance:
34+
[source,java,indent=0]
35+
----
36+
include::ROOT:example$hazelcast-embedded-springboot/src/main/java/guides/hazelcast/springboot/HazelcastApplication.java[tag=imap-bean]
37+
----
38+
39+
Bean will have name "map" and can be autowired by `IMap` type (if it's the only IMap added as bean).
40+
41+
Now you can autowire the `IMap` bean in the `CommandController` and use it to access the Hazelcast structure:
3442

3543
[source,java,indent=0]
3644
----
3745
include::ROOT:example$hazelcast-embedded-springboot/src/main/java/guides/hazelcast/springboot/CommandController.java[]
3846
----
3947

48+
Please notice, that we've used `@Qualifier("map")` - it's strictly speaking optional, but once you add more IMaps, you will need to distinguish which map you want to autowire.
49+
4050
== Run the Sample Application
4151

4252
Run the application using Maven in a terminal:
4353

54+
[source,bash]
4455
----
45-
mvn spring-boot:run -Dspring-boot.run.jvmArguments="-Dserver.port=8080"
56+
mvn spring-boot:run -Dspring-boot.run.jvmArguments="-Dserver.port=8080 -Djava.net.preferIPv4Stack=true"
4657
----
4758

4859
Then, rerun the application in another terminal.
4960

5061
NOTE: Notice the different value for the `server.port` argument.
5162

63+
NOTE: We've used `-Djava.net.preferIPv4Stack=true`, because on some platforms there are problems with multicast on IPv6. Adding this option ensures smooth run when learning.
64+
65+
[source,bash]
5266
----
53-
mvn spring-boot:run -Dspring-boot.run.jvmArguments="-Dserver.port=8081"
67+
mvn spring-boot:run -Dspring-boot.run.jvmArguments="-Dserver.port=8081 -Djava.net.preferIPv4Stack=true"
5468
----
5569

5670
After both application instances are initialized, you should see that the Hazelcast cluster is formed:
5771

58-
```bash
72+
[source,bash]
73+
----
5974
Members {size:2, ver:2} [
6075
Member [192.168.1.64]:5701 - 520aec3f-58a6-4fcb-a3c7-498dcf37d8ff
6176
Member [192.168.1.64]:5702 - 5c03e467-d457-4847-b49a-745a335db557 this
6277
]
63-
```
78+
----
6479

6580
Now, you can issue HTTP requests to put and get data back. Run the following command to put the data into a Hazelcast distributed map:
6681

67-
```bash
82+
[source,bash]
83+
----
6884
curl --data "key=key1&value=hazelcast" "localhost:8080/put"
69-
```
85+
----
7086

7187
You will see the value in the output. Then run the command below to get the data back. Please note that the call is made to the other application instance:
7288

73-
```bash
89+
[source,bash]
90+
----
7491
curl "localhost:8081/get?key=key1"
75-
```
92+
----
7693

77-
Again, you will see the value in the output since the data is distributed among Hazelcast cluster instances and can be accessed from any of them.
94+
Again, you will see the value in the output (`{"value":"hazelcast"}`), because the data is distributed among Hazelcast cluster instances and can be accessed from any of them.
7895

7996
== Test the Application
8097

8198
To run the integration tests, run the following command in terminal. But before, make sure to kill the running application instances.
8299

83100
----
84-
mvn verify -Ptests
101+
mvn verify
85102
----
86103

87104
If the tests pass, you’ll see a similar output to the following:

pom.xml

Lines changed: 38 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,12 @@
1111
<parent>
1212
<groupId>org.springframework.boot</groupId>
1313
<artifactId>spring-boot-starter-parent</artifactId>
14-
<version>2.4.1</version>
15-
<relativePath/>
14+
<version>3.4.1</version>
1615
</parent>
1716

1817
<properties>
19-
<java.version>1.8</java.version>
20-
<hazelcast.version>5.3.2</hazelcast.version>
18+
<java.version>17</java.version>
19+
<hazelcast.version>5.5.0</hazelcast.version>
2120
</properties>
2221

2322
<build>
@@ -26,35 +25,34 @@
2625
<groupId>org.springframework.boot</groupId>
2726
<artifactId>spring-boot-maven-plugin</artifactId>
2827
</plugin>
28+
<plugin>
29+
<artifactId>maven-failsafe-plugin</artifactId>
30+
<version>3.5.2</version>
31+
<executions>
32+
<execution>
33+
<goals>
34+
<goal>integration-test</goal>
35+
<goal>verify</goal>
36+
</goals>
37+
</execution>
38+
</executions>
39+
<configuration>
40+
<argLine>-Djava.net.preferIPv4Stack=true</argLine>
41+
</configuration>
42+
</plugin>
2943
</plugins>
3044
</build>
3145

32-
<profiles>
33-
<profile>
34-
<id>tests</id>
35-
<build>
36-
<plugins>
37-
<plugin>
38-
<artifactId>maven-failsafe-plugin</artifactId>
39-
<version>2.22.2</version>
40-
<executions>
41-
<execution>
42-
<goals>
43-
<goal>integration-test</goal>
44-
<goal>verify</goal>
45-
</goals>
46-
</execution>
47-
</executions>
48-
</plugin>
49-
</plugins>
50-
</build>
51-
</profile>
52-
</profiles>
53-
5446
<dependencies>
5547
<dependency>
5648
<groupId>org.springframework.boot</groupId>
5749
<artifactId>spring-boot-starter-web</artifactId>
50+
<exclusions>
51+
<exclusion>
52+
<groupId>org.springframework.boot</groupId>
53+
<artifactId>spring-boot-starter-logging</artifactId>
54+
</exclusion>
55+
</exclusions>
5856
</dependency>
5957
<!-- tag::hazelcast-dep[] -->
6058
<dependency>
@@ -74,11 +72,24 @@
7472
<artifactId>spring-boot-starter-webflux</artifactId>
7573
<scope>test</scope>
7674
</dependency>
75+
<dependency>
76+
<groupId>org.springframework.boot</groupId>
77+
<artifactId>spring-boot-starter-log4j2</artifactId>
78+
</dependency>
79+
<dependency>
80+
<groupId>org.apache.logging.log4j</groupId>
81+
<artifactId>log4j-spring-boot</artifactId>
82+
</dependency>
7783
<dependency>
7884
<groupId>net.minidev</groupId>
7985
<artifactId>json-smart</artifactId>
80-
<version>2.3</version>
86+
<version>2.5.1</version>
8187
<scope>test</scope>
8288
</dependency>
89+
<dependency>
90+
<groupId>org.awaitility</groupId>
91+
<artifactId>awaitility</artifactId>
92+
<version>4.2.2</version>
93+
</dependency>
8394
</dependencies>
8495
</project>
Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,27 @@
11
package guides.hazelcast.springboot;
22

3-
import com.hazelcast.core.HazelcastInstance;
3+
import com.hazelcast.map.IMap;
44
import org.springframework.beans.factory.annotation.Autowired;
5+
import org.springframework.beans.factory.annotation.Qualifier;
56
import org.springframework.web.bind.annotation.GetMapping;
67
import org.springframework.web.bind.annotation.PostMapping;
78
import org.springframework.web.bind.annotation.RequestParam;
89
import org.springframework.web.bind.annotation.RestController;
910

10-
import java.util.concurrent.ConcurrentMap;
11-
1211
@RestController
1312
public class CommandController {
14-
@Autowired
15-
private HazelcastInstance hazelcastInstance;
16-
17-
private ConcurrentMap<String,String> retrieveMap() {
18-
return hazelcastInstance.getMap("map");
19-
}
13+
@Autowired @Qualifier("map")
14+
private IMap<String, String> map;
2015

2116
@PostMapping("/put")
2217
public CommandResponse put(@RequestParam(value = "key") String key, @RequestParam(value = "value") String value) {
23-
retrieveMap().put(key, value);
18+
map.put(key, value);
2419
return new CommandResponse(value);
2520
}
2621

2722
@GetMapping("/get")
2823
public CommandResponse get(@RequestParam(value = "key") String key) {
29-
String value = retrieveMap().get(key);
24+
String value = map.get(key);
3025
return new CommandResponse(value);
3126
}
3227
}
Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,4 @@
11
package guides.hazelcast.springboot;
22

3-
public class CommandResponse {
4-
5-
private String value;
6-
7-
public CommandResponse(String value) {
8-
this.value = value;
9-
}
10-
11-
public String getValue() {
12-
return value;
13-
}
14-
15-
public void setValue(String value) {
16-
this.value = value;
17-
}
3+
public record CommandResponse (String value) {
184
}

src/main/java/guides/hazelcast/springboot/HazelcastApplication.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package guides.hazelcast.springboot;
22

3+
import com.hazelcast.core.HazelcastInstance;
4+
import com.hazelcast.map.IMap;
35
import org.springframework.boot.SpringApplication;
46
import org.springframework.boot.autoconfigure.SpringBootApplication;
7+
import org.springframework.context.annotation.Bean;
58
import org.springframework.web.bind.annotation.RestController;
69

710
@SpringBootApplication
@@ -10,4 +13,11 @@ public class HazelcastApplication {
1013
public static void main(String[] args) {
1114
SpringApplication.run(HazelcastApplication.class, args);
1215
}
16+
17+
//tag::imap-bean[]
18+
@Bean
19+
public IMap<String, String> map(HazelcastInstance instance) {
20+
return instance.getMap("map");
21+
}
22+
//end::imap-bean[]
1323
}

src/main/resources/hazelcast.yaml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,8 @@
11
hazelcast:
2-
cluster-name: hazelcast-cluster
2+
cluster-name: hazelcast-cluster
3+
properties:
4+
hazelcast.logging.type: log4j2
5+
network:
6+
join:
7+
multicast:
8+
enabled: true

src/main/resources/log4j2.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Configuration status="ERROR">
3+
<Appenders>
4+
<Console name="Console" target="SYSTEM_OUT">
5+
<PatternLayout pattern="%d{ABSOLUTE} %5p |%X{test-name}| - [%c{1}] %t - %m%n" />
6+
</Console>
7+
</Appenders>
8+
<Loggers>
9+
<Root level="INFO">
10+
<AppenderRef ref="Console" />
11+
</Root>
12+
</Loggers>
13+
</Configuration>

src/test/java/guides/hazelcast/springboot/CommandControllerIT.java

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package guides.hazelcast.springboot;
22

3+
import com.hazelcast.config.Config;
34
import com.hazelcast.core.Hazelcast;
45
import com.hazelcast.core.HazelcastInstance;
56
import org.junit.jupiter.api.Test;
@@ -9,7 +10,9 @@
910
import org.springframework.test.context.junit.jupiter.SpringExtension;
1011
import org.springframework.test.web.reactive.server.WebTestClient;
1112

12-
import static org.junit.jupiter.api.Assertions.assertEquals;
13+
import java.time.Duration;
14+
15+
import static org.awaitility.Awaitility.await;
1316
import static org.springframework.http.HttpHeaders.ACCEPT;
1417
import static org.springframework.http.MediaType.APPLICATION_JSON;
1518
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
@@ -26,7 +29,11 @@ public class CommandControllerIT {
2629
@Test
2730
public void testPutRequest(){
2831
//when
29-
WebTestClient.ResponseSpec responseSpec = makePostRequest("/put?key={key}&value={value}", "key1", "value1");
32+
WebTestClient.ResponseSpec responseSpec = webTestClient
33+
.post()
34+
.uri("/put?key={key}&value={value}", "key1", "value1")
35+
.header(ACCEPT, APPLICATION_JSON_VALUE)
36+
.exchange();
3037

3138
//then
3239
responseSpec.expectStatus()
@@ -40,7 +47,11 @@ public void testPutRequest(){
4047
@Test
4148
public void testGetRequest(){
4249
//given
43-
makePostRequest("/put?key={key}&value={value}", "key1", "value1");
50+
webTestClient
51+
.post()
52+
.uri("/put?key={key}&value={value}", "key1", "value1")
53+
.header(ACCEPT, APPLICATION_JSON_VALUE)
54+
.exchange();
4455

4556
//when
4657
WebTestClient.ResponseSpec responseSpec = webTestClient
@@ -58,20 +69,21 @@ public void testGetRequest(){
5869
.jsonPath("$.value").isEqualTo("value1");
5970
}
6071

61-
private WebTestClient.ResponseSpec makePostRequest(String uri, Object... parameters) {
62-
return webTestClient
63-
.post()
64-
.uri(uri, parameters)
65-
.header(ACCEPT, APPLICATION_JSON_VALUE)
66-
.exchange();
67-
}
68-
6972
@Test
70-
public void testHazelcastCluster(){
73+
public void testHazelcastCluster() {
74+
Config config = Config.load();
75+
config.setProperty("hazelcast.logging.type", "log4j2");
76+
7177
//given
72-
Hazelcast.newHazelcastInstance();
78+
HazelcastInstance hz = Hazelcast.newHazelcastInstance();
7379

7480
//then
75-
assertEquals(2, hazelcastInstance.getCluster().getMembers().size());
81+
try {
82+
await()
83+
.atMost(Duration.ofMinutes(2))
84+
.until(() -> hazelcastInstance.getCluster().getMembers().size() == 2);
85+
} finally {
86+
hz.shutdown();
87+
}
7688
}
7789
}

0 commit comments

Comments
 (0)