Skip to content

Commit d959bf8

Browse files
authored
Guide update (#16)
* Add a main method class to Initial folder A Java class with a main method class is required to build the application with CI. Additionally, the Initial folder is meant to mirror the content that is donwloaded from Spring Initializr, which comes with a main method class. * Add CI file for GitHub Actions * Include Docker Compose Support This commit implements Spring Boot Docker Compose Support to run the externaly Redis container. This simplifies the learning experince and makes the guide more repeatable. * Rewrite content about running the example The new content will walk the user through 4 different ways to build the application. First through a standalone jar file, next through a docker container, next through a native compile, and finally through a native container. * Replace Lombok with Record Lombok was initially used to reduce boilerplate code before Record functionality was introduced in Java. Now that we have records, we can switch out Lombok for Java records and still have no boilerplate code in the Coffee class. In general, the fewer dependencies that we have the more the learner can focus on the core teaching. * Polish for README * Add dependabot and remove Jenkins
1 parent b7e9afd commit d959bf8

File tree

14 files changed

+166
-205
lines changed

14 files changed

+166
-205
lines changed

.github/dependabot.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
version: 2
2+
updates:
3+
4+
- package-ecosystem: "maven"
5+
directories:
6+
- "/initial"
7+
- "/complete"
8+
ignore:
9+
- dependency-name: "*"
10+
update-types: ["version-update:semver-patch"]
11+
schedule:
12+
interval: "monthly"
13+
target-branch: "main"
14+
groups:
15+
guide-dependencies-maven:
16+
patterns:
17+
- "*"
18+
19+
- package-ecosystem: "gradle"
20+
directories:
21+
- "/initial"
22+
- "/complete"
23+
ignore:
24+
- dependency-name: "*"
25+
update-types: ["version-update:semver-patch"]
26+
schedule:
27+
interval: "monthly"
28+
target-branch: "main"
29+
groups:
30+
guide-dependencies-gradle:
31+
patterns:
32+
- "*"
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
name: CI Build
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
branches:
9+
- main
10+
11+
jobs:
12+
build:
13+
uses: spring-guides/getting-started-macros/.github/workflows/build_initial_complete_maven_gradle.yml@main

Jenkinsfile

Lines changed: 0 additions & 44 deletions
This file was deleted.

README.adoc

Lines changed: 87 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -2,108 +2,62 @@
22
:icons: font
33
:source-highlighter: prettify
44
:project_id: gs-spring-data-reactive-redis
5+
:java_version: 17
6+
:build_system: maven
7+
:build_name: demo
8+
:build_version: 0.0.1-SNAPSHOT
9+
:network_container: guide-redis
10+
511
This guide walks you through the process of creating a functional reactive application that uses Spring Data to interact with Redis using the non-blocking Lettuce driver.
612

713
== What You Will Build
814

915
You'll build a Spring application that uses https://projects.spring.io/spring-data-redis/[Spring Data Redis] and https://projectreactor.io/[Project Reactor] to interact with a Redis data store reactively, storing and retrieving `Coffee` objects without blocking. This application uses Reactor's `Publisher` implementations based upon the Reactive Streams specification, namely `Mono` (for a Publisher returning 0 or 1 value) and `Flux` (for a Publisher returning 0 to n values).
1016

11-
== What You Need
17+
include::https://raw.githubusercontent.com/spring-guides/getting-started-macros/main/guide_introduction.adoc[]
1218

13-
:java_version: 17
14-
include::https://raw.githubusercontent.com/spring-guides/getting-started-macros/main/prereq_editor_jdk_buildtools.adoc[]
19+
== Setting up the Redis Server
20+
21+
Before you can build a messaging application, you need to set up the server to
22+
handle receiving and sending messages.
23+
include::https://raw.githubusercontent.com/spring-guides/getting-started-macros/main/docker_compose_support.adoc[]
1524

16-
include::https://raw.githubusercontent.com/spring-guides/getting-started-macros/main/how_to_complete_this_guide.adoc[]
25+
If you choose to run the Redis server yourself instead of using Spring Boot Docker Compose support, you have a few options:
26+
- https://redis.io/download[Download the server] and manually run it
27+
- Install with Homebrew, if you use a Mac
28+
- Manually run the `compose.yaml` file with `docker compose up`
29+
30+
If you go with any of these alternate approaches, you should remove the `spring-boot-docker-compose` dependency from the Maven or Gradle build file.
31+
You also need to add configuration to an `application.properties` file, as described in greater detail in the <<_preparing_to_build_the_application>> section.
32+
As mentioned earlier, this guide assumes that you use Docker Compose support in Spring Boot, so additional changes to `application.properties` are not required at this point.
1733

1834
[[scratch]]
1935
== Starting with Spring Initializr
2036

21-
You can use this https://start.spring.io/#!type=maven-project&language=java&packaging=jar&jvmVersion=17&groupId=com.example&artifactId=demo&name=demo&description=Demo%20project%20for%20Spring%20Boot&packageName=com.example.demo&dependencies=data-redis-reactive,lombok,webflux[pre-initialized project] and click Generate to download a ZIP file. This project is configured to fit the examples in this tutorial.
37+
You can use this https://start.spring.io/#!type=maven-project&language=java&packaging=jar&groupId=com.example&artifactId=demo&name=demo&description=Demo%20project%20for%20Spring%20Boot&packageName=com.example.demo&dependencies=data-redis-reactive,webflux,docker-compose[pre-initialized project] and click Generate to download a ZIP file. This project is configured to fit the examples in this tutorial.
2238

2339
To manually initialize the project:
2440

2541
. Navigate to https://start.spring.io.
2642
This service pulls in all the dependencies you need for an application and does most of the setup for you.
2743
. Choose either Gradle or Maven and the language you want to use. This guide assumes that you chose Java.
28-
. Click *Dependencies* and select *Spring Reactive Web*, *Spring Data Reactive Redis*, and *Lombok*.
44+
. Click *Dependencies* and select *Spring Reactive Web*, *Spring Data Reactive Redis*, and *Docker Compose Support*.
2945
. Click *Generate*.
3046
. Download the resulting ZIP file, which is an archive of a web application that is configured with your choices.
3147

3248
NOTE: If your IDE has the Spring Initializr integration, you can complete this process from your IDE.
3349

34-
NOTE: You can also fork the project from Github and open it in your IDE or other editor.
35-
36-
[[scratch]]
37-
== Standing up a Redis Server
38-
39-
Before you can build a messaging application, you need to set up the server that will
40-
handle receiving and sending messages.
41-
42-
Redis is an open source, BSD-licensed, key-value data store that also comes with a
43-
messaging system. The server is freely available at https://redis.io/download. You can
44-
download it manually, or, if you use a Mac, with Homebrew, by running the following
45-
command in a terminal window:
46-
47-
====
48-
[source,bash]
49-
----
50-
brew install redis
51-
----
52-
====
53-
54-
Once you unpack Redis, you can launch it with its default settings by running the following command:
55-
56-
====
57-
[source,bash]
58-
----
59-
redis-server
60-
----
61-
====
62-
63-
You should see a message similar to the following:
64-
65-
====
66-
[source,text]
67-
----
68-
[35142] 01 May 14:36:28.939 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
69-
[35142] 01 May 14:36:28.940 * Max number of open files set to 10032
70-
_._
71-
_.-``__ ''-._
72-
_.-`` `. `_. ''-._ Redis 2.6.12 (00000000/0) 64 bit
73-
.-`` .-```. ```\/ _.,_ ''-._
74-
( ' , .-` | `, ) Running in stand alone mode
75-
|`-._`-...-` __...-.``-._|'` _.-'| Port: 6379
76-
| `-._ `._ / _.-' | PID: 35142
77-
`-._ `-._ `-./ _.-' _.-'
78-
|`-._`-._ `-.__.-' _.-'_.-'|
79-
| `-._`-._ _.-'_.-' | https://redis.io
80-
`-._ `-._`-.__.-'_.-' _.-'
81-
|`-._`-._ `-.__.-' _.-'_.-'|
82-
| `-._`-._ _.-'_.-' |
83-
`-._ `-._`-.__.-'_.-' _.-'
84-
`-._ `-.__.-' _.-'
85-
`-._ _.-'
86-
`-.__.-'
87-
88-
[35142] 01 May 14:36:28.941 # Server started, Redis version 2.6.12
89-
[35142] 01 May 14:36:28.941 * The server is now ready to accept connections on port 6379
90-
----
91-
====
92-
9350
[[initial]]
9451
== Create a Domain Class
9552

96-
Create a class representing a type of coffee we wish to stock in our coffee catalog:
53+
Create a record representing a type of coffee we wish to stock in our coffee catalog:
9754

9855
`src/main/java/com/example/demo/Coffee.java`
9956
[source,java,tabsize=2]
10057
----
10158
include::complete/src/main/java/com/example/demo/Coffee.java[]
10259
----
10360

104-
NOTE: I use Lombok in this example to eliminate the boilerplate code for constructors and so-called "data class" methods ( accessors/mutators, `equals()`, `toString()`, & `hashCode()`).
105-
106-
10761
== Create a Configuration Class
10862

10963
Create a class that includes Spring Beans that support reactive Redis operations:
@@ -114,7 +68,6 @@ Create a class that includes Spring Beans that support reactive Redis operations
11468
include::complete/src/main/java/com/example/demo/CoffeeConfiguration.java[]
11569
----
11670

117-
11871
== Create a Spring Bean to Load Data
11972

12073
Create a Spring Bean to load sample data for our application when we start it:
@@ -138,29 +91,83 @@ Create a `RestController` to provide an external interface for our application:
13891
include::complete/src/main/java/com/example/demo/CoffeeController.java[]
13992
----
14093

94+
== Run the Application
14195

142-
== Make the Application Executable
96+
You can run the main method through your IDE.
97+
Note that, if you have cloned the project from the solution repository, your IDE may look in the wrong place for the `compose.yaml` file.
98+
You can configure your IDE to look in the correct place or you could use the command line to run the application.
99+
The `./gradlew bootRun` and `./mvnw spring-boot:run` commands will launch the application and automatically find the compose.yaml file.
143100

144-
Although you can package this service as a traditional link:/understanding/WAR[WAR] file for deployment to an external application server, the simpler approach shown here creates a standalone application. You package everything in a single, executable JAR file, driven by a good old Java `main()` method. Along the way, you use Spring's support for embedding the link:/understanding/Netty[Netty] an asynchronous "container" as the HTTP runtime instead of deploying to an external instance.
101+
== Test the Application
145102

103+
With the application running, run the following command from a new terminal:
104+
[source,bash]
105+
```
106+
curl http://localhost:8080/coffees
107+
```
146108

147-
`src/main/java/com/example/demo/DemoApplication.java`
148-
[source,java,tabsize=2]
109+
You should see the following output:
110+
[source,json]
111+
```
112+
[
113+
{
114+
"id": "04ce0843-c9f8-40f6-942f-1ff643c1d426",
115+
"name": "Jet Black Redis"
116+
},
117+
{
118+
"id": "e2a0d798-5fa4-48a2-a45c-7770d8bb82bf",
119+
"name": "Black Alert Redis"
120+
},
121+
{
122+
"id": "13f13e3a-0798-44b7-8ae4-b319b227bb19",
123+
"name": "Darth Redis"
124+
}
125+
]
126+
```
127+
128+
== Preparing to Build the Application
129+
130+
To run the code without Spring Boot Docker Compose support, you need a version of Redis running locally to connect to.
131+
To do this, you can use Docker Compose, but you must first make two changes to the `compose.yaml` file.
132+
First, modify the `ports` entry in `compose.yaml` to be `'6379:6379'`.
133+
Second, add a `container_name`.
134+
135+
The `compose.yaml` should now be:
149136
----
150-
include::complete/src/main/java/com/example/demo/DemoApplication.java[]
137+
services:
138+
redis:
139+
container_name: 'guide-redis'
140+
image: 'redis:latest'
141+
ports:
142+
- '6379:6379'
151143
----
152144

153-
include::https://raw.githubusercontent.com/spring-guides/getting-started-macros/main/spring-boot-application.adoc[]
145+
You can now run `docker compose up` to start the Redis server.
146+
Now you should have an external Redis server that is ready to accept requests.
147+
You can rerun the application and see the same output using your external Redis server.
154148

155-
include::https://raw.githubusercontent.com/spring-guides/getting-started-macros/main/build_an_executable_jar_subhead.adoc[]
149+
NOTE: No configuration is required in the `application.properties` file because the default values match the Redis server configuration in `compose.yaml`. Specifically, the properties `spring.data.redis.host` and `spring.data.redis.port` default to `localhost` and `6379` respectively.
156150

157-
include::https://raw.githubusercontent.com/spring-guides/getting-started-macros/main/build_an_executable_jar_with_both.adoc[]
151+
include::https://raw.githubusercontent.com/spring-guides/getting-started-macros/main/build_and_execute_guide.adoc[]
158152

153+
== Test the Application in Docker
159154

160-
== Test the application
155+
If you ran the application using a Docker instruction (shown earlier), a simple curl command from a terminal or command line will no longer work.
156+
This is because we run our containers in a https://docs.docker.com/compose/networking/[Docker network] that is not accessible from the terminal or command line. To run curl commands, we can start a third container to run our curl commands and attach it to the same network.
161157

162-
Now that the application is running, you can test it by accessing `http://localhost:8080/coffees` from HTTPie, curl, or your favorite browser.
158+
First, obtain an interactive shell to a new container that runs on the same network as the Redis container and the application:
159+
[source, bash]
160+
----
161+
docker run --rm --network container:guide-redis -it alpine
162+
----
163+
164+
Next, from the shell inside the container, install curl:
165+
[source, bash]
166+
----
167+
apk add curl
168+
----
163169

170+
Finally, you can run the curl commands as described in <<_test_the_application>>.
164171

165172
== Summary
166173

complete/build.gradle

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@ repositories {
2121
dependencies {
2222
implementation 'org.springframework.boot:spring-boot-starter-data-redis-reactive'
2323
implementation 'org.springframework.boot:spring-boot-starter-webflux'
24-
compileOnly 'org.projectlombok:lombok'
25-
annotationProcessor 'org.projectlombok:lombok'
24+
developmentOnly 'org.springframework.boot:spring-boot-docker-compose'
2625
testImplementation 'org.springframework.boot:spring-boot-starter-test'
2726
testImplementation 'io.projectreactor:reactor-test'
2827
}

complete/compose.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
services:
2+
redis:
3+
image: 'redis:latest'
4+
ports:
5+
- '6379'

complete/pom.xml

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@
2525
<groupId>org.springframework.boot</groupId>
2626
<artifactId>spring-boot-starter-webflux</artifactId>
2727
</dependency>
28-
2928
<dependency>
30-
<groupId>org.projectlombok</groupId>
31-
<artifactId>lombok</artifactId>
29+
<groupId>org.springframework.boot</groupId>
30+
<artifactId>spring-boot-docker-compose</artifactId>
31+
<scope>runtime</scope>
3232
<optional>true</optional>
3333
</dependency>
3434
<dependency>
@@ -45,18 +45,7 @@
4545

4646
<build>
4747
<plugins>
48-
<plugin>
49-
<groupId>org.springframework.boot</groupId>
50-
<artifactId>spring-boot-maven-plugin</artifactId>
51-
<configuration>
52-
<excludes>
53-
<exclude>
54-
<groupId>org.projectlombok</groupId>
55-
<artifactId>lombok</artifactId>
56-
</exclude>
57-
</excludes>
58-
</configuration>
59-
</plugin>
48+
6049
</plugins>
6150
</build>
6251

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,4 @@
11
package com.example.demo;
22

3-
import lombok.AllArgsConstructor;
4-
import lombok.Data;
5-
import lombok.NoArgsConstructor;
6-
7-
@Data
8-
@NoArgsConstructor
9-
@AllArgsConstructor
10-
public class Coffee {
11-
private String id;
12-
private String name;
3+
public record Coffee(String id, String name) {
134
}

0 commit comments

Comments
 (0)