Skip to content

Commit 79c92bd

Browse files
Revamp to 3.2.2
1 parent 46d92dd commit 79c92bd

File tree

13 files changed

+94
-78
lines changed

13 files changed

+94
-78
lines changed

.github/workflows/spring-boot-webflux-kotlin-coroutine.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ jobs:
2222
uses: actions/setup-java@v3
2323
with:
2424
distribution: 'temurin' # See 'Supported distributions' for available options
25-
java-version: '11'
25+
java-version: '17'
2626

2727
- name: Install dependencies, run tests, and collect coverage
28-
run: gradle clean build
28+
run: ./gradlew clean build
2929
- name: Upload coverage to Codecov
3030
uses: codecov/codecov-action@v3

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ COPY . .
99
RUN gradle assemble
1010

1111
# Container in which to run the application
12-
FROM eclipse-temurin:11.0.19_7-jdk-alpine
12+
FROM eclipse-temurin:17.0.10_7-jdk-alpine
1313

1414
# Copy the jar from the builder container into the run container
1515
COPY --from=builder /app/build/libs/spring-boot-webflux-kotlin-coroutine-*.jar spring-boot-webflux-kotlin-coroutine.jar

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
A sample of Spring boot WebFlux and Kotlin Coroutine with Handler and Router. In this sample, implementing Todo model, handler and router with database (MySQL) testing.
66

77
# Reqirements
8-
- Java 11
9-
- Docker 4.17.0 >=
10-
- gradle 7.4.1 >=
8+
- Java 17
9+
- Docker 4.26.1 >=
10+
- gradle 8.1.1 >=
1111

1212
# Getting Started
1313
Please make sure Docker is up and running.

build.gradle.kts

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,27 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
33
plugins {
44
java
55
jacoco
6-
id("io.freefair.lombok") version "6.6.1"
7-
id("org.springframework.boot") version "2.7.11"
8-
id("org.springdoc.openapi-gradle-plugin") version "1.6.0"
9-
id("io.spring.dependency-management") version "1.1.0"
10-
id("org.openapi.generator") version "6.5.0"
11-
12-
kotlin("jvm") version "1.7.22"
13-
kotlin("plugin.spring") version "1.7.22"
6+
id("org.springframework.boot") version "3.2.2"
7+
id("io.spring.dependency-management") version "1.1.4"
8+
id("org.springdoc.openapi-gradle-plugin") version "1.8.0"
9+
id("org.openapi.generator") version "7.2.0"
10+
11+
kotlin("jvm") version "1.9.22"
12+
kotlin("plugin.spring") version "1.9.22"
1413
}
1514

1615
group = "com.sennproject"
1716
version = "1.0.0"
18-
java.sourceCompatibility = JavaVersion.VERSION_11
17+
java.sourceCompatibility = JavaVersion.VERSION_17
1918

2019
repositories {
2120
mavenCentral()
2221
}
2322

24-
extra["kotestVersion"] = "5.5.5"
25-
extra["openAPIVersion"] = "1.6.15"
26-
extra["testcontainersVersion"] = "1.18.0"
27-
extra["coroutinesCoreVersion"] = "1.6.4"
23+
extra["kotestVersion"] = "5.8.0"
24+
extra["openAPIVersion"] = "1.7.0"
25+
extra["testcontainersVersion"] = "1.19.4"
26+
extra["coroutinesCoreVersion"] = "1.8.0-RC2"
2827

2928
dependencies {
3029
implementation("org.springframework.boot:spring-boot-starter-data-r2dbc")
@@ -49,19 +48,21 @@ dependencies {
4948
implementation("org.springdoc:springdoc-openapi-webflux-ui:${property("openAPIVersion")}")
5049

5150
// Database
52-
runtimeOnly("dev.miku:r2dbc-mysql:0.8.2.RELEASE")
51+
implementation("io.asyncer:r2dbc-mysql:1.0.6")
5352
runtimeOnly("com.mysql:mysql-connector-j:8.0.+")
53+
implementation("org.springframework.data:spring-data-commons")
54+
implementation("org.springframework.data:spring-data-relational")
5455

5556
// Test
5657
testImplementation("io.kotest:kotest-runner-junit5:${property("kotestVersion")}")
5758
testImplementation("io.kotest:kotest-assertions-core:${property("kotestVersion")}")
5859
testImplementation("io.kotest:kotest-property:${property("kotestVersion")}")
5960
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:${property("coroutinesCoreVersion")}")
60-
testImplementation("io.kotest.extensions:kotest-extensions-spring:1.1.2")
61+
testImplementation("io.kotest.extensions:kotest-extensions-spring:1.1.3")
6162

6263
testImplementation("org.springframework.boot:spring-boot-starter-test")
64+
testImplementation("org.springframework.boot:spring-boot-testcontainers")
6365
testImplementation("io.projectreactor:reactor-test")
64-
testImplementation("org.testcontainers:elasticsearch")
6566
testImplementation("org.testcontainers:junit-jupiter")
6667
testImplementation("org.testcontainers:mysql")
6768
testImplementation("org.testcontainers:r2dbc")
@@ -81,7 +82,7 @@ dependencyManagement {
8182
tasks.withType<KotlinCompile> {
8283
kotlinOptions {
8384
freeCompilerArgs = listOf("-Xjsr305=strict")
84-
jvmTarget = "11"
85+
jvmTarget = "17"
8586
}
8687
}
8788

gradle/wrapper/gradle-wrapper.jar

2.2 KB
Binary file not shown.
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
distributionBase=GRADLE_USER_HOME
22
distributionPath=wrapper/dists
3-
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.1-bin.zip
3+
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
4+
networkTimeout=10000
45
zipStoreBase=GRADLE_USER_HOME
56
zipStorePath=wrapper/dists

gradlew

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
# Darwin, MinGW, and NonStop.
5656
#
5757
# (3) This script is generated from the Groovy template
58-
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
58+
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
5959
# within the Gradle project.
6060
#
6161
# You can find Gradle at https://github.com/gradle/gradle/.
@@ -80,13 +80,10 @@ do
8080
esac
8181
done
8282

83-
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
84-
85-
APP_NAME="Gradle"
83+
# This is normally unused
84+
# shellcheck disable=SC2034
8685
APP_BASE_NAME=${0##*/}
87-
88-
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
89-
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
86+
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
9087

9188
# Use the maximum available, or set MAX_FD != -1 to use that value.
9289
MAX_FD=maximum
@@ -143,12 +140,16 @@ fi
143140
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
144141
case $MAX_FD in #(
145142
max*)
143+
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
144+
# shellcheck disable=SC3045
146145
MAX_FD=$( ulimit -H -n ) ||
147146
warn "Could not query maximum file descriptor limit"
148147
esac
149148
case $MAX_FD in #(
150149
'' | soft) :;; #(
151150
*)
151+
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
152+
# shellcheck disable=SC3045
152153
ulimit -n "$MAX_FD" ||
153154
warn "Could not set maximum file descriptor limit to $MAX_FD"
154155
esac
@@ -193,6 +194,10 @@ if "$cygwin" || "$msys" ; then
193194
done
194195
fi
195196

197+
198+
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
199+
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
200+
196201
# Collect all arguments for the java command;
197202
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
198203
# shell script including quotes and variable substitutions, so put them in
@@ -205,6 +210,12 @@ set -- \
205210
org.gradle.wrapper.GradleWrapperMain \
206211
"$@"
207212

213+
# Stop when "xargs" is not available.
214+
if ! command -v xargs >/dev/null 2>&1
215+
then
216+
die "xargs is not available"
217+
fi
218+
208219
# Use "xargs" to parse quoted args.
209220
#
210221
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.

gradlew.bat

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
@rem limitations under the License.
1515
@rem
1616

17-
@if "%DEBUG%" == "" @echo off
17+
@if "%DEBUG%"=="" @echo off
1818
@rem ##########################################################################
1919
@rem
2020
@rem Gradle startup script for Windows
@@ -25,7 +25,8 @@
2525
if "%OS%"=="Windows_NT" setlocal
2626

2727
set DIRNAME=%~dp0
28-
if "%DIRNAME%" == "" set DIRNAME=.
28+
if "%DIRNAME%"=="" set DIRNAME=.
29+
@rem This is normally unused
2930
set APP_BASE_NAME=%~n0
3031
set APP_HOME=%DIRNAME%
3132

@@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
4041

4142
set JAVA_EXE=java.exe
4243
%JAVA_EXE% -version >NUL 2>&1
43-
if "%ERRORLEVEL%" == "0" goto execute
44+
if %ERRORLEVEL% equ 0 goto execute
4445

4546
echo.
4647
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
7576

7677
:end
7778
@rem End local scope for the variables with windows NT shell
78-
if "%ERRORLEVEL%"=="0" goto mainEnd
79+
if %ERRORLEVEL% equ 0 goto mainEnd
7980

8081
:fail
8182
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
8283
rem the _cmd.exe /c_ return code!
83-
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84-
exit /b 1
84+
set EXIT_CODE=%ERRORLEVEL%
85+
if %EXIT_CODE% equ 0 set EXIT_CODE=1
86+
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
87+
exit /b %EXIT_CODE%
8588

8689
:mainEnd
8790
if "%OS%"=="Windows_NT" endlocal

src/main/kotlin/com/sennproject/springbootwebfluxkotlincoroutine/handlers/TodoHandler.kt

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class TodoHandler(val repository: TodoRepository) {
2626

2727
suspend fun findAllByStatus(request: ServerRequest): ServerResponse = coroutineScope {
2828
return@coroutineScope runCatching {
29-
var status = request.queryParam("status").map { it.toBoolean() }.orElse(false)
29+
val status = request.queryParam("status").map { it.toBoolean() }.orElse(false)
3030
val page = request.queryParam("page").map { it.toInt() }.orElse(0)
3131
val size = request.queryParam("size").map { it.toInt() }.orElse(10)
3232
val sort = Sort.by(listOf(Sort.Order.desc("id")))
@@ -38,39 +38,39 @@ class TodoHandler(val repository: TodoRepository) {
3838
}
3939
repository.findAllByStatusEquals(status, paging)
4040
}.fold(
41-
onSuccess = {
42-
ok().contentType(APPLICATION_JSON).bodyAndAwait(it);
43-
},
44-
onFailure = {
45-
log.error(it.message)
46-
status(HttpStatus.INTERNAL_SERVER_ERROR)
47-
.contentType(APPLICATION_JSON)
48-
.bodyAndAwait(flowOf(listOf<Todo>()))
49-
}
41+
onSuccess = {
42+
ok().contentType(APPLICATION_JSON).bodyAndAwait(it);
43+
},
44+
onFailure = {
45+
log.error(it.message)
46+
status(HttpStatus.INTERNAL_SERVER_ERROR)
47+
.contentType(APPLICATION_JSON)
48+
.bodyAndAwait(flowOf(listOf<Todo>()))
49+
}
5050
)
5151
}
5252

5353
suspend fun findById(request: ServerRequest): ServerResponse = coroutineScope {
5454
val id = request.pathVariable("id").toLong()
5555
val todo = id.let { repository.findById(id) }
5656
return@coroutineScope todo?.let { ok().contentType(APPLICATION_JSON).bodyValueAndAwait(it) }
57-
?: ServerResponse.notFound().buildAndAwait()
57+
?: ServerResponse.notFound().buildAndAwait()
5858
}
5959

6060
suspend fun edit(request: ServerRequest): ServerResponse = coroutineScope {
6161
return@coroutineScope runCatching {
6262
val todo = request.awaitBody<Todo>()
6363
repository.save(todo)
6464
}.fold(
65-
onSuccess = {
66-
ok().contentType(APPLICATION_JSON).bodyAndAwait(flowOf(it));
67-
},
68-
onFailure = {
69-
log.error(it.message)
70-
status(HttpStatus.NOT_FOUND)
71-
.contentType(APPLICATION_JSON)
72-
.bodyAndAwait(flowOf(Todo(id = 0L, task = "", status = false)))
73-
}
65+
onSuccess = {
66+
ok().contentType(APPLICATION_JSON).bodyAndAwait(flowOf(it));
67+
},
68+
onFailure = {
69+
log.error(it.message)
70+
status(HttpStatus.NOT_FOUND)
71+
.contentType(APPLICATION_JSON)
72+
.bodyAndAwait(flowOf(Todo(id = 0L, task = "", status = false)))
73+
}
7474
)
7575
}
7676

@@ -79,15 +79,15 @@ class TodoHandler(val repository: TodoRepository) {
7979
val id = request.pathVariable("id").toLong()
8080
repository.deleteById(id)
8181
}.fold(
82-
onSuccess = {
83-
ok().contentType(APPLICATION_JSON).bodyAndAwait(flowOf(it));
84-
},
85-
onFailure = {
86-
log.error(it.message)
87-
status(HttpStatus.INTERNAL_SERVER_ERROR)
88-
.contentType(APPLICATION_JSON)
89-
.bodyAndAwait(flowOf(Todo(id = 0L, task = "", status = false)))
90-
}
82+
onSuccess = {
83+
ok().contentType(APPLICATION_JSON).bodyAndAwait(flowOf(it));
84+
},
85+
onFailure = {
86+
log.error(it.message)
87+
status(HttpStatus.INTERNAL_SERVER_ERROR)
88+
.contentType(APPLICATION_JSON)
89+
.bodyAndAwait(flowOf(Todo(id = 0L, task = "", status = false)))
90+
}
9191
)
9292
}
9393

src/main/kotlin/com/sennproject/springbootwebfluxkotlincoroutine/repositories/TodoRepository.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ package com.sennproject.springbootwebfluxkotlincoroutine.repositories
33
import com.sennproject.springbootwebfluxkotlincoroutine.models.Todo
44
import kotlinx.coroutines.flow.Flow
55
import org.springframework.data.domain.Pageable
6-
import org.springframework.data.repository.kotlin.CoroutineSortingRepository
6+
import org.springframework.data.repository.kotlin.CoroutineCrudRepository
77
import org.springframework.stereotype.Service
88

99
/**
1010
* @author Yasuyuki Takeo
1111
*/
1212
@Service
13-
interface TodoRepository : CoroutineSortingRepository<Todo, Long> {
13+
interface TodoRepository : CoroutineCrudRepository<Todo, Long> {
1414
fun findAllByStatusEquals(status: Boolean, paging: Pageable?) : Flow<Todo>
1515
}

0 commit comments

Comments
 (0)