Download a random file
diff --git a/spring-boot-uploading-and-downloading-files-with-react/pom.xml b/spring-boot-uploading-and-downloading-files-with-react/pom.xml
index 768d0413..f5b02bc6 100644
--- a/spring-boot-uploading-and-downloading-files-with-react/pom.xml
+++ b/spring-boot-uploading-and-downloading-files-with-react/pom.xml
@@ -1,29 +1,19 @@
-
+
4.0.0
+
+ de.rieckpil.blog
+ blog-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
+
+
de.rieckpil.learning
spring-boot-uploading-and-downloading-files-with-react
0.0.1-SNAPSHOT
jar
- demo
- Demo project for Spring Boot
-
-
- org.springframework.boot
- spring-boot-starter-parent
- 2.3.0.RELEASE
-
-
-
-
- UTF-8
- UTF-8
- 11
-
-
org.springframework.boot
@@ -47,12 +37,6 @@
org.springframework.boot
spring-boot-starter-test
test
-
-
- org.junit.vintage
- junit-vintage-engine
-
-
@@ -60,24 +44,24 @@
app
- ${project.basedir}/frontend/build
- false
public/
+ false
+ ${project.basedir}/frontend/build
- ${project.basedir}/src/main/resources
false
+ ${project.basedir}/src/main/resources
-
- org.springframework.boot
- spring-boot-maven-plugin
-
com.github.eirslett
frontend-maven-plugin
- 1.8.0
+ 1.15.0
+
+ frontend
+ v16.20.0
+
install node and npm
@@ -110,10 +94,6 @@
-
- frontend
- v12.18.0
-
diff --git a/spring-boot-uploading-and-downloading-files-with-react/src/main/java/de/rieckpil/blog/FileBoundary.java b/spring-boot-uploading-and-downloading-files-with-react/src/main/java/de/rieckpil/blog/FileBoundary.java
index b9d7a504..28149a41 100644
--- a/spring-boot-uploading-and-downloading-files-with-react/src/main/java/de/rieckpil/blog/FileBoundary.java
+++ b/spring-boot-uploading-and-downloading-files-with-react/src/main/java/de/rieckpil/blog/FileBoundary.java
@@ -1,5 +1,9 @@
package de.rieckpil.blog;
+import jakarta.validation.constraints.NotNull;
+import java.io.IOException;
+import java.net.URI;
+import java.util.concurrent.ThreadLocalRandom;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
@@ -8,14 +12,11 @@
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
-import javax.validation.constraints.NotNull;
-import java.io.IOException;
-import java.net.URI;
-import java.util.concurrent.ThreadLocalRandom;
-
@RestController
@RequestMapping("/api/files")
-@CrossOrigin(value = {"*"}, exposedHeaders = {"Content-Disposition"})
+@CrossOrigin(
+ value = {"*"},
+ exposedHeaders = {"Content-Disposition"})
public class FileBoundary {
private final FileEntityRepository fileEntityRepository;
@@ -50,16 +51,18 @@ public ResponseEntity getRandomFile() {
}
@PostMapping
- public ResponseEntity uploadNewFile(@NotNull @RequestParam("file") MultipartFile multipartFile) throws IOException {
+ public ResponseEntity uploadNewFile(
+ @NotNull @RequestParam("file") MultipartFile multipartFile) throws IOException {
- FileEntity fileEntity = new FileEntity(multipartFile.getOriginalFilename(), multipartFile.getContentType(),
- multipartFile.getBytes());
+ FileEntity fileEntity =
+ new FileEntity(
+ multipartFile.getOriginalFilename(),
+ multipartFile.getContentType(),
+ multipartFile.getBytes());
fileEntityRepository.save(fileEntity);
URI location = ServletUriComponentsBuilder.fromCurrentRequest().build().toUri();
return ResponseEntity.created(location).build();
-
}
-
}
diff --git a/spring-boot-uploading-and-downloading-files-with-react/src/main/java/de/rieckpil/blog/FileEntity.java b/spring-boot-uploading-and-downloading-files-with-react/src/main/java/de/rieckpil/blog/FileEntity.java
index f7469267..a56680cb 100644
--- a/spring-boot-uploading-and-downloading-files-with-react/src/main/java/de/rieckpil/blog/FileEntity.java
+++ b/spring-boot-uploading-and-downloading-files-with-react/src/main/java/de/rieckpil/blog/FileEntity.java
@@ -1,6 +1,6 @@
package de.rieckpil.blog;
-import javax.persistence.*;
+import jakarta.persistence.*;
@Entity
public class FileEntity {
@@ -13,11 +13,9 @@ public class FileEntity {
private String contentType;
- @Lob
- private byte[] data;
+ @Lob private byte[] data;
- public FileEntity() {
- }
+ public FileEntity() {}
public FileEntity(String fileName, String contentType, byte[] data) {
this.fileName = fileName;
diff --git a/spring-boot-uploading-and-downloading-files-with-react/src/main/java/de/rieckpil/blog/FileEntityRepository.java b/spring-boot-uploading-and-downloading-files-with-react/src/main/java/de/rieckpil/blog/FileEntityRepository.java
index 1255bbe7..14fff784 100644
--- a/spring-boot-uploading-and-downloading-files-with-react/src/main/java/de/rieckpil/blog/FileEntityRepository.java
+++ b/spring-boot-uploading-and-downloading-files-with-react/src/main/java/de/rieckpil/blog/FileEntityRepository.java
@@ -2,5 +2,4 @@
import org.springframework.data.jpa.repository.JpaRepository;
-public interface FileEntityRepository extends JpaRepository {
-}
+public interface FileEntityRepository extends JpaRepository {}
diff --git a/spring-boot-uploading-and-downloading-files-with-react/src/test/java/de/rieckpil/blog/DemoApplicationTests.java b/spring-boot-uploading-and-downloading-files-with-react/src/test/java/de/rieckpil/blog/DemoApplicationTests.java
index a01bb6c2..ca700edd 100644
--- a/spring-boot-uploading-and-downloading-files-with-react/src/test/java/de/rieckpil/blog/DemoApplicationTests.java
+++ b/spring-boot-uploading-and-downloading-files-with-react/src/test/java/de/rieckpil/blog/DemoApplicationTests.java
@@ -1,16 +1,11 @@
package de.rieckpil.blog;
import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.test.context.junit.jupiter.SpringExtension;
-@ExtendWith(SpringExtension.class)
@SpringBootTest
-public class DemoApplicationTests {
-
- @Test
- public void contextLoads() {
- }
+class DemoApplicationTests {
+ @Test
+ void contextLoads() {}
}
diff --git a/spring-boot-web-mvc-testing/.gitignore b/spring-boot-web-mvc-testing/.gitignore
new file mode 100644
index 00000000..549e00a2
--- /dev/null
+++ b/spring-boot-web-mvc-testing/.gitignore
@@ -0,0 +1,33 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
diff --git a/spring-boot-web-mvc-testing/.mvn/wrapper/maven-wrapper.jar b/spring-boot-web-mvc-testing/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 00000000..c1dd12f1
Binary files /dev/null and b/spring-boot-web-mvc-testing/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-boot-web-mvc-testing/.mvn/wrapper/maven-wrapper.properties b/spring-boot-web-mvc-testing/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 00000000..b7cb93e7
--- /dev/null
+++ b/spring-boot-web-mvc-testing/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,2 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.4/apache-maven-3.8.4-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar
diff --git a/spring-boot-web-mvc-testing/README.md b/spring-boot-web-mvc-testing/README.md
new file mode 100644
index 00000000..945a9c96
--- /dev/null
+++ b/spring-boot-web-mvc-testing/README.md
@@ -0,0 +1,8 @@
+# Codebase for the blog post [Spring Boot Test Spring Web MVC HandlerInterceptor](https://rieckpil.de/spring-boot-test-spring-web-mvc-handlerinterceptor/)
+
+Steps to run this project:
+
+1. Clone this Git repository
+2. Navigate to the folder `spring-boot-web-mvc-testing`
+3. Run all tests with `./mvnw verify`
+
diff --git a/spring-boot-web-mvc-testing/mvnw b/spring-boot-web-mvc-testing/mvnw
new file mode 100755
index 00000000..8a8fb228
--- /dev/null
+++ b/spring-boot-web-mvc-testing/mvnw
@@ -0,0 +1,316 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# M2_HOME - location of maven2's installed home dir
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /usr/local/etc/mavenrc ] ; then
+ . /usr/local/etc/mavenrc
+ fi
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ export JAVA_HOME="`/usr/libexec/java_home`"
+ else
+ export JAVA_HOME="/Library/Java/Home"
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=`java-config --jre-home`
+ fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+ ## resolve links - $0 may be a link to maven's home
+ PRG="$0"
+
+ # need this for relative symlinks
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG="`dirname "$PRG"`/$link"
+ fi
+ done
+
+ saveddir=`pwd`
+
+ M2_HOME=`dirname "$PRG"`/..
+
+ # make it fully qualified
+ M2_HOME=`cd "$M2_HOME" && pwd`
+
+ cd "$saveddir"
+ # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --unix "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME="`(cd "$M2_HOME"; pwd)`"
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="`which javac`"
+ if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=`which readlink`
+ if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+ if $darwin ; then
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+ else
+ javaExecutable="`readlink -f \"$javaExecutable\"`"
+ fi
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="`\\unset -f command; \\command -v java`"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=`cd "$wdir/.."; pwd`
+ fi
+ # end of workaround
+ done
+ echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ echo "$(tr -s '\n' ' ' < "$1")"
+ fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found .mvn/wrapper/maven-wrapper.jar"
+ fi
+else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+ fi
+ if [ -n "$MVNW_REPOURL" ]; then
+ jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+ else
+ jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+ fi
+ while IFS="=" read key value; do
+ case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
+ esac
+ done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Downloading from: $jarUrl"
+ fi
+ wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+ if $cygwin; then
+ wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
+ fi
+
+ if command -v wget > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found wget ... using wget"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ else
+ wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ fi
+ elif command -v curl > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found curl ... using curl"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl -o "$wrapperJarPath" "$jarUrl" -f
+ else
+ curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
+ fi
+
+ else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Falling back to using Java to download"
+ fi
+ javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaClass=`cygpath --path --windows "$javaClass"`
+ fi
+ if [ -e "$javaClass" ]; then
+ if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Compiling MavenWrapperDownloader.java ..."
+ fi
+ # Compiling the Java class
+ ("$JAVA_HOME/bin/javac" "$javaClass")
+ fi
+ if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ # Running the downloader
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Running MavenWrapperDownloader.java ..."
+ fi
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+if [ "$MVNW_VERBOSE" = true ]; then
+ echo $MAVEN_PROJECTBASEDIR
+fi
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --path --windows "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ $MAVEN_DEBUG_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.home=${M2_HOME}" \
+ "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/spring-boot-web-mvc-testing/mvnw.cmd b/spring-boot-web-mvc-testing/mvnw.cmd
new file mode 100644
index 00000000..1d8ab018
--- /dev/null
+++ b/spring-boot-web-mvc-testing/mvnw.cmd
@@ -0,0 +1,188 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM https://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
+if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Found %WRAPPER_JAR%
+ )
+) else (
+ if not "%MVNW_REPOURL%" == "" (
+ SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+ )
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %DOWNLOAD_URL%
+ )
+
+ powershell -Command "&{"^
+ "$webclient = new-object System.Net.WebClient;"^
+ "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+ "}"^
+ "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
+ "}"
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Finished downloading %WRAPPER_JAR%
+ )
+)
+@REM End of extension
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% ^
+ %JVM_CONFIG_MAVEN_PROPS% ^
+ %MAVEN_OPTS% ^
+ %MAVEN_DEBUG_OPTS% ^
+ -classpath %WRAPPER_JAR% ^
+ "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
+ %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
+if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%"=="on" pause
+
+if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
+
+cmd /C exit /B %ERROR_CODE%
diff --git a/spring-boot-web-mvc-testing/pom.xml b/spring-boot-web-mvc-testing/pom.xml
new file mode 100644
index 00000000..1fcfc354
--- /dev/null
+++ b/spring-boot-web-mvc-testing/pom.xml
@@ -0,0 +1,38 @@
+
+
+ 4.0.0
+
+ de.rieckpil.blog
+ blog-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
+
+
+ spring-boot-web-mvc-testing
+ 0.0.1-SNAPSHOT
+ spring-boot-web-mvc-testing
+ spring-boot-web-mvc-testing
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.springframework.security
+ spring-security-test
+ test
+
+
+
diff --git a/spring-boot-web-mvc-testing/src/main/java/de/rieckpil/blog/Application.java b/spring-boot-web-mvc-testing/src/main/java/de/rieckpil/blog/Application.java
new file mode 100644
index 00000000..6511f3c1
--- /dev/null
+++ b/spring-boot-web-mvc-testing/src/main/java/de/rieckpil/blog/Application.java
@@ -0,0 +1,12 @@
+package de.rieckpil.blog;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+}
diff --git a/spring-boot-web-mvc-testing/src/main/java/de/rieckpil/blog/LoggingContextFilter.java b/spring-boot-web-mvc-testing/src/main/java/de/rieckpil/blog/LoggingContextFilter.java
new file mode 100644
index 00000000..d0f037f7
--- /dev/null
+++ b/spring-boot-web-mvc-testing/src/main/java/de/rieckpil/blog/LoggingContextFilter.java
@@ -0,0 +1,3 @@
+package de.rieckpil.blog;
+
+public class LoggingContextFilter {}
diff --git a/spring-boot-web-mvc-testing/src/main/java/de/rieckpil/blog/WebMvcConfig.java b/spring-boot-web-mvc-testing/src/main/java/de/rieckpil/blog/WebMvcConfig.java
new file mode 100644
index 00000000..f988b01c
--- /dev/null
+++ b/spring-boot-web-mvc-testing/src/main/java/de/rieckpil/blog/WebMvcConfig.java
@@ -0,0 +1,23 @@
+package de.rieckpil.blog;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+public class WebMvcConfig implements WebMvcConfigurer {
+
+ private final String validApiKey;
+
+ public WebMvcConfig(@Value("${valid-api-key}") String validApiKey) {
+ this.validApiKey = validApiKey;
+ }
+
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ registry
+ .addInterceptor(new WebhookAuthorizationHandlerInterceptor(validApiKey))
+ .addPathPatterns("/webhooks/**");
+ }
+}
diff --git a/spring-boot-web-mvc-testing/src/main/java/de/rieckpil/blog/WebSecurityConfig.java b/spring-boot-web-mvc-testing/src/main/java/de/rieckpil/blog/WebSecurityConfig.java
new file mode 100644
index 00000000..fb2aa314
--- /dev/null
+++ b/spring-boot-web-mvc-testing/src/main/java/de/rieckpil/blog/WebSecurityConfig.java
@@ -0,0 +1,26 @@
+package de.rieckpil.blog;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpMethod;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
+import org.springframework.security.web.SecurityFilterChain;
+
+@Configuration
+public class WebSecurityConfig {
+
+ @Bean
+ public SecurityFilterChain configure(HttpSecurity http) throws Exception {
+ http.authorizeRequests(
+ authorizeRequests ->
+ authorizeRequests
+ .requestMatchers(HttpMethod.POST, "/webhooks/orders")
+ .permitAll()
+ .anyRequest()
+ .authenticated())
+ .csrf(AbstractHttpConfigurer::disable);
+
+ return http.build();
+ }
+}
diff --git a/spring-boot-web-mvc-testing/src/main/java/de/rieckpil/blog/WebhookAuthorizationHandlerInterceptor.java b/spring-boot-web-mvc-testing/src/main/java/de/rieckpil/blog/WebhookAuthorizationHandlerInterceptor.java
new file mode 100644
index 00000000..c9513582
--- /dev/null
+++ b/spring-boot-web-mvc-testing/src/main/java/de/rieckpil/blog/WebhookAuthorizationHandlerInterceptor.java
@@ -0,0 +1,35 @@
+package de.rieckpil.blog;
+
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+public class WebhookAuthorizationHandlerInterceptor implements HandlerInterceptor {
+
+ private final String validApiKey;
+
+ private static final Logger LOG =
+ LoggerFactory.getLogger(WebhookAuthorizationHandlerInterceptor.class);
+
+ public WebhookAuthorizationHandlerInterceptor(String validApiKey) {
+ this.validApiKey = validApiKey;
+ }
+
+ @Override
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
+ throws Exception {
+ String apiKey = request.getHeader("X-API-KEY");
+
+ LOG.debug("Incoming X-API-KEY header for accessing a webhook: '{}'", apiKey);
+
+ if (validApiKey.equalsIgnoreCase(apiKey)) {
+ return true;
+ } else {
+ LOG.warn("Invalid API key in the request when trying to access webhooks: '{}'", apiKey);
+ response.sendError(403); // you may also argue to return 401 here
+ return false;
+ }
+ }
+}
diff --git a/spring-boot-web-mvc-testing/src/main/java/de/rieckpil/blog/WebhookController.java b/spring-boot-web-mvc-testing/src/main/java/de/rieckpil/blog/WebhookController.java
new file mode 100644
index 00000000..05c9fe45
--- /dev/null
+++ b/spring-boot-web-mvc-testing/src/main/java/de/rieckpil/blog/WebhookController.java
@@ -0,0 +1,27 @@
+package de.rieckpil.blog;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/webhooks")
+public class WebhookController {
+
+ private static final Logger LOG = LoggerFactory.getLogger(WebhookController.class);
+
+ @PostMapping("/orders")
+ public ResponseEntity handleOrderWebhook(@RequestBody ObjectNode objectNode) {
+
+ LOG.info("Incoming webhook payload for orders: '{}'", objectNode);
+
+ // further order handling
+
+ return ResponseEntity.noContent().build();
+ }
+}
diff --git a/spring-boot-web-mvc-testing/src/main/resources/application.properties b/spring-boot-web-mvc-testing/src/main/resources/application.properties
new file mode 100644
index 00000000..d7665251
--- /dev/null
+++ b/spring-boot-web-mvc-testing/src/main/resources/application.properties
@@ -0,0 +1 @@
+valid-api-key=XZShsk4wh6lw
diff --git a/maven-plugins-to-ensure-quality/src/test/java/de/rieckpil/blog/MavenPluginsToEnsureQualityApplicationTests.java b/spring-boot-web-mvc-testing/src/test/java/de/rieckpil/blog/ApplicationTest.java
similarity index 60%
rename from maven-plugins-to-ensure-quality/src/test/java/de/rieckpil/blog/MavenPluginsToEnsureQualityApplicationTests.java
rename to spring-boot-web-mvc-testing/src/test/java/de/rieckpil/blog/ApplicationTest.java
index db5b8302..b6751e0d 100644
--- a/maven-plugins-to-ensure-quality/src/test/java/de/rieckpil/blog/MavenPluginsToEnsureQualityApplicationTests.java
+++ b/spring-boot-web-mvc-testing/src/test/java/de/rieckpil/blog/ApplicationTest.java
@@ -4,10 +4,8 @@
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
-class MavenPluginsToEnsureQualityApplicationTests {
-
- @Test
- void contextLoads() {
- }
+class ApplicationTest {
+ @Test
+ void contextLoads() {}
}
diff --git a/spring-boot-web-mvc-testing/src/test/java/de/rieckpil/blog/WebhookAuthorizationHandlerInterceptorTest.java b/spring-boot-web-mvc-testing/src/test/java/de/rieckpil/blog/WebhookAuthorizationHandlerInterceptorTest.java
new file mode 100644
index 00000000..8de51c81
--- /dev/null
+++ b/spring-boot-web-mvc-testing/src/test/java/de/rieckpil/blog/WebhookAuthorizationHandlerInterceptorTest.java
@@ -0,0 +1,35 @@
+package de.rieckpil.blog;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+
+class WebhookAuthorizationHandlerInterceptorTest {
+
+ private WebhookAuthorizationHandlerInterceptor cut;
+
+ private static final String VALID_TEST_API_KEY = "test400";
+
+ @BeforeEach
+ void setUp() {
+ this.cut = new WebhookAuthorizationHandlerInterceptor(VALID_TEST_API_KEY);
+ }
+
+ @Test
+ void shouldBlockRequestWithWhenHeaderIsMissing() throws Exception {
+
+ HttpServletRequest httpServletRequest = new MockHttpServletRequest();
+ HttpServletResponse httpServletResponse = new MockHttpServletResponse();
+
+ boolean result = cut.preHandle(httpServletRequest, httpServletResponse, null);
+
+ assertThat(result).isFalse();
+
+ assertThat(httpServletResponse.getStatus()).isEqualTo(403);
+ }
+}
diff --git a/spring-boot-web-mvc-testing/src/test/java/de/rieckpil/blog/WebhookControllerTest.java b/spring-boot-web-mvc-testing/src/test/java/de/rieckpil/blog/WebhookControllerTest.java
new file mode 100644
index 00000000..60988fe9
--- /dev/null
+++ b/spring-boot-web-mvc-testing/src/test/java/de/rieckpil/blog/WebhookControllerTest.java
@@ -0,0 +1,62 @@
+package de.rieckpil.blog;
+
+import static org.springframework.http.MediaType.APPLICATION_JSON;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
+import org.springframework.context.annotation.Import;
+import org.springframework.test.web.servlet.MockMvc;
+
+@Import(WebSecurityConfig.class)
+@WebMvcTest(value = WebhookController.class, properties = "valid-api-key=test42")
+class WebhookControllerTest {
+
+ @Autowired private MockMvc mockMvc;
+
+ @Test
+ void shouldForbidAccessWithMissingApiKey() throws Exception {
+ this.mockMvc
+ .perform(
+ post("/webhooks/orders")
+ .contentType(APPLICATION_JSON)
+ .content("""
+ {
+ "orderId": 42
+ }
+ """))
+ .andExpect(status().isForbidden());
+ }
+
+ @Test
+ void shouldForbidAccessWithInvalidApiKey() throws Exception {
+ this.mockMvc
+ .perform(
+ post("/webhooks/orders")
+ .header("X-API-KEY", "invalid42")
+ .contentType(APPLICATION_JSON)
+ .content("""
+ {
+ "orderId": 42
+ }
+ """))
+ .andExpect(status().isForbidden());
+ }
+
+ @Test
+ void shouldAllowAccessWithValidApiKey() throws Exception {
+ this.mockMvc
+ .perform(
+ post("/webhooks/orders")
+ .header("X-API-KEY", "test42")
+ .contentType(APPLICATION_JSON)
+ .content("""
+ {
+ "orderId": 42
+ }
+ """))
+ .andExpect(status().isNoContent());
+ }
+}
diff --git a/spring-boot-with-kotlin/README.md b/spring-boot-with-kotlin/README.md
index 8e42423e..49c9f926 100644
--- a/spring-boot-with-kotlin/README.md
+++ b/spring-boot-with-kotlin/README.md
@@ -1,8 +1,8 @@
-# Codebase for the blog post [#HOWTO: Create Spring Boot applications with Maven and Kotlin](https://rieckpil.de/create-spring-boot-applications-with-maven-and-kotlin/)
+# Codebase for the blog post [Building Spring Boot Applications With Maven and Kotlin](https://rieckpil.de/create-spring-boot-applications-with-maven-and-kotlin/)
Steps to run this project:
1. Clone this Git repository
2. Navigate to the folder `spring-boot-with-maven`
3. Start the application with `mvn spring-boot:run`
-4. Access http://localhost:8080/api/todos or http://localhost:8080/api/persons
\ No newline at end of file
+4. Access http://localhost:8080/api/todos or http://localhost:8080/api/persons
diff --git a/spring-boot-with-kotlin/pom.xml b/spring-boot-with-kotlin/pom.xml
index 3c37de81..875cf93a 100644
--- a/spring-boot-with-kotlin/pom.xml
+++ b/spring-boot-with-kotlin/pom.xml
@@ -1,25 +1,19 @@
-
+
4.0.0
+
- org.springframework.boot
- spring-boot-starter-parent
- 2.3.0.RELEASE
-
+ de.rieckpil.blog
+ blog-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
- de.rieckpil.blog
spring-boot-with-kotlin
0.0.1-SNAPSHOT
spring-boot-with-kotlin
Template for Spring Boot applications with Kotlin
-
- 11
- 1.3.72
-
-
org.springframework.boot
@@ -55,36 +49,38 @@
org.springframework.boot
spring-boot-starter-test
test
-
-
- org.junit.vintage
- junit-vintage-engine
-
-
io.projectreactor
reactor-test
test
+
+ org.jetbrains.kotlin
+ kotlin-stdlib-jdk8
+ ${kotlin.version}
+
+
+ org.jetbrains.kotlin
+ kotlin-test
+ ${kotlin.version}
+ test
+
- ${project.basedir}/src/main/kotlin
- ${project.basedir}/src/test/kotlin
org.springframework.boot
spring-boot-maven-plugin
- kotlin-maven-plugin
org.jetbrains.kotlin
+ kotlin-maven-plugin
-Xjsr305=strict
- ${java.version}
spring
jpa
@@ -112,33 +108,48 @@
org.apache.maven.plugins
maven-antrun-plugin
- 1.7
+ 3.1.0
+
+
+ com.pinterest.ktlint
+ ktlint-cli
+ 1.1.1
+
+
ktlint
+
+ run
+
validate
-
-
+
+
+
+
+ ktlint-format
run
+
+
+
+
+
+
+
+
-
-
- com.pinterest
- ktlint
- 0.35.0
-
-
+ src/main/kotlin
+ src/test/kotlin
diff --git a/spring-boot-with-kotlin/src/main/kotlin/de.rieckpil.blog/ApiController.kt b/spring-boot-with-kotlin/src/main/kotlin/de.rieckpil.blog/ApiController.kt
index 29085e26..d0d89855 100644
--- a/spring-boot-with-kotlin/src/main/kotlin/de.rieckpil.blog/ApiController.kt
+++ b/spring-boot-with-kotlin/src/main/kotlin/de.rieckpil.blog/ApiController.kt
@@ -11,16 +11,16 @@ import org.springframework.web.reactive.function.client.WebClient
@RequestMapping("/api")
class ApiController(
val jsonPlaceHolderWebClient: WebClient,
- val personRepository: PersonRepository
+ val personRepository: PersonRepository,
) {
-
@GetMapping(value = ["/todos"], produces = [MediaType.APPLICATION_JSON_VALUE])
- fun getAllTodos() = jsonPlaceHolderWebClient
- .get()
- .uri("/todos")
- .retrieve()
- .bodyToMono(ArrayNode::class.java)
- .block()
+ fun getAllTodos() =
+ jsonPlaceHolderWebClient
+ .get()
+ .uri("/todos")
+ .retrieve()
+ .bodyToMono(ArrayNode::class.java)
+ .block()
@GetMapping(value = ["/persons"], produces = [MediaType.APPLICATION_JSON_VALUE])
fun getAllPersons(): List = personRepository.findAll()
diff --git a/spring-boot-with-kotlin/src/main/kotlin/de.rieckpil.blog/Application.kt b/spring-boot-with-kotlin/src/main/kotlin/de.rieckpil.blog/Application.kt
new file mode 100644
index 00000000..50cf101c
--- /dev/null
+++ b/spring-boot-with-kotlin/src/main/kotlin/de.rieckpil.blog/Application.kt
@@ -0,0 +1,48 @@
+package de.rieckpil.blog
+
+import org.springframework.boot.CommandLineRunner
+import org.springframework.boot.autoconfigure.SpringBootApplication
+import org.springframework.boot.runApplication
+import org.springframework.stereotype.Component
+import java.time.LocalDate
+
+@SpringBootApplication
+class Application
+
+fun main(args: Array) {
+ runApplication(*args)
+}
+
+@Component
+class PersonInitializer(
+ private val personRepository: PersonRepository,
+) : CommandLineRunner {
+ override fun run(vararg args: String?) {
+ val personOne =
+ Person(
+ null,
+ "Mike",
+ "Kotlin",
+ "mk90",
+ LocalDate.of(1990, 1, 1),
+ )
+ val personTwo =
+ Person(
+ null,
+ "Java",
+ "Duke",
+ "jduke",
+ LocalDate.of(1995, 1, 1),
+ )
+ val personThree =
+ Person(
+ null,
+ "Andy",
+ "Fresh",
+ "afresh",
+ LocalDate.of(2000, 1, 1),
+ )
+
+ personRepository.saveAll(listOf(personOne, personTwo, personThree))
+ }
+}
diff --git a/spring-boot-with-kotlin/src/main/kotlin/de.rieckpil.blog/Person.kt b/spring-boot-with-kotlin/src/main/kotlin/de.rieckpil.blog/Person.kt
index abf791b4..4bedaf72 100644
--- a/spring-boot-with-kotlin/src/main/kotlin/de.rieckpil.blog/Person.kt
+++ b/spring-boot-with-kotlin/src/main/kotlin/de.rieckpil.blog/Person.kt
@@ -1,10 +1,10 @@
package de.rieckpil.blog
+import jakarta.persistence.Column
+import jakarta.persistence.Entity
+import jakarta.persistence.GeneratedValue
+import jakarta.persistence.Id
import java.time.LocalDate
-import javax.persistence.Column
-import javax.persistence.Entity
-import javax.persistence.GeneratedValue
-import javax.persistence.Id
@Entity
class Person(
@@ -12,5 +12,5 @@ class Person(
@Column(nullable = false) var firstname: String,
@Column(nullable = false) var lastname: String,
@Column(unique = true, nullable = false) var username: String,
- @Column(nullable = false) var dayOfBirth: LocalDate
+ @Column(nullable = false) var dayOfBirth: LocalDate,
)
diff --git a/spring-boot-with-kotlin/src/main/kotlin/de.rieckpil.blog/SpringBootWithKotlinApplication.kt b/spring-boot-with-kotlin/src/main/kotlin/de.rieckpil.blog/SpringBootWithKotlinApplication.kt
deleted file mode 100644
index c7ffb758..00000000
--- a/spring-boot-with-kotlin/src/main/kotlin/de.rieckpil.blog/SpringBootWithKotlinApplication.kt
+++ /dev/null
@@ -1,32 +0,0 @@
-package de.rieckpil.blog
-
-import java.time.LocalDate
-import org.springframework.boot.CommandLineRunner
-import org.springframework.boot.autoconfigure.SpringBootApplication
-import org.springframework.boot.runApplication
-import org.springframework.stereotype.Component
-
-@SpringBootApplication
-class SpringBootWithKotlinApplication
-
-fun main(args: Array) {
- runApplication(*args)
-}
-
-@Component
-class PersonInitializer(
- private val personRepository: PersonRepository
-) : CommandLineRunner {
-
- override fun run(vararg args: String?) {
-
- val personOne = Person(null, "Mike", "Kotlin", "mk90",
- LocalDate.of(1990, 1, 1))
- val personTwo = Person(null, "Java", "Duke", "jduke",
- LocalDate.of(1995, 1, 1))
- val personThree = Person(null, "Andy", "Fresh", "afresh",
- LocalDate.of(2000, 1, 1))
-
- personRepository.saveAll(listOf(personOne, personTwo, personThree))
- }
-}
diff --git a/spring-boot-with-kotlin/src/main/kotlin/de.rieckpil.blog/WebClientConfig.kt b/spring-boot-with-kotlin/src/main/kotlin/de.rieckpil.blog/WebClientConfig.kt
index 4fa31d21..c0679fbe 100644
--- a/spring-boot-with-kotlin/src/main/kotlin/de.rieckpil.blog/WebClientConfig.kt
+++ b/spring-boot-with-kotlin/src/main/kotlin/de.rieckpil.blog/WebClientConfig.kt
@@ -8,12 +8,12 @@ import org.springframework.web.reactive.function.client.WebClient
@Configuration
class WebClientConfig {
-
@Bean
- fun jsonPlaceHolderWebClient(builder: WebClient.Builder) = builder
- .clone()
- .baseUrl("https://jsonplaceholder.typicode.com/")
- .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
- .defaultHeader(HttpHeaders.USER_AGENT, "SpringBootKotlinApplication")
- .build()
+ fun jsonPlaceHolderWebClient(builder: WebClient.Builder) =
+ builder
+ .clone()
+ .baseUrl("https://jsonplaceholder.typicode.com/")
+ .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
+ .defaultHeader(HttpHeaders.USER_AGENT, "SpringBootKotlinApplication")
+ .build()
}
diff --git a/spring-boot-with-kotlin/src/test/kotlin/de/rieckpil/blog/ApiControllerIntegrationTest.kt b/spring-boot-with-kotlin/src/test/kotlin/de/rieckpil/blog/ApiControllerIntegrationTest.kt
index 4f713f10..49f46537 100644
--- a/spring-boot-with-kotlin/src/test/kotlin/de/rieckpil/blog/ApiControllerIntegrationTest.kt
+++ b/spring-boot-with-kotlin/src/test/kotlin/de/rieckpil/blog/ApiControllerIntegrationTest.kt
@@ -9,9 +9,8 @@ import org.springframework.test.web.reactive.server.WebTestClient
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class ApiControllerIntegrationTest(
- @Autowired val webTestClient: WebTestClient
+ @Autowired val webTestClient: WebTestClient,
) {
-
@Test
fun `should get todos with status code 200`() {
this.webTestClient
diff --git a/spring-boot-with-kotlin/src/test/kotlin/de/rieckpil/blog/SpringBootWithKotlinApplicationTest.kt b/spring-boot-with-kotlin/src/test/kotlin/de/rieckpil/blog/SpringBootWithKotlinApplicationTest.kt
index 5c539c83..12835fa6 100644
--- a/spring-boot-with-kotlin/src/test/kotlin/de/rieckpil/blog/SpringBootWithKotlinApplicationTest.kt
+++ b/spring-boot-with-kotlin/src/test/kotlin/de/rieckpil/blog/SpringBootWithKotlinApplicationTest.kt
@@ -5,7 +5,6 @@ import org.springframework.boot.test.context.SpringBootTest
@SpringBootTest
class SpringBootWithKotlinApplicationTest {
-
@Test
fun `Spring context should load`() {
}
diff --git a/spring-cloud-aws-sqs-testing/.gitignore b/spring-cloud-aws-sqs-testing/.gitignore
new file mode 100644
index 00000000..549e00a2
--- /dev/null
+++ b/spring-cloud-aws-sqs-testing/.gitignore
@@ -0,0 +1,33 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
diff --git a/spring-cloud-aws-sqs-testing/.mvn/wrapper/maven-wrapper.jar b/spring-cloud-aws-sqs-testing/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 00000000..c1dd12f1
Binary files /dev/null and b/spring-cloud-aws-sqs-testing/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-cloud-aws-sqs-testing/.mvn/wrapper/maven-wrapper.properties b/spring-cloud-aws-sqs-testing/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 00000000..22f219d2
--- /dev/null
+++ b/spring-cloud-aws-sqs-testing/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,2 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.5/apache-maven-3.8.5-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar
diff --git a/spring-cloud-aws-sqs-testing/README.md b/spring-cloud-aws-sqs-testing/README.md
new file mode 100644
index 00000000..e0d0d596
--- /dev/null
+++ b/spring-cloud-aws-sqs-testing/README.md
@@ -0,0 +1,9 @@
+# Codebase for the blog post [Amazon SQS Listener Testing with @SqsTest (Spring Cloud AWS)](https://rieckpil.de/amazon-sqs-listener-testing-with-sqstest-spring-cloud-aws/)
+
+Steps to run this project:
+
+1. Clone this Git repository
+2. Navigate to the folder `spring-cloud-aws-testing`
+3. Ensure your Docker engine is running with `docker ps`
+4. Run all tests with `./mvnw verify`
+
diff --git a/spring-cloud-aws-sqs-testing/mvnw b/spring-cloud-aws-sqs-testing/mvnw
new file mode 100755
index 00000000..8a8fb228
--- /dev/null
+++ b/spring-cloud-aws-sqs-testing/mvnw
@@ -0,0 +1,316 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# M2_HOME - location of maven2's installed home dir
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /usr/local/etc/mavenrc ] ; then
+ . /usr/local/etc/mavenrc
+ fi
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ export JAVA_HOME="`/usr/libexec/java_home`"
+ else
+ export JAVA_HOME="/Library/Java/Home"
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=`java-config --jre-home`
+ fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+ ## resolve links - $0 may be a link to maven's home
+ PRG="$0"
+
+ # need this for relative symlinks
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG="`dirname "$PRG"`/$link"
+ fi
+ done
+
+ saveddir=`pwd`
+
+ M2_HOME=`dirname "$PRG"`/..
+
+ # make it fully qualified
+ M2_HOME=`cd "$M2_HOME" && pwd`
+
+ cd "$saveddir"
+ # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --unix "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME="`(cd "$M2_HOME"; pwd)`"
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="`which javac`"
+ if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=`which readlink`
+ if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+ if $darwin ; then
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+ else
+ javaExecutable="`readlink -f \"$javaExecutable\"`"
+ fi
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="`\\unset -f command; \\command -v java`"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=`cd "$wdir/.."; pwd`
+ fi
+ # end of workaround
+ done
+ echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ echo "$(tr -s '\n' ' ' < "$1")"
+ fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found .mvn/wrapper/maven-wrapper.jar"
+ fi
+else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+ fi
+ if [ -n "$MVNW_REPOURL" ]; then
+ jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+ else
+ jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+ fi
+ while IFS="=" read key value; do
+ case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
+ esac
+ done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Downloading from: $jarUrl"
+ fi
+ wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+ if $cygwin; then
+ wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
+ fi
+
+ if command -v wget > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found wget ... using wget"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ else
+ wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ fi
+ elif command -v curl > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found curl ... using curl"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl -o "$wrapperJarPath" "$jarUrl" -f
+ else
+ curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
+ fi
+
+ else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Falling back to using Java to download"
+ fi
+ javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaClass=`cygpath --path --windows "$javaClass"`
+ fi
+ if [ -e "$javaClass" ]; then
+ if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Compiling MavenWrapperDownloader.java ..."
+ fi
+ # Compiling the Java class
+ ("$JAVA_HOME/bin/javac" "$javaClass")
+ fi
+ if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ # Running the downloader
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Running MavenWrapperDownloader.java ..."
+ fi
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+if [ "$MVNW_VERBOSE" = true ]; then
+ echo $MAVEN_PROJECTBASEDIR
+fi
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --path --windows "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ $MAVEN_DEBUG_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.home=${M2_HOME}" \
+ "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/spring-cloud-aws-sqs-testing/mvnw.cmd b/spring-cloud-aws-sqs-testing/mvnw.cmd
new file mode 100644
index 00000000..1d8ab018
--- /dev/null
+++ b/spring-cloud-aws-sqs-testing/mvnw.cmd
@@ -0,0 +1,188 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM https://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
+if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Found %WRAPPER_JAR%
+ )
+) else (
+ if not "%MVNW_REPOURL%" == "" (
+ SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+ )
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %DOWNLOAD_URL%
+ )
+
+ powershell -Command "&{"^
+ "$webclient = new-object System.Net.WebClient;"^
+ "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+ "}"^
+ "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
+ "}"
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Finished downloading %WRAPPER_JAR%
+ )
+)
+@REM End of extension
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% ^
+ %JVM_CONFIG_MAVEN_PROPS% ^
+ %MAVEN_OPTS% ^
+ %MAVEN_DEBUG_OPTS% ^
+ -classpath %WRAPPER_JAR% ^
+ "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
+ %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
+if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%"=="on" pause
+
+if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
+
+cmd /C exit /B %ERROR_CODE%
diff --git a/spring-cloud-aws-sqs-testing/pom.xml b/spring-cloud-aws-sqs-testing/pom.xml
new file mode 100644
index 00000000..e231ec08
--- /dev/null
+++ b/spring-cloud-aws-sqs-testing/pom.xml
@@ -0,0 +1,87 @@
+
+
+ 4.0.0
+
+
+ de.rieckpil.blog
+ blog-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
+
+
+ spring-cloud-aws-sqs-testing
+ 0.0.1-SNAPSHOT
+ spring-cloud-aws-sqs-testing
+ spring-cloud-aws-sqs-testing
+
+
+ 3.1.0
+
+
+
+
+
+ io.awspring.cloud
+ spring-cloud-aws-dependencies
+ ${spring-cloud-aws.version}
+ pom
+ import
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ io.awspring.cloud
+ spring-cloud-aws-starter-sqs
+
+
+
+ com.h2database
+ h2
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ io.awspring.cloud
+ spring-cloud-aws-test
+ test
+
+
+ org.awaitility
+ awaitility
+ test
+
+
+ org.testcontainers
+ junit-jupiter
+ test
+
+
+ org.testcontainers
+ localstack
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
diff --git a/spring-cloud-aws-sqs-testing/src/main/java/de/rieckpil/Application.java b/spring-cloud-aws-sqs-testing/src/main/java/de/rieckpil/Application.java
new file mode 100644
index 00000000..22638758
--- /dev/null
+++ b/spring-cloud-aws-sqs-testing/src/main/java/de/rieckpil/Application.java
@@ -0,0 +1,12 @@
+package de.rieckpil;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+}
diff --git a/spring-cloud-aws-sqs-testing/src/main/java/de/rieckpil/OrderListener.java b/spring-cloud-aws-sqs-testing/src/main/java/de/rieckpil/OrderListener.java
new file mode 100644
index 00000000..936bfc68
--- /dev/null
+++ b/spring-cloud-aws-sqs-testing/src/main/java/de/rieckpil/OrderListener.java
@@ -0,0 +1,39 @@
+package de.rieckpil;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import io.awspring.cloud.sqs.annotation.SqsListener;
+import java.util.Map;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.messaging.handler.annotation.Headers;
+import org.springframework.messaging.handler.annotation.Payload;
+import org.springframework.stereotype.Component;
+
+@Component
+public class OrderListener {
+
+ private final PurchaseOrderRepository purchaseOrderRepository;
+
+ private static final Logger LOG = LoggerFactory.getLogger(OrderListener.class);
+
+ public OrderListener(PurchaseOrderRepository purchaseOrderRepository) {
+ this.purchaseOrderRepository = purchaseOrderRepository;
+ }
+
+ @SqsListener("${order-queue-name}")
+ public void processOrder(@Payload String rawPayload, @Headers Map payloadHeaders)
+ throws JsonProcessingException {
+ LOG.info("Incoming order payload {} with headers {}", rawPayload, payloadHeaders);
+
+ ObjectNode payload = new ObjectMapper().readValue(rawPayload, ObjectNode.class);
+
+ PurchaseOrder purchaseOrder = new PurchaseOrder();
+ purchaseOrder.setCustomer(payload.get("customerName").asText());
+ purchaseOrder.setAmount(payload.get("orderAmount").asLong());
+ purchaseOrder.setDelivered(false);
+
+ purchaseOrderRepository.save(purchaseOrder);
+ }
+}
diff --git a/spring-cloud-aws-sqs-testing/src/main/java/de/rieckpil/PurchaseOrder.java b/spring-cloud-aws-sqs-testing/src/main/java/de/rieckpil/PurchaseOrder.java
new file mode 100644
index 00000000..16715dd5
--- /dev/null
+++ b/spring-cloud-aws-sqs-testing/src/main/java/de/rieckpil/PurchaseOrder.java
@@ -0,0 +1,49 @@
+package de.rieckpil;
+
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.Id;
+
+@Entity
+public class PurchaseOrder {
+
+ @Id @GeneratedValue private Long id;
+
+ private String customer;
+
+ private Long amount;
+
+ private boolean delivered;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getCustomer() {
+ return customer;
+ }
+
+ public void setCustomer(String customer) {
+ this.customer = customer;
+ }
+
+ public Long getAmount() {
+ return amount;
+ }
+
+ public void setAmount(Long amount) {
+ this.amount = amount;
+ }
+
+ public boolean isDelivered() {
+ return delivered;
+ }
+
+ public void setDelivered(boolean delivered) {
+ this.delivered = delivered;
+ }
+}
diff --git a/spring-cloud-aws-sqs-testing/src/main/java/de/rieckpil/PurchaseOrderPayload.java b/spring-cloud-aws-sqs-testing/src/main/java/de/rieckpil/PurchaseOrderPayload.java
new file mode 100644
index 00000000..633c6daf
--- /dev/null
+++ b/spring-cloud-aws-sqs-testing/src/main/java/de/rieckpil/PurchaseOrderPayload.java
@@ -0,0 +1,30 @@
+package de.rieckpil;
+
+public class PurchaseOrderPayload {
+
+ private String customerName;
+ private Long orderAmount;
+
+ public PurchaseOrderPayload() {}
+
+ public PurchaseOrderPayload(String customerName, Long orderAmount) {
+ this.customerName = customerName;
+ this.orderAmount = orderAmount;
+ }
+
+ public String getCustomerName() {
+ return customerName;
+ }
+
+ public void setCustomerName(String customerName) {
+ this.customerName = customerName;
+ }
+
+ public Long getOrderAmount() {
+ return orderAmount;
+ }
+
+ public void setOrderAmount(Long orderAmount) {
+ this.orderAmount = orderAmount;
+ }
+}
diff --git a/spring-cloud-aws-sqs-testing/src/main/java/de/rieckpil/PurchaseOrderRepository.java b/spring-cloud-aws-sqs-testing/src/main/java/de/rieckpil/PurchaseOrderRepository.java
new file mode 100644
index 00000000..017048fa
--- /dev/null
+++ b/spring-cloud-aws-sqs-testing/src/main/java/de/rieckpil/PurchaseOrderRepository.java
@@ -0,0 +1,5 @@
+package de.rieckpil;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface PurchaseOrderRepository extends JpaRepository {}
diff --git a/spring-cloud-aws-sqs-testing/src/main/resources/application.properties b/spring-cloud-aws-sqs-testing/src/main/resources/application.properties
new file mode 100644
index 00000000..e69de29b
diff --git a/spring-cloud-aws-sqs-testing/src/test/java/de/rieckpil/OrderListenerTest.java b/spring-cloud-aws-sqs-testing/src/test/java/de/rieckpil/OrderListenerTest.java
new file mode 100644
index 00000000..06b5d018
--- /dev/null
+++ b/spring-cloud-aws-sqs-testing/src/test/java/de/rieckpil/OrderListenerTest.java
@@ -0,0 +1,63 @@
+package de.rieckpil;
+
+import static org.awaitility.Awaitility.await;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.verify;
+import static org.testcontainers.containers.localstack.LocalStackContainer.Service;
+import static org.testcontainers.containers.localstack.LocalStackContainer.Service.SQS;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import io.awspring.cloud.sqs.operations.SqsTemplate;
+import io.awspring.cloud.test.sqs.SqsTest;
+import java.time.Duration;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.test.context.DynamicPropertyRegistry;
+import org.springframework.test.context.DynamicPropertySource;
+import org.testcontainers.containers.BindMode;
+import org.testcontainers.containers.localstack.LocalStackContainer;
+import org.testcontainers.containers.wait.strategy.Wait;
+import org.testcontainers.junit.jupiter.Container;
+import org.testcontainers.junit.jupiter.Testcontainers;
+import org.testcontainers.utility.DockerImageName;
+
+@Testcontainers
+@SqsTest(OrderListener.class)
+class OrderListenerTest {
+
+ @Container
+ static LocalStackContainer localStack =
+ new LocalStackContainer(DockerImageName.parse("localstack/localstack:0.14.3"))
+ .withClasspathResourceMapping(
+ "/localstack", "/docker-entrypoint-initaws.d", BindMode.READ_ONLY)
+ .withServices(Service.SQS)
+ .waitingFor(Wait.forLogMessage(".*Initialized\\.\n", 1));
+
+ @DynamicPropertySource
+ static void properties(DynamicPropertyRegistry registry) {
+ registry.add(
+ "spring.cloud.aws.sqs.endpoint", () -> localStack.getEndpointOverride(SQS).toString());
+ registry.add("spring.cloud.aws.credentials.access-key", () -> "foo");
+ registry.add("spring.cloud.aws.credentials.secret-key", () -> "bar");
+ registry.add("spring.cloud.aws.region.static", () -> localStack.getRegion());
+ registry.add("order-queue-name", () -> "test-order-queue");
+ }
+
+ @Autowired private SqsTemplate sqsTemplate;
+
+ @MockBean private PurchaseOrderRepository purchaseOrderRepository;
+
+ @Test
+ void shouldStoreIncomingPurchaseOrderInDatabase() throws JsonProcessingException {
+
+ sqsTemplate.send(
+ "test-order-queue",
+ new ObjectMapper().writeValueAsString(new PurchaseOrderPayload("duke", 42L)));
+
+ await()
+ .atMost(Duration.ofSeconds(3))
+ .untilAsserted(() -> verify(purchaseOrderRepository).save(any(PurchaseOrder.class)));
+ }
+}
diff --git a/spring-cloud-aws-sqs-testing/src/test/resources/localstack/init.sh b/spring-cloud-aws-sqs-testing/src/test/resources/localstack/init.sh
new file mode 100755
index 00000000..a47f14b5
--- /dev/null
+++ b/spring-cloud-aws-sqs-testing/src/test/resources/localstack/init.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+awslocal sqs create-queue --queue-name test-order-queue
+
+echo "Initialized."
diff --git a/spring-cloud-aws-sqs-testing/src/test/resources/logback-test.xml b/spring-cloud-aws-sqs-testing/src/test/resources/logback-test.xml
new file mode 100644
index 00000000..28cbf968
--- /dev/null
+++ b/spring-cloud-aws-sqs-testing/src/test/resources/logback-test.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-cloud-function-aws-kotlin/.gitignore b/spring-cloud-function-aws-kotlin/.gitignore
new file mode 100644
index 00000000..b88aa583
--- /dev/null
+++ b/spring-cloud-function-aws-kotlin/.gitignore
@@ -0,0 +1,36 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+.gradle
+.serverless
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
diff --git a/spring-cloud-function-aws-kotlin/.java-version b/spring-cloud-function-aws-kotlin/.java-version
new file mode 100644
index 00000000..b4de3947
--- /dev/null
+++ b/spring-cloud-function-aws-kotlin/.java-version
@@ -0,0 +1 @@
+11
diff --git a/spring-cloud-function-aws-kotlin/.mvn/wrapper/MavenWrapperDownloader.java b/spring-cloud-function-aws-kotlin/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 00000000..068c4d62
--- /dev/null
+++ b/spring-cloud-function-aws-kotlin/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2007-present 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.
+ */
+
+import java.net.*;
+import java.io.*;
+import java.nio.channels.*;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ private static final String WRAPPER_VERSION = "0.5.6";
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if (mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if (mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if (!outputFile.getParentFile().exists()) {
+ if (!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
+ String username = System.getenv("MVNW_USERNAME");
+ char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
+ Authenticator.setDefault(new Authenticator() {
+ @Override
+ protected PasswordAuthentication getPasswordAuthentication() {
+ return new PasswordAuthentication(username, password);
+ }
+ });
+ }
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/spring-cloud-function-aws-kotlin/.mvn/wrapper/maven-wrapper.jar b/spring-cloud-function-aws-kotlin/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 00000000..2cc7d4a5
Binary files /dev/null and b/spring-cloud-function-aws-kotlin/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-cloud-function-aws-kotlin/.mvn/wrapper/maven-wrapper.properties b/spring-cloud-function-aws-kotlin/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 00000000..abd303b6
--- /dev/null
+++ b/spring-cloud-function-aws-kotlin/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,2 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.2/apache-maven-3.8.2-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
diff --git a/spring-cloud-function-aws-kotlin/README.md b/spring-cloud-function-aws-kotlin/README.md
new file mode 100644
index 00000000..0999ba7c
--- /dev/null
+++ b/spring-cloud-function-aws-kotlin/README.md
@@ -0,0 +1,103 @@
+# Minimum Reproducible Example for a Spring Boot + Kotlin + Spring Cloud AWS Lambda Setup
+
+**Fixed since Spring Cloud Function > 3.2.0-M2**: https://github.com/spring-cloud/spring-cloud-function/issues/747
+
+Steps to reproduce:
+
+1. `npm install -g serverless`
+2. `mvn package`
+3. `sls invoke local -f test`
+
+```
+19:04:10.497 [main] INFO org.springframework.cloud.function.utils.FunctionClassUtils - Searching for start class in manifest: jar:file:/Users/rieckpil/Development/git/blog-tutorials/spring-cloud-function-aws-kotlin/./target/spring-cloud-function-aws-kotlin-1.0.0-aws.jar!/META-INF/MANIFEST.MF
+
+Manifest-Version: 1.0
+Created-By: Maven Jar Plugin 3.2.0
+Build-Jdk-Spec: 11
+Implementation-Title: spring-cloud-function-aws-kotlin
+Implementation-Version: 1.0.0
+Main-Class: org.springframework.boot.loader.wrapper.ThinJarWrapper
+Start-Class: de.rieckpil.ApplicationKt
+
+Spring-Boot-Version: 2.5.5
+Spring-Boot-Classes:
+
+
+java.lang.IllegalStateException: Failed to discover main class. An attempt was made to discover main class as 'MAIN_CLASS' environment variable, system property as well as entry in META-INF/MANIFEST.MF (in that order).
+
+ at org.springframework.cloud.function.utils.FunctionClassUtils.getStartClass(FunctionClassUtils.java:83)
+ at org.springframework.cloud.function.utils.FunctionClassUtils.getStartClass(FunctionClassUtils.java:60)
+ at org.springframework.cloud.function.adapter.aws.FunctionInvoker.start(FunctionInvoker.java:123)
+ at org.springframework.cloud.function.adapter.aws.FunctionInvoker.(FunctionInvoker.java:70)
+ at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
+ at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
+
+ at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
+ at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
+ at java.base/java.lang.Class.newInstance(Class.java:584)
+ at com.serverless.InvokeBridge.getInstance(InvokeBridge.java:71)
+ at com.serverless.InvokeBridge.(InvokeBridge.java:36)
+ at com.serverless.InvokeBridge.main(InvokeBridge.java:137)
+
+Caused by: java.lang.IllegalArgumentException: Failed to locate main class
+ at org.springframework.util.Assert.notNull(Assert.java:201)
+ at org.springframework.cloud.function.utils.FunctionClassUtils.getStartClass(FunctionClassUtils.java:79)
+
+ ... 11 more
+
+
+```
+
+Second try:
+
+1. Add `MAIN_CLASS` to the `serverless.yml`:
+```yaml
+# ...
+functions:
+ test:
+ handler: org.springframework.cloud.function.adapter.aws.FunctionInvoker
+ environment:
+ MAIN_CLASS: org.springframework.boot.loader.wrapper.ThinJarWrapper
+```
+
+2. `mvn clean package`
+3. `sls invoke local -f test`
+
+```
+ . ____ _ __ _ _
+
+ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
+( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
+ \\/ ___)| |_)| | | | | || (_| | ) ) ) )
+ ' |____| .__|_| |_|_| |_\__, | / / / /
+ =========|_|==============|___/=/_/_/_/
+
+ :: Spring Boot :: (v1.0.0)
+
+
+2021-09-23 19:05:45.381 INFO 49067 --- [ main] com.serverless.InvokeBridge : Starting InvokeBridge using Java 11.0.11 on Philips-MBP.fritz.box with PID 49067 (/Users/rieckpil/.nvm/versions/node/v15.14.0/lib/node_modules/serverless/lib/plugins/aws/invokeLocal/runtimeWrappers/java/target/invoke-bridge-1.0.1.jar started by rieckpil in /Users/rieckpil/Development/git/blog-tutorials/spring-cloud-function-aws-kotlin)
+
+2021-09-23 19:05:45.382 INFO 49067 --- [ main] com.serverless.InvokeBridge : No active profile set, falling back to default profiles: default
+
+2021-09-23 19:05:45.427 INFO 49067 --- [ main] com.serverless.InvokeBridge : Started InvokeBridge in 0.253 seconds (JVM running for 0.533)
+
+org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.cloud.function.context.FunctionCatalog' available
+
+ at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:351)
+ at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:342)
+ at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1172)
+ at org.springframework.cloud.function.adapter.aws.FunctionInvoker.start(FunctionInvoker.java:131)
+ at org.springframework.cloud.function.adapter.aws.FunctionInvoker.(FunctionInvoker.java:70)
+ at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
+
+ at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
+ at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
+ at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
+ at java.base/java.lang.Class.newInstance(Class.java:584)
+ at com.serverless.InvokeBridge.getInstance(InvokeBridge.java:71)
+ at com.serverless.InvokeBridge.(InvokeBridge.java:36)
+
+ at com.serverless.InvokeBridge.main(InvokeBridge.java:137)
+```
+
+-> Spring Context starts, but fails to inject beans
diff --git a/spring-cloud-function-aws-kotlin/mvnw b/spring-cloud-function-aws-kotlin/mvnw
new file mode 100755
index 00000000..a16b5431
--- /dev/null
+++ b/spring-cloud-function-aws-kotlin/mvnw
@@ -0,0 +1,310 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# M2_HOME - location of maven2's installed home dir
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ export JAVA_HOME="`/usr/libexec/java_home`"
+ else
+ export JAVA_HOME="/Library/Java/Home"
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=`java-config --jre-home`
+ fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+ ## resolve links - $0 may be a link to maven's home
+ PRG="$0"
+
+ # need this for relative symlinks
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG="`dirname "$PRG"`/$link"
+ fi
+ done
+
+ saveddir=`pwd`
+
+ M2_HOME=`dirname "$PRG"`/..
+
+ # make it fully qualified
+ M2_HOME=`cd "$M2_HOME" && pwd`
+
+ cd "$saveddir"
+ # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --unix "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME="`(cd "$M2_HOME"; pwd)`"
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="`which javac`"
+ if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=`which readlink`
+ if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+ if $darwin ; then
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+ else
+ javaExecutable="`readlink -f \"$javaExecutable\"`"
+ fi
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="`which java`"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=`cd "$wdir/.."; pwd`
+ fi
+ # end of workaround
+ done
+ echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ echo "$(tr -s '\n' ' ' < "$1")"
+ fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found .mvn/wrapper/maven-wrapper.jar"
+ fi
+else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+ fi
+ if [ -n "$MVNW_REPOURL" ]; then
+ jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ else
+ jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ fi
+ while IFS="=" read key value; do
+ case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
+ esac
+ done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Downloading from: $jarUrl"
+ fi
+ wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+ if $cygwin; then
+ wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
+ fi
+
+ if command -v wget > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found wget ... using wget"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget "$jarUrl" -O "$wrapperJarPath"
+ else
+ wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
+ fi
+ elif command -v curl > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found curl ... using curl"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl -o "$wrapperJarPath" "$jarUrl" -f
+ else
+ curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
+ fi
+
+ else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Falling back to using Java to download"
+ fi
+ javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaClass=`cygpath --path --windows "$javaClass"`
+ fi
+ if [ -e "$javaClass" ]; then
+ if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Compiling MavenWrapperDownloader.java ..."
+ fi
+ # Compiling the Java class
+ ("$JAVA_HOME/bin/javac" "$javaClass")
+ fi
+ if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ # Running the downloader
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Running MavenWrapperDownloader.java ..."
+ fi
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+if [ "$MVNW_VERBOSE" = true ]; then
+ echo $MAVEN_PROJECTBASEDIR
+fi
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --path --windows "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/spring-cloud-function-aws-kotlin/mvnw.cmd b/spring-cloud-function-aws-kotlin/mvnw.cmd
new file mode 100644
index 00000000..c8d43372
--- /dev/null
+++ b/spring-cloud-function-aws-kotlin/mvnw.cmd
@@ -0,0 +1,182 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM https://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
+if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+
+FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Found %WRAPPER_JAR%
+ )
+) else (
+ if not "%MVNW_REPOURL%" == "" (
+ SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ )
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %DOWNLOAD_URL%
+ )
+
+ powershell -Command "&{"^
+ "$webclient = new-object System.Net.WebClient;"^
+ "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+ "}"^
+ "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
+ "}"
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Finished downloading %WRAPPER_JAR%
+ )
+)
+@REM End of extension
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
+if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%" == "on" pause
+
+if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
+
+exit /B %ERROR_CODE%
diff --git a/spring-cloud-function-aws-kotlin/pom.xml b/spring-cloud-function-aws-kotlin/pom.xml
new file mode 100644
index 00000000..426e3e6f
--- /dev/null
+++ b/spring-cloud-function-aws-kotlin/pom.xml
@@ -0,0 +1,184 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.5.5
+
+
+
+ de.rieckpil
+ spring-cloud-function-aws-kotlin
+ 1.0.0
+ spring-cloud-function-aws-kotlin
+ spring-cloud-function-aws-kotlin
+
+
+ 11
+ 1.5.31
+ 3.2.0-M2
+ 1.0.27.RELEASE
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+ org.jetbrains.kotlin
+ kotlin-reflect
+
+
+ org.jetbrains.kotlin
+ kotlin-stdlib-jdk8
+
+
+
+ org.springframework.cloud
+ spring-cloud-function-web
+
+
+ org.springframework.cloud
+ spring-cloud-function-adapter-aws
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-function-dependencies
+ ${spring-cloud-function.version}
+ pom
+ import
+
+
+
+
+
+ ${project.basedir}/src/main/kotlin
+ ${project.basedir}/src/test/kotlin
+ ${project.artifactId}
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ org.springframework.boot.experimental
+ spring-boot-thin-layout
+ ${wrapper.version}
+
+
+
+
+ org.jetbrains.kotlin
+ kotlin-maven-plugin
+
+
+ -Xjsr305=strict
+
+
+ spring
+
+
+
+
+ org.jetbrains.kotlin
+ kotlin-maven-allopen
+ ${kotlin.version}
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 3.2.4
+
+ false
+ true
+ aws
+
+
+
+
+
+
+
+ false
+
+ central
+ bintray
+ https://jcenter.bintray.com
+
+
+ spring-releases
+ Spring Releases
+ https://repo.spring.io/release
+
+ false
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
+
+ false
+
+ central
+ bintray-plugins
+ https://jcenter.bintray.com
+
+
+ spring-releases
+ Spring Releases
+ https://repo.spring.io/release
+
+ false
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
diff --git a/spring-cloud-function-aws-kotlin/serverless.yml b/spring-cloud-function-aws-kotlin/serverless.yml
new file mode 100644
index 00000000..7742db64
--- /dev/null
+++ b/spring-cloud-function-aws-kotlin/serverless.yml
@@ -0,0 +1,22 @@
+service: kotlin-spring-cloud-aws-test
+
+variablesResolutionMode: 20210326
+
+provider:
+ name: aws
+ runtime: java11
+ stage: production
+ region: eu-central-1
+ timeout: 120
+ memorySize: 1024
+ logRetentionInDays: 7
+ lambdaHashingVersion: 20201221
+
+package:
+ artifact: target/spring-cloud-function-aws-kotlin-1.0.0-aws.jar
+
+functions:
+ test:
+ handler: org.springframework.cloud.function.adapter.aws.FunctionInvoker
+ environment:
+ SPRING_CLOUD_FUNCTION_DEFINITION: test
diff --git a/spring-cloud-function-aws-kotlin/src/main/kotlin/de/rieckpil/Application.kt b/spring-cloud-function-aws-kotlin/src/main/kotlin/de/rieckpil/Application.kt
new file mode 100644
index 00000000..f0778ec9
--- /dev/null
+++ b/spring-cloud-function-aws-kotlin/src/main/kotlin/de/rieckpil/Application.kt
@@ -0,0 +1,11 @@
+package de.rieckpil
+
+import org.springframework.boot.autoconfigure.SpringBootApplication
+import org.springframework.boot.runApplication
+
+@SpringBootApplication
+class Application
+
+fun main(args: Array) {
+ runApplication(*args)
+}
diff --git a/spring-cloud-function-aws-kotlin/src/main/kotlin/de/rieckpil/CustomFunctionConfig.kt b/spring-cloud-function-aws-kotlin/src/main/kotlin/de/rieckpil/CustomFunctionConfig.kt
new file mode 100644
index 00000000..dc14cca7
--- /dev/null
+++ b/spring-cloud-function-aws-kotlin/src/main/kotlin/de/rieckpil/CustomFunctionConfig.kt
@@ -0,0 +1,16 @@
+package de.rieckpil
+
+import org.springframework.context.annotation.Bean
+import org.springframework.context.annotation.Configuration
+import org.springframework.messaging.Message
+
+@Configuration
+class CustomFunctionConfig {
+
+ @Bean
+ fun test(): (Message) -> Unit {
+ return {
+ println("Works!")
+ }
+ }
+}
diff --git a/spring-cloud-function-aws-kotlin/src/main/resources/application.properties b/spring-cloud-function-aws-kotlin/src/main/resources/application.properties
new file mode 100644
index 00000000..8b137891
--- /dev/null
+++ b/spring-cloud-function-aws-kotlin/src/main/resources/application.properties
@@ -0,0 +1 @@
+
diff --git a/spring-cloud-function-aws-kotlin/src/main/resources/logback.xml b/spring-cloud-function-aws-kotlin/src/main/resources/logback.xml
new file mode 100644
index 00000000..7bf39b86
--- /dev/null
+++ b/spring-cloud-function-aws-kotlin/src/main/resources/logback.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-cloud-function-aws-kotlin/src/test/kotlin/de/rieckpil/SpringCloudFunctionAwsKotlinApplicationTests.kt b/spring-cloud-function-aws-kotlin/src/test/kotlin/de/rieckpil/SpringCloudFunctionAwsKotlinApplicationTests.kt
new file mode 100644
index 00000000..46c7a18a
--- /dev/null
+++ b/spring-cloud-function-aws-kotlin/src/test/kotlin/de/rieckpil/SpringCloudFunctionAwsKotlinApplicationTests.kt
@@ -0,0 +1,13 @@
+package de.rieckpil
+
+import org.junit.jupiter.api.Test
+import org.springframework.boot.test.context.SpringBootTest
+
+@SpringBootTest
+class SpringCloudFunctionAwsKotlinApplicationTests {
+
+ @Test
+ fun contextLoads() {
+ }
+
+}
diff --git a/spring-data-mongo-test-testcontainers/pom.xml b/spring-data-mongo-test-testcontainers/pom.xml
index 034f8032..d37f2088 100644
--- a/spring-data-mongo-test-testcontainers/pom.xml
+++ b/spring-data-mongo-test-testcontainers/pom.xml
@@ -2,23 +2,19 @@
4.0.0
+
- org.springframework.boot
- spring-boot-starter-parent
- 2.4.0
-
+ de.rieckpil.blog
+ blog-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
- de.rieckpil.blog
+
spring-data-mongo-test-testcontainers
0.0.1-SNAPSHOT
spring-data-mongo-test-testcontainers
-
- 11
- 1.15.1
-
-
org.springframework.boot
@@ -46,18 +42,6 @@
-
-
-
- org.testcontainers
- testcontainers-bom
- ${testcontainers.version}
- pom
- import
-
-
-
-
diff --git a/spring-data-mongo-test-testcontainers/src/main/java/de/rieckpil/blog/Application.java b/spring-data-mongo-test-testcontainers/src/main/java/de/rieckpil/blog/Application.java
index bd5e4c56..6511f3c1 100644
--- a/spring-data-mongo-test-testcontainers/src/main/java/de/rieckpil/blog/Application.java
+++ b/spring-data-mongo-test-testcontainers/src/main/java/de/rieckpil/blog/Application.java
@@ -9,5 +9,4 @@ public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
-
}
diff --git a/spring-data-mongo-test-testcontainers/src/main/java/de/rieckpil/blog/Customer.java b/spring-data-mongo-test-testcontainers/src/main/java/de/rieckpil/blog/Customer.java
index 69f1a2c4..4871fe56 100644
--- a/spring-data-mongo-test-testcontainers/src/main/java/de/rieckpil/blog/Customer.java
+++ b/spring-data-mongo-test-testcontainers/src/main/java/de/rieckpil/blog/Customer.java
@@ -6,16 +6,13 @@
@Document
public class Customer {
- @Id
- private String id;
+ @Id private String id;
private String email;
private Integer rating;
- public Customer() {
-
- }
+ public Customer() {}
public Customer(String email, Integer rating) {
this.email = email;
diff --git a/spring-data-mongo-test-testcontainers/src/main/java/de/rieckpil/blog/CustomerRepository.java b/spring-data-mongo-test-testcontainers/src/main/java/de/rieckpil/blog/CustomerRepository.java
index ebb9e65e..59f6f784 100644
--- a/spring-data-mongo-test-testcontainers/src/main/java/de/rieckpil/blog/CustomerRepository.java
+++ b/spring-data-mongo-test-testcontainers/src/main/java/de/rieckpil/blog/CustomerRepository.java
@@ -1,10 +1,9 @@
package de.rieckpil.blog;
+import java.util.List;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.mongodb.repository.Query;
-import java.util.List;
-
public interface CustomerRepository extends MongoRepository {
@Query(sort = "{ rating : 1 }")
diff --git a/spring-data-mongo-test-testcontainers/src/main/java/de/rieckpil/blog/CustomerService.java b/spring-data-mongo-test-testcontainers/src/main/java/de/rieckpil/blog/CustomerService.java
index 6582d42d..e78b237f 100644
--- a/spring-data-mongo-test-testcontainers/src/main/java/de/rieckpil/blog/CustomerService.java
+++ b/spring-data-mongo-test-testcontainers/src/main/java/de/rieckpil/blog/CustomerService.java
@@ -1,12 +1,11 @@
package de.rieckpil.blog;
+import java.util.List;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
-import java.util.List;
-
@Service
public class CustomerService {
diff --git a/spring-data-mongo-test-testcontainers/src/test/java/de/rieckpil/blog/CustomerRepositoryTest.java b/spring-data-mongo-test-testcontainers/src/test/java/de/rieckpil/blog/CustomerRepositoryTest.java
index 4d7f6ad9..f689e042 100644
--- a/spring-data-mongo-test-testcontainers/src/test/java/de/rieckpil/blog/CustomerRepositoryTest.java
+++ b/spring-data-mongo-test-testcontainers/src/test/java/de/rieckpil/blog/CustomerRepositoryTest.java
@@ -1,9 +1,11 @@
package de.rieckpil.blog;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.List;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration;
import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
@@ -11,24 +13,18 @@
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
-import java.util.List;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
@Testcontainers
-@DataMongoTest(excludeAutoConfiguration = EmbeddedMongoAutoConfiguration.class)
+@DataMongoTest
class CustomerRepositoryTest {
- @Container
- static MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:4.4.2");
+ @Container static MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:4.4.2");
@DynamicPropertySource
static void setProperties(DynamicPropertyRegistry registry) {
registry.add("spring.data.mongodb.uri", mongoDBContainer::getReplicaSetUrl);
}
- @Autowired
- private CustomerRepository customerRepository;
+ @Autowired private CustomerRepository customerRepository;
@AfterEach
void cleanUp() {
@@ -59,4 +55,3 @@ void shouldReturnOrderedListOfCustomer() {
assertEquals("mike@spring.io", customers.get(2).getEmail());
}
}
-
diff --git a/spring-data-mongo-test-testcontainers/src/test/java/de/rieckpil/blog/CustomerServiceTest.java b/spring-data-mongo-test-testcontainers/src/test/java/de/rieckpil/blog/CustomerServiceTest.java
index 3009b32b..7307c8d7 100644
--- a/spring-data-mongo-test-testcontainers/src/test/java/de/rieckpil/blog/CustomerServiceTest.java
+++ b/spring-data-mongo-test-testcontainers/src/test/java/de/rieckpil/blog/CustomerServiceTest.java
@@ -1,9 +1,11 @@
package de.rieckpil.blog;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.List;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration;
import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.test.context.DynamicPropertyRegistry;
@@ -12,24 +14,18 @@
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
-import java.util.List;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
@Testcontainers
-@DataMongoTest(excludeAutoConfiguration = EmbeddedMongoAutoConfiguration.class)
+@DataMongoTest
class CustomerServiceTest {
- @Container
- static MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:4.4.2");
+ @Container static MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:4.4.2");
@DynamicPropertySource
static void setProperties(DynamicPropertyRegistry registry) {
registry.add("spring.data.mongodb.uri", mongoDBContainer::getReplicaSetUrl);
}
- @Autowired
- private MongoTemplate mongoTemplate;
+ @Autowired private MongoTemplate mongoTemplate;
private CustomerService cut;
diff --git a/spring-mockmvc-with-webtestclient/.java-version b/spring-mockmvc-with-webtestclient/.java-version
new file mode 100644
index 00000000..5f39e914
--- /dev/null
+++ b/spring-mockmvc-with-webtestclient/.java-version
@@ -0,0 +1 @@
+21.0
diff --git a/spring-mockmvc-with-webtestclient/pom.xml b/spring-mockmvc-with-webtestclient/pom.xml
index 5f82c494..17655659 100644
--- a/spring-mockmvc-with-webtestclient/pom.xml
+++ b/spring-mockmvc-with-webtestclient/pom.xml
@@ -2,22 +2,19 @@
4.0.0
+
- org.springframework.boot
- spring-boot-starter-parent
- 2.4.0
-
+ de.rieckpil.blog
+ blog-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
- de.rieckpil.blog
+
spring-mockmvc-with-webtestclient
0.0.1-SNAPSHOT
spring-mockmvc-with-webtestclient
Demo project for Spring Boot
-
- 11
-
-
org.springframework.boot
@@ -56,14 +53,4 @@
test
-
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
-
-
-
diff --git a/spring-mockmvc-with-webtestclient/src/main/java/de/rieckpil/blog/Application.java b/spring-mockmvc-with-webtestclient/src/main/java/de/rieckpil/blog/Application.java
index bd5e4c56..6511f3c1 100644
--- a/spring-mockmvc-with-webtestclient/src/main/java/de/rieckpil/blog/Application.java
+++ b/spring-mockmvc-with-webtestclient/src/main/java/de/rieckpil/blog/Application.java
@@ -9,5 +9,4 @@ public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
-
}
diff --git a/spring-mockmvc-with-webtestclient/src/main/java/de/rieckpil/blog/DashboardController.java b/spring-mockmvc-with-webtestclient/src/main/java/de/rieckpil/blog/DashboardController.java
index 934aa897..51e5deaf 100644
--- a/spring-mockmvc-with-webtestclient/src/main/java/de/rieckpil/blog/DashboardController.java
+++ b/spring-mockmvc-with-webtestclient/src/main/java/de/rieckpil/blog/DashboardController.java
@@ -1,12 +1,11 @@
package de.rieckpil.blog;
+import java.util.Arrays;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
-import java.util.Arrays;
-
@Controller
@RequestMapping("/dashboard")
public class DashboardController {
diff --git a/spring-mockmvc-with-webtestclient/src/main/java/de/rieckpil/blog/User.java b/spring-mockmvc-with-webtestclient/src/main/java/de/rieckpil/blog/User.java
index 17227b4c..3cc9e3c4 100644
--- a/spring-mockmvc-with-webtestclient/src/main/java/de/rieckpil/blog/User.java
+++ b/spring-mockmvc-with-webtestclient/src/main/java/de/rieckpil/blog/User.java
@@ -1,22 +1,19 @@
package de.rieckpil.blog;
-import javax.validation.constraints.NotEmpty;
-import javax.validation.constraints.NotNull;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
class User {
- @NotNull
- private Long id;
+ @NotNull private Long id;
- @NotEmpty
- private String name;
+ @NotEmpty private String name;
private Set tags;
- public User() {
- }
+ public User() {}
public User(Long id, String name) {
this.name = name;
@@ -59,9 +56,9 @@ public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
- return Objects.equals(id, user.id) &&
- Objects.equals(name, user.name) &&
- Objects.equals(tags, user.tags);
+ return Objects.equals(id, user.id)
+ && Objects.equals(name, user.name)
+ && Objects.equals(tags, user.tags);
}
@Override
diff --git a/spring-mockmvc-with-webtestclient/src/main/java/de/rieckpil/blog/UserController.java b/spring-mockmvc-with-webtestclient/src/main/java/de/rieckpil/blog/UserController.java
index 5151ea3e..682e262f 100644
--- a/spring-mockmvc-with-webtestclient/src/main/java/de/rieckpil/blog/UserController.java
+++ b/spring-mockmvc-with-webtestclient/src/main/java/de/rieckpil/blog/UserController.java
@@ -1,15 +1,14 @@
package de.rieckpil.blog;
+import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
+
+import java.util.List;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;
-import java.util.List;
-
-import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
-
@RestController
@RequestMapping(value = "/api/users", produces = APPLICATION_JSON_VALUE)
public class UserController {
@@ -28,18 +27,24 @@ public List getAllUsers() {
@GetMapping("/{id}")
public User getUserById(@PathVariable("id") Long id) {
return userService
- .getUserById(id)
- .orElseThrow(() -> new UserNotFoundException(String.format("User with id [%s] not found", id)));
+ .getUserById(id)
+ .orElseThrow(
+ () -> new UserNotFoundException(String.format("User with id [%s] not found", id)));
}
@PostMapping(consumes = APPLICATION_JSON_VALUE)
- public ResponseEntity createNewUser(@RequestBody @Validated User user, UriComponentsBuilder uriComponentsBuilder) {
- User addedUser = this.userService.addNewUser(user)
- .orElseThrow(() -> new UserAlreadyExistsException(
- String.format("User with id [%s] is already present", user.getId())));
+ public ResponseEntity createNewUser(
+ @RequestBody @Validated User user, UriComponentsBuilder uriComponentsBuilder) {
+ User addedUser =
+ this.userService
+ .addNewUser(user)
+ .orElseThrow(
+ () ->
+ new UserAlreadyExistsException(
+ String.format("User with id [%s] is already present", user.getId())));
UriComponents uriComponents =
- uriComponentsBuilder.path("/api/users/{id}").buildAndExpand(addedUser.getId());
+ uriComponentsBuilder.path("/api/users/{id}").buildAndExpand(addedUser.getId());
return ResponseEntity.created(uriComponents.toUri()).build();
}
@@ -49,4 +54,3 @@ public void deleteUser(@PathVariable("id") Long id) {
this.userService.deleteUserById(id);
}
}
-
diff --git a/spring-mockmvc-with-webtestclient/src/main/java/de/rieckpil/blog/UserService.java b/spring-mockmvc-with-webtestclient/src/main/java/de/rieckpil/blog/UserService.java
index bf0d8989..cbb2ffdd 100644
--- a/spring-mockmvc-with-webtestclient/src/main/java/de/rieckpil/blog/UserService.java
+++ b/spring-mockmvc-with-webtestclient/src/main/java/de/rieckpil/blog/UserService.java
@@ -1,12 +1,11 @@
package de.rieckpil.blog;
-import org.springframework.stereotype.Service;
-
-import javax.annotation.PostConstruct;
+import jakarta.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
+import org.springframework.stereotype.Service;
@Service
public class UserService {
@@ -26,9 +25,7 @@ public List getAllUsers() {
}
public Optional getUserById(Long id) {
- return this.userList.stream()
- .filter(user -> user.getId() == id)
- .findFirst();
+ return this.userList.stream().filter(user -> user.getId() == id).findFirst();
}
public Optional addNewUser(User user) {
diff --git a/spring-mockmvc-with-webtestclient/src/main/java/de/rieckpil/blog/WebSecurityConfig.java b/spring-mockmvc-with-webtestclient/src/main/java/de/rieckpil/blog/WebSecurityConfig.java
index 288a6082..31b70db7 100644
--- a/spring-mockmvc-with-webtestclient/src/main/java/de/rieckpil/blog/WebSecurityConfig.java
+++ b/spring-mockmvc-with-webtestclient/src/main/java/de/rieckpil/blog/WebSecurityConfig.java
@@ -1,21 +1,29 @@
package de.rieckpil.blog;
+import static org.springframework.security.config.Customizer.withDefaults;
+
+import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
-import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.web.SecurityFilterChain;
@Configuration
-public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
+public class WebSecurityConfig {
+
+ @Bean
+ public SecurityFilterChain configure(HttpSecurity http) throws Exception {
+ http.authorizeHttpRequests(
+ authorize ->
+ authorize
+ .requestMatchers(HttpMethod.GET, "/dashboard")
+ .permitAll()
+ .requestMatchers("/api/users/**")
+ .authenticated()
+ .requestMatchers("/**")
+ .authenticated())
+ .httpBasic(withDefaults());
- @Override
- protected void configure(HttpSecurity http) throws Exception {
- http
- .authorizeRequests(authorize -> authorize
- .mvcMatchers(HttpMethod.GET, "/dashboard").permitAll()
- .mvcMatchers("/api/users/**").authenticated()
- .mvcMatchers("/**").authenticated()
- )
- .httpBasic();
+ return http.build();
}
}
diff --git a/spring-mockmvc-with-webtestclient/src/test/java/de/rieckpil/blog/ApplicationTests.java b/spring-mockmvc-with-webtestclient/src/test/java/de/rieckpil/blog/ApplicationTests.java
index 6158e9b9..da34f8f8 100644
--- a/spring-mockmvc-with-webtestclient/src/test/java/de/rieckpil/blog/ApplicationTests.java
+++ b/spring-mockmvc-with-webtestclient/src/test/java/de/rieckpil/blog/ApplicationTests.java
@@ -1,24 +1,19 @@
package de.rieckpil.blog;
+import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.reactive.server.WebTestClient;
-import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
-
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class ApplicationTests {
- @Autowired
- private WebTestClient webTestClient;
+ @Autowired private WebTestClient webTestClient;
@Test
void contextLoads() {
- this.webTestClient
- .get()
- .uri("/api/users")
- .exchange()
- .expectStatus().is4xxClientError();
+ this.webTestClient.get().uri("/api/users").exchange().expectStatus().is4xxClientError();
}
}
diff --git a/spring-mockmvc-with-webtestclient/src/test/java/de/rieckpil/blog/DashboardControllerTest.java b/spring-mockmvc-with-webtestclient/src/test/java/de/rieckpil/blog/DashboardControllerTest.java
index faad5556..58f5f65c 100644
--- a/spring-mockmvc-with-webtestclient/src/test/java/de/rieckpil/blog/DashboardControllerTest.java
+++ b/spring-mockmvc-with-webtestclient/src/test/java/de/rieckpil/blog/DashboardControllerTest.java
@@ -1,48 +1,49 @@
package de.rieckpil.blog;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
+
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
+import org.springframework.context.annotation.Import;
import org.springframework.test.web.reactive.server.EntityExchangeResult;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.client.MockMvcWebTestClient;
-import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.mockUser;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
-
+@Import(WebSecurityConfig.class)
@WebMvcTest(DashboardController.class)
class DashboardControllerTest {
- @Autowired
- private MockMvc mockMvc;
+ @Autowired private MockMvc mockMvc;
private WebTestClient webTestClient;
@BeforeEach
void setup() {
- this.webTestClient = MockMvcWebTestClient
- .bindTo(mockMvc)
- .build();
+ this.webTestClient = MockMvcWebTestClient.bindTo(mockMvc).build();
}
@Test
void shouldReturnDashboardViewWithDefaultModel() throws Exception {
- EntityExchangeResult result = this.webTestClient
- .get()
- .uri("/dashboard")
- .exchange()
- .expectStatus().is2xxSuccessful()
- .expectBody().returnResult();
+ EntityExchangeResult result =
+ this.webTestClient
+ .get()
+ .uri("/dashboard")
+ .exchange()
+ .expectStatus()
+ .is2xxSuccessful()
+ .expectBody()
+ .returnResult();
MockMvcWebTestClient.resultActionsFor(result)
- .andExpect(model().size(2))
- .andExpect(model().attributeExists("message"))
- .andExpect(model().attributeExists("orderIds"))
- .andExpect(model().attribute("message", "Hello World!"))
- .andExpect(view().name("dashboard"));
+ .andExpect(model().size(2))
+ .andExpect(model().attributeExists("message"))
+ .andExpect(model().attributeExists("orderIds"))
+ .andExpect(model().attribute("message", "Hello World!"))
+ .andExpect(view().name("dashboard"));
}
}
diff --git a/spring-mockmvc-with-webtestclient/src/test/java/de/rieckpil/blog/UserControllerMockMvcTest.java b/spring-mockmvc-with-webtestclient/src/test/java/de/rieckpil/blog/UserControllerMockMvcTest.java
index fc823618..f419f77c 100644
--- a/spring-mockmvc-with-webtestclient/src/test/java/de/rieckpil/blog/UserControllerMockMvcTest.java
+++ b/spring-mockmvc-with-webtestclient/src/test/java/de/rieckpil/blog/UserControllerMockMvcTest.java
@@ -1,34 +1,33 @@
package de.rieckpil.blog;
+import static org.mockito.Mockito.when;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+import java.util.List;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.context.annotation.Import;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
-import java.util.List;
-
-import static org.mockito.Mockito.when;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
-
+@Import(WebSecurityConfig.class)
@WebMvcTest(UserController.class)
class UserControllerMockMvcTest {
- @Autowired
- private MockMvc mockMvc;
+ @Autowired private MockMvc mockMvc;
- @MockBean
- private UserService userService;
+ @MockBean private UserService userService;
@Test
void shouldForbidAccessToUnauthenticatedRequests() throws Exception {
this.mockMvc
- .perform(MockMvcRequestBuilders.get("/api/users"))
- .andExpect(status().is4xxClientError());
+ .perform(MockMvcRequestBuilders.get("/api/users"))
+ .andExpect(status().is4xxClientError());
}
@Test
@@ -36,11 +35,11 @@ void shouldForbidAccessToUnauthenticatedRequests() throws Exception {
void shouldReturnListOfUsersForAuthenticatedRequests() throws Exception {
when(userService.getAllUsers())
- .thenReturn(List.of(new User(42L, "duke"), new User(24L, "mike")));
+ .thenReturn(List.of(new User(42L, "duke"), new User(24L, "mike")));
this.mockMvc
- .perform(MockMvcRequestBuilders.get("/api/users"))
- .andExpect(status().isOk())
- .andExpect(jsonPath("$.size()", Matchers.is(2)));
+ .perform(MockMvcRequestBuilders.get("/api/users"))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.size()", Matchers.is(2)));
}
}
diff --git a/spring-mockmvc-with-webtestclient/src/test/java/de/rieckpil/blog/UserControllerTest.java b/spring-mockmvc-with-webtestclient/src/test/java/de/rieckpil/blog/UserControllerTest.java
index 8850dbea..d9980fd9 100644
--- a/spring-mockmvc-with-webtestclient/src/test/java/de/rieckpil/blog/UserControllerTest.java
+++ b/spring-mockmvc-with-webtestclient/src/test/java/de/rieckpil/blog/UserControllerTest.java
@@ -1,5 +1,8 @@
package de.rieckpil.blog;
+import static org.mockito.Mockito.when;
+
+import java.util.List;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -12,42 +15,38 @@
import org.springframework.test.web.servlet.client.MockMvcWebTestClient;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
-import java.util.List;
-
-import static org.mockito.Mockito.when;
-
@WebMvcTest(UserController.class)
class UserControllerTest {
- @Autowired
- private MockMvc mockMvc;
+ @Autowired private MockMvc mockMvc;
- @MockBean
- private UserService userService;
+ @MockBean private UserService userService;
private WebTestClient webTestClient;
@BeforeEach
public void setup() {
- this.webTestClient = MockMvcWebTestClient
- .bindTo(mockMvc)
- .defaultHeader("X-Duke", "42")
- .filter(logRequest())
- .build();
+ this.webTestClient =
+ MockMvcWebTestClient.bindTo(mockMvc)
+ .defaultHeader("X-Duke", "42")
+ .filter(logRequest())
+ .build();
}
@Test
@WithMockUser(username = "duke")
void shouldReturnListOfUsersForAuthenticatedRequests() {
when(userService.getAllUsers())
- .thenReturn(List.of(new User(42L, "duke"), new User(24L, "mike")));
+ .thenReturn(List.of(new User(42L, "duke"), new User(24L, "mike")));
this.webTestClient
- .get()
- .uri("/api/users")
- .exchange()
- .expectStatus().is2xxSuccessful()
- .expectBody().jsonPath("$.size()", Matchers.is(2));
+ .get()
+ .uri("/api/users")
+ .exchange()
+ .expectStatus()
+ .is2xxSuccessful()
+ .expectBody()
+ .jsonPath("$.size()", Matchers.is(2));
}
private ExchangeFilterFunction logRequest() {
diff --git a/spring-security-aws-cognito-thymeleaf/pom.xml b/spring-security-aws-cognito-thymeleaf/pom.xml
index df49716c..807c2b32 100644
--- a/spring-security-aws-cognito-thymeleaf/pom.xml
+++ b/spring-security-aws-cognito-thymeleaf/pom.xml
@@ -4,22 +4,17 @@
4.0.0
- org.springframework.boot
- spring-boot-starter-parent
- 2.3.0.RELEASE
-
+ de.rieckpil.blog
+ blog-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
- de.rieckpil.blog
spring-security-aws-cognito-thymeleaf
0.0.1-SNAPSHOT
spring-security-aws-cognito-thymeleaf
Demo project using AWS Cognito with Spring Security
-
- 11
-
-
org.springframework.boot
@@ -40,19 +35,13 @@
org.thymeleaf.extras
- thymeleaf-extras-springsecurity5
+ thymeleaf-extras-springsecurity6
org.springframework.boot
spring-boot-starter-test
test
-
-
- org.junit.vintage
- junit-vintage-engine
-
-
org.springframework.security
diff --git a/spring-security-aws-cognito-thymeleaf/src/main/java/de/rieckpil/blog/Application.java b/spring-security-aws-cognito-thymeleaf/src/main/java/de/rieckpil/blog/Application.java
index bd5e4c56..6511f3c1 100644
--- a/spring-security-aws-cognito-thymeleaf/src/main/java/de/rieckpil/blog/Application.java
+++ b/spring-security-aws-cognito-thymeleaf/src/main/java/de/rieckpil/blog/Application.java
@@ -9,5 +9,4 @@ public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
-
}
diff --git a/spring-security-aws-cognito-thymeleaf/src/main/java/de/rieckpil/blog/CognitoOidcLogoutSuccessHandler.java b/spring-security-aws-cognito-thymeleaf/src/main/java/de/rieckpil/blog/CognitoOidcLogoutSuccessHandler.java
index 811d6f15..3d86eb07 100644
--- a/spring-security-aws-cognito-thymeleaf/src/main/java/de/rieckpil/blog/CognitoOidcLogoutSuccessHandler.java
+++ b/spring-security-aws-cognito-thymeleaf/src/main/java/de/rieckpil/blog/CognitoOidcLogoutSuccessHandler.java
@@ -1,16 +1,15 @@
package de.rieckpil.blog;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import java.net.URI;
+import java.nio.charset.StandardCharsets;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;
import org.springframework.security.web.util.UrlUtils;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.net.URI;
-import java.nio.charset.StandardCharsets;
-
public class CognitoOidcLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
private final String logoutUrl;
@@ -22,22 +21,21 @@ public CognitoOidcLogoutSuccessHandler(String logoutUrl, String clientId) {
}
@Override
- protected String determineTargetUrl(HttpServletRequest request, HttpServletResponse response,
- Authentication authentication) {
-
- UriComponents baseUrl = UriComponentsBuilder
- .fromHttpUrl(UrlUtils.buildFullRequestUrl(request))
- .replacePath(request.getContextPath())
- .replaceQuery(null)
- .fragment(null)
- .build();
-
- return UriComponentsBuilder
- .fromUri(URI.create(logoutUrl))
- .queryParam("client_id", clientId)
- .queryParam("logout_uri", baseUrl)
- .encode(StandardCharsets.UTF_8)
- .build()
- .toUriString();
+ protected String determineTargetUrl(
+ HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
+
+ UriComponents baseUrl =
+ UriComponentsBuilder.fromHttpUrl(UrlUtils.buildFullRequestUrl(request))
+ .replacePath(request.getContextPath())
+ .replaceQuery(null)
+ .fragment(null)
+ .build();
+
+ return UriComponentsBuilder.fromUri(URI.create(logoutUrl))
+ .queryParam("client_id", clientId)
+ .queryParam("logout_uri", baseUrl)
+ .encode(StandardCharsets.UTF_8)
+ .build()
+ .toUriString();
}
}
diff --git a/spring-security-aws-cognito-thymeleaf/src/main/java/de/rieckpil/blog/IndexController.java b/spring-security-aws-cognito-thymeleaf/src/main/java/de/rieckpil/blog/IndexController.java
index efed2d96..b8f2ef29 100644
--- a/spring-security-aws-cognito-thymeleaf/src/main/java/de/rieckpil/blog/IndexController.java
+++ b/spring-security-aws-cognito-thymeleaf/src/main/java/de/rieckpil/blog/IndexController.java
@@ -11,7 +11,8 @@ public class IndexController {
@GetMapping
public String getIndexPage(Model model, Authentication authentication) {
if (authentication != null && authentication.isAuthenticated()) {
- if (authentication.getAuthorities().stream().anyMatch(a -> a.getAuthority().equals("ROLE_ADMIN"))) {
+ if (authentication.getAuthorities().stream()
+ .anyMatch(a -> a.getAuthority().equals("ROLE_ADMIN"))) {
model.addAttribute("secretMessage", "Admin message is s3crEt");
} else {
model.addAttribute("secretMessage", "Lorem ipsum dolor sit amet");
diff --git a/spring-security-aws-cognito-thymeleaf/src/main/java/de/rieckpil/blog/WebSecurityConfig.java b/spring-security-aws-cognito-thymeleaf/src/main/java/de/rieckpil/blog/WebSecurityConfig.java
index 566aeeaf..8dd18e55 100644
--- a/spring-security-aws-cognito-thymeleaf/src/main/java/de/rieckpil/blog/WebSecurityConfig.java
+++ b/spring-security-aws-cognito-thymeleaf/src/main/java/de/rieckpil/blog/WebSecurityConfig.java
@@ -1,33 +1,36 @@
package de.rieckpil.blog;
import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
-import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.web.SecurityFilterChain;
@Configuration
-public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
+public class WebSecurityConfig {
private final String clientId;
private final String logoutUrl;
- public WebSecurityConfig(@Value("${spring.security.oauth2.client.registration.cognito.clientId}") String clientId,
- @Value("${cognito.logoutUrl}") String logoutUrl) {
+ public WebSecurityConfig(
+ @Value("${spring.security.oauth2.client.registration.cognito.clientId}") String clientId,
+ @Value("${cognito.logoutUrl}") String logoutUrl) {
this.clientId = clientId;
this.logoutUrl = logoutUrl;
}
- @Override
- protected void configure(HttpSecurity http) throws Exception {
- http
- .csrf()
- .and()
- .authorizeRequests(authorize ->
- authorize.mvcMatchers("/").permitAll()
- .anyRequest().authenticated())
- .oauth2Login()
- .and()
- .logout()
- .logoutSuccessHandler(new CognitoOidcLogoutSuccessHandler(logoutUrl, clientId));
+ @Bean
+ public SecurityFilterChain configure(HttpSecurity http) throws Exception {
+ http.csrf(Customizer.withDefaults())
+ .authorizeHttpRequests(
+ authorize -> authorize.requestMatchers("/").permitAll().anyRequest().authenticated())
+ .oauth2Login(Customizer.withDefaults())
+ .logout(
+ logout ->
+ logout.logoutSuccessHandler(
+ new CognitoOidcLogoutSuccessHandler(logoutUrl, clientId)));
+
+ return http.build();
}
}
diff --git a/spring-security-aws-cognito-thymeleaf/src/test/java/de/rieckpil/blog/IndexControllerTest.java b/spring-security-aws-cognito-thymeleaf/src/test/java/de/rieckpil/blog/IndexControllerTest.java
index de5cea06..dbc36719 100644
--- a/spring-security-aws-cognito-thymeleaf/src/test/java/de/rieckpil/blog/IndexControllerTest.java
+++ b/spring-security-aws-cognito-thymeleaf/src/test/java/de/rieckpil/blog/IndexControllerTest.java
@@ -1,5 +1,10 @@
package de.rieckpil.blog;
+import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.*;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
@@ -8,45 +13,37 @@
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.test.web.servlet.MockMvc;
-import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.*;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
-
@Disabled
@WebMvcTest
class IndexControllerTest {
- @Autowired
- private MockMvc mockMvc;
+ @Autowired private MockMvc mockMvc;
@Test
void anonymousUsersShouldNotGetSecretMessage() throws Exception {
this.mockMvc
- .perform(get("/")
- .with(anonymous()))
- .andExpect(status().isOk())
- .andExpect(model().attributeDoesNotExist("secretMessage"))
- .andExpect(model().attribute("message", "AWS Cognito with Spring Security"));
+ .perform(get("/").with(anonymous()))
+ .andExpect(status().isOk())
+ .andExpect(model().attributeDoesNotExist("secretMessage"))
+ .andExpect(model().attribute("message", "AWS Cognito with Spring Security"));
}
@Test
void authenticatedUsersShouldGetSecretMessage() throws Exception {
this.mockMvc
- .perform(get("/")
- .with(oidcLogin()))
- .andExpect(status().isOk())
- .andExpect(model().attributeExists("secretMessage", "message"))
- .andExpect(model().attribute("secretMessage", Matchers.stringContainsInOrder("Lorem ipsum")));
+ .perform(get("/").with(oidcLogin()))
+ .andExpect(status().isOk())
+ .andExpect(model().attributeExists("secretMessage", "message"))
+ .andExpect(
+ model().attribute("secretMessage", Matchers.stringContainsInOrder("Lorem ipsum")));
}
@Test
void authenticatedAdminUsersShouldGetDetailedSecretMessage() throws Exception {
this.mockMvc
- .perform(get("/")
- .with(oidcLogin().authorities(new SimpleGrantedAuthority("ROLE_ADMIN"))))
- .andExpect(status().isOk())
- .andExpect(model().attributeExists("secretMessage", "message"))
- .andExpect(model().attribute("secretMessage", "Admin message is s3crEt"));
+ .perform(get("/").with(oidcLogin().authorities(new SimpleGrantedAuthority("ROLE_ADMIN"))))
+ .andExpect(status().isOk())
+ .andExpect(model().attributeExists("secretMessage", "message"))
+ .andExpect(model().attribute("secretMessage", "Admin message is s3crEt"));
}
}
diff --git a/spring-test-context-caching-introduction/pom.xml b/spring-test-context-caching-introduction/pom.xml
index 1ae4f638..04a1ba12 100644
--- a/spring-test-context-caching-introduction/pom.xml
+++ b/spring-test-context-caching-introduction/pom.xml
@@ -2,22 +2,19 @@
4.0.0
+
- org.springframework.boot
- spring-boot-starter-parent
- 2.3.0.RELEASE
-
+ de.rieckpil.blog
+ blog-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
- de.rieckpil.blog
+
spring-test-context-caching-introduction
0.0.1-SNAPSHOT
spring-test-context-caching-introduction
Demo project for Spring Boot
-
- 11
-
-
org.springframework.boot
diff --git a/spring-test-context-caching-introduction/src/main/java/de/rieckpil/blog/Application.java b/spring-test-context-caching-introduction/src/main/java/de/rieckpil/blog/Application.java
index bd5e4c56..6511f3c1 100644
--- a/spring-test-context-caching-introduction/src/main/java/de/rieckpil/blog/Application.java
+++ b/spring-test-context-caching-introduction/src/main/java/de/rieckpil/blog/Application.java
@@ -9,5 +9,4 @@ public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
-
}
diff --git a/spring-test-context-caching-introduction/src/main/java/de/rieckpil/blog/CustomInitializer.java b/spring-test-context-caching-introduction/src/main/java/de/rieckpil/blog/CustomInitializer.java
index 70b9aaea..d14c0564 100644
--- a/spring-test-context-caching-introduction/src/main/java/de/rieckpil/blog/CustomInitializer.java
+++ b/spring-test-context-caching-introduction/src/main/java/de/rieckpil/blog/CustomInitializer.java
@@ -3,7 +3,8 @@
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
-public class CustomInitializer implements ApplicationContextInitializer {
+public class CustomInitializer
+ implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
System.out.println("Init stuff");
diff --git a/spring-test-context-caching-introduction/src/test/java/de/rieckpil/blog/AbstractIntegrationTest.java b/spring-test-context-caching-introduction/src/test/java/de/rieckpil/blog/AbstractIntegrationTest.java
index ffcfac19..d0e1d927 100644
--- a/spring-test-context-caching-introduction/src/test/java/de/rieckpil/blog/AbstractIntegrationTest.java
+++ b/spring-test-context-caching-introduction/src/test/java/de/rieckpil/blog/AbstractIntegrationTest.java
@@ -1,12 +1,12 @@
package de.rieckpil.blog;
+import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
+
import org.junit.jupiter.api.BeforeAll;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ContextConfiguration;
-import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
-
@AutoConfigureMockMvc
@ContextConfiguration(initializers = CustomInitializer.class)
@SpringBootTest(webEnvironment = RANDOM_PORT)
@@ -17,4 +17,3 @@ public static void commonSetup() {
// e.g. provide WireMock stubs
}
}
-
diff --git a/spring-test-context-caching-introduction/src/test/java/de/rieckpil/blog/ApplicationTests.java b/spring-test-context-caching-introduction/src/test/java/de/rieckpil/blog/ApplicationTests.java
index 874de1b2..4f1f1cf4 100644
--- a/spring-test-context-caching-introduction/src/test/java/de/rieckpil/blog/ApplicationTests.java
+++ b/spring-test-context-caching-introduction/src/test/java/de/rieckpil/blog/ApplicationTests.java
@@ -7,7 +7,5 @@
class ApplicationTests {
@Test
- void contextLoads() {
- }
-
+ void contextLoads() {}
}
diff --git a/spring-test-context-caching-introduction/src/test/java/de/rieckpil/blog/SecondApplicationTest.java b/spring-test-context-caching-introduction/src/test/java/de/rieckpil/blog/SecondApplicationTest.java
index 8361f48c..8482aa82 100644
--- a/spring-test-context-caching-introduction/src/test/java/de/rieckpil/blog/SecondApplicationTest.java
+++ b/spring-test-context-caching-introduction/src/test/java/de/rieckpil/blog/SecondApplicationTest.java
@@ -1,30 +1,27 @@
package de.rieckpil.blog;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.Mockito.when;
+import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
+
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.test.web.client.TestRestTemplate;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.mockito.Mockito.when;
-import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
-
@SpringBootTest(webEnvironment = RANDOM_PORT)
public class SecondApplicationTest {
- @Autowired
- private TestRestTemplate testRestTemplate;
+ @Autowired private TestRestTemplate testRestTemplate;
- @MockBean
- private PersonService personService;
+ @MockBean private PersonService personService;
@Test
public void testPublicEndpoint() {
when(personService.getPerson()).thenReturn("testPerson");
- String result = this.testRestTemplate
- .getForObject("/", String.class);
+ String result = this.testRestTemplate.getForObject("/", String.class);
assertEquals("testPerson", result);
}
diff --git a/spring-test-context-caching-introduction/src/test/java/de/rieckpil/blog/ThirdApplicationContext.java b/spring-test-context-caching-introduction/src/test/java/de/rieckpil/blog/ThirdApplicationContext.java
index 71dd9c59..93c1953b 100644
--- a/spring-test-context-caching-introduction/src/test/java/de/rieckpil/blog/ThirdApplicationContext.java
+++ b/spring-test-context-caching-introduction/src/test/java/de/rieckpil/blog/ThirdApplicationContext.java
@@ -1,5 +1,9 @@
package de.rieckpil.blog;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.Mockito.when;
+import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
+
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@@ -7,26 +11,19 @@
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.test.context.TestPropertySource;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.mockito.Mockito.when;
-import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
-
@SpringBootTest(webEnvironment = RANDOM_PORT)
@TestPropertySource(properties = "secret_value=foo")
public class ThirdApplicationContext {
- @Autowired
- private TestRestTemplate testRestTemplate;
+ @Autowired private TestRestTemplate testRestTemplate;
- @MockBean
- private PersonService personService;
+ @MockBean private PersonService personService;
@Test
public void testPublicEndpoint() {
when(personService.getPerson()).thenReturn("testPerson");
- String result = this.testRestTemplate
- .getForObject("/", String.class);
+ String result = this.testRestTemplate.getForObject("/", String.class);
assertEquals("testPerson", result);
}
diff --git a/spring-web-client-customizing/pom.xml b/spring-web-client-customizing/pom.xml
index c1a198a1..b93f2e3c 100644
--- a/spring-web-client-customizing/pom.xml
+++ b/spring-web-client-customizing/pom.xml
@@ -2,21 +2,18 @@
4.0.0
+
- org.springframework.boot
- spring-boot-starter-parent
- 2.2.2.RELEASE
-
+ de.rieckpil.blog
+ blog-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
- de.rieckpil.blog
+
spring-web-client-customizing
0.0.1-SNAPSHOT
spring-web-client-customizing
- Demo project for Spring Boot
-
-
- 11
-
+ Customize Spring WebClient
@@ -32,12 +29,6 @@
org.springframework.boot
spring-boot-starter-test
test
-
-
- org.junit.vintage
- junit-vintage-engine
-
-
io.projectreactor
diff --git a/spring-web-client-customizing/src/main/java/de/rieckpil/blog/Application.java b/spring-web-client-customizing/src/main/java/de/rieckpil/blog/Application.java
new file mode 100644
index 00000000..6511f3c1
--- /dev/null
+++ b/spring-web-client-customizing/src/main/java/de/rieckpil/blog/Application.java
@@ -0,0 +1,12 @@
+package de.rieckpil.blog;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+}
diff --git a/spring-web-client-customizing/src/main/java/de/rieckpil/blog/RandomDataController.java b/spring-web-client-customizing/src/main/java/de/rieckpil/blog/RandomDataController.java
index 8288250d..ec9b9683 100644
--- a/spring-web-client-customizing/src/main/java/de/rieckpil/blog/RandomDataController.java
+++ b/spring-web-client-customizing/src/main/java/de/rieckpil/blog/RandomDataController.java
@@ -18,11 +18,6 @@ public RandomDataController(WebClient.Builder webClientBuilder) {
@GetMapping
public JsonNode getRandomData() {
- return webClient
- .get()
- .uri("/todos")
- .retrieve()
- .bodyToMono(JsonNode.class)
- .block();
+ return webClient.get().uri("/todos").retrieve().bodyToMono(JsonNode.class).block();
}
}
diff --git a/spring-web-client-customizing/src/main/java/de/rieckpil/blog/ResponseLoggingCustomizer.java b/spring-web-client-customizing/src/main/java/de/rieckpil/blog/ResponseLoggingCustomizer.java
index 191f10ed..7c8400bc 100644
--- a/spring-web-client-customizing/src/main/java/de/rieckpil/blog/ResponseLoggingCustomizer.java
+++ b/spring-web-client-customizing/src/main/java/de/rieckpil/blog/ResponseLoggingCustomizer.java
@@ -1,5 +1,6 @@
package de.rieckpil.blog;
+import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.web.reactive.function.client.WebClientCustomizer;
@@ -8,8 +9,6 @@
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
-import java.util.List;
-
@Component
public class ResponseLoggingCustomizer implements WebClientCustomizer {
@@ -22,13 +21,17 @@ public void customize(WebClient.Builder webClientBuilder) {
}
private ExchangeFilterFunction logResponse() {
- return ExchangeFilterFunction.ofResponseProcessor(clientResponse -> {
- logger.info("Response: {}", clientResponse.statusCode());
- logger.info("--- Http Headers of Response: ---");
- clientResponse.headers().asHttpHeaders()
- .forEach((name, values) -> values.forEach(value -> logger.info("{}={}", name, value)));
- return Mono.just(clientResponse);
- });
+ return ExchangeFilterFunction.ofResponseProcessor(
+ clientResponse -> {
+ logger.info("Response: {}", clientResponse.statusCode());
+ logger.info("--- Http Headers of Response: ---");
+ clientResponse
+ .headers()
+ .asHttpHeaders()
+ .forEach(
+ (name, values) -> values.forEach(value -> logger.info("{}={}", name, value)));
+ return Mono.just(clientResponse);
+ });
}
private ExchangeFilterFunction logRequest() {
diff --git a/spring-web-client-customizing/src/test/java/de/rieckpil/blog/ApplicationTests.java b/spring-web-client-customizing/src/test/java/de/rieckpil/blog/ApplicationTests.java
new file mode 100644
index 00000000..4f1f1cf4
--- /dev/null
+++ b/spring-web-client-customizing/src/test/java/de/rieckpil/blog/ApplicationTests.java
@@ -0,0 +1,11 @@
+package de.rieckpil.blog;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class ApplicationTests {
+
+ @Test
+ void contextLoads() {}
+}
diff --git a/spring-web-client-demo/pom.xml b/spring-web-client-demo/pom.xml
index 074066ee..c1af5110 100644
--- a/spring-web-client-demo/pom.xml
+++ b/spring-web-client-demo/pom.xml
@@ -4,20 +4,18 @@
4.0.0
- org.springframework.boot
- spring-boot-starter-parent
- 2.4.5
-
+ de.rieckpil.blog
+ blog-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
- de.rieckpil.blog
spring-web-client-demo
0.0.1-SNAPSHOT
spring-web-client-demo
Demo project for Spring Boot
- 11
4.8.0
4.8.0
diff --git a/spring-web-client-demo/src/main/java/de/rieckpil/blog/Application.java b/spring-web-client-demo/src/main/java/de/rieckpil/blog/Application.java
index bd5e4c56..6511f3c1 100644
--- a/spring-web-client-demo/src/main/java/de/rieckpil/blog/Application.java
+++ b/spring-web-client-demo/src/main/java/de/rieckpil/blog/Application.java
@@ -9,5 +9,4 @@ public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
-
}
diff --git a/spring-web-client-demo/src/main/java/de/rieckpil/blog/CustomerController.java b/spring-web-client-demo/src/main/java/de/rieckpil/blog/CustomerController.java
index 2cedd9e4..9101beb3 100644
--- a/spring-web-client-demo/src/main/java/de/rieckpil/blog/CustomerController.java
+++ b/spring-web-client-demo/src/main/java/de/rieckpil/blog/CustomerController.java
@@ -19,8 +19,6 @@ public CustomerController(ObjectMapper objectMapper) {
@GetMapping(path = "/{id}")
public JsonNode getCustomerById(@PathVariable("id") Long id) {
- return objectMapper.createObjectNode()
- .put("name", "duke")
- .put("customerId", id);
+ return objectMapper.createObjectNode().put("name", "duke").put("customerId", id);
}
}
diff --git a/spring-web-client-demo/src/main/java/de/rieckpil/blog/SimpleApiClient.java b/spring-web-client-demo/src/main/java/de/rieckpil/blog/SimpleApiClient.java
index 63090166..43d3fb18 100644
--- a/spring-web-client-demo/src/main/java/de/rieckpil/blog/SimpleApiClient.java
+++ b/spring-web-client-demo/src/main/java/de/rieckpil/blog/SimpleApiClient.java
@@ -2,15 +2,14 @@
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
-import org.springframework.http.HttpStatus;
+import java.time.Duration;
+import org.springframework.http.HttpStatusCode;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import reactor.util.retry.Retry;
-import java.time.Duration;
-
@Service
public class SimpleApiClient {
@@ -24,36 +23,47 @@ public SimpleApiClient(WebClient defaultWebClient, ObjectMapper objectMapper) {
}
public JsonNode getTodoFromAPI() {
- return this.defaultWebClient.get().uri("/todos/1")
- .retrieve()
- .onStatus(HttpStatus::is4xxClientError, response -> {
- System.out.println("4xx error");
- return Mono.error(new RuntimeException("4xx"));
- })
- .onStatus(HttpStatus::is5xxServerError, response -> {
- System.out.println("5xx error");
- return Mono.error(new RuntimeException("5xx"));
- })
- .bodyToMono(JsonNode.class)
- .block();
+ return this.defaultWebClient
+ .get()
+ .uri("/todos/1")
+ .retrieve()
+ .onStatus(
+ HttpStatusCode::is4xxClientError,
+ response -> {
+ System.out.println("4xx error");
+ return Mono.error(new RuntimeException("4xx"));
+ })
+ .onStatus(
+ HttpStatusCode::is5xxServerError,
+ response -> {
+ System.out.println("5xx error");
+ return Mono.error(new RuntimeException("5xx"));
+ })
+ .bodyToMono(JsonNode.class)
+ .block();
}
public JsonNode getRetryTodoFromAPI() {
- return this.defaultWebClient.get().uri("/todos/1")
- .retrieve()
- .bodyToMono(JsonNode.class)
- .retryWhen(Retry.max(5))
- .timeout(Duration.ofSeconds(2), Mono.just(objectMapper.createObjectNode().put("message", "fallback")))
- .block();
+ return this.defaultWebClient
+ .get()
+ .uri("/todos/1")
+ .retrieve()
+ .bodyToMono(JsonNode.class)
+ .retryWhen(Retry.max(5))
+ .timeout(
+ Duration.ofSeconds(2),
+ Mono.just(objectMapper.createObjectNode().put("message", "fallback")))
+ .block();
}
public JsonNode postToTodoAPI() {
return this.defaultWebClient
- .post()
- .uri("/todos")
- .body(BodyInserters.fromValue("{ \"title\": \"foo\", \"body\": \"bar\", \"userId\": \"1\"}"))
- .retrieve()
- .bodyToMono(JsonNode.class)
- .block();
+ .post()
+ .uri("/todos")
+ .body(
+ BodyInserters.fromValue("{ \"title\": \"foo\", \"body\": \"bar\", \"userId\": \"1\"}"))
+ .retrieve()
+ .bodyToMono(JsonNode.class)
+ .block();
}
}
diff --git a/spring-web-client-demo/src/main/java/de/rieckpil/blog/SimpleWebClientConfiguration.java b/spring-web-client-demo/src/main/java/de/rieckpil/blog/SimpleWebClientConfiguration.java
index 0c3e741f..e81e8cd7 100644
--- a/spring-web-client-demo/src/main/java/de/rieckpil/blog/SimpleWebClientConfiguration.java
+++ b/spring-web-client-demo/src/main/java/de/rieckpil/blog/SimpleWebClientConfiguration.java
@@ -3,6 +3,9 @@
import io.netty.channel.ChannelOption;
import io.netty.handler.timeout.ReadTimeoutHandler;
import io.netty.handler.timeout.WriteTimeoutHandler;
+import java.util.List;
+import java.util.UUID;
+import java.util.function.Function;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
@@ -16,11 +19,6 @@
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import reactor.netty.http.client.HttpClient;
-import reactor.netty.tcp.TcpClient;
-
-import java.util.List;
-import java.util.UUID;
-import java.util.function.Function;
@Component
public class SimpleWebClientConfiguration {
@@ -31,49 +29,55 @@ public class SimpleWebClientConfiguration {
// @Bean
public WebClient webClientFromBuilder(WebClient.Builder webClientBuilder) {
- HttpClient httpClient = HttpClient.create()
- .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 2_000) // millis
- .doOnConnected(connection ->
- connection
- .addHandlerLast(new ReadTimeoutHandler(2)) // seconds
- .addHandlerLast(new WriteTimeoutHandler(2))); // seconds
+ HttpClient httpClient =
+ HttpClient.create()
+ .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 2_000) // millis
+ .doOnConnected(
+ connection ->
+ connection
+ .addHandlerLast(new ReadTimeoutHandler(2)) // seconds
+ .addHandlerLast(new WriteTimeoutHandler(2))); // seconds
return webClientBuilder
- .baseUrl(BASE_URL)
- .clientConnector(new ReactorClientHttpConnector(httpClient))
- .defaultCookie("cookieKey", "cookieValue", "teapot", "amsterdam")
- .defaultCookie("secretToken", UUID.randomUUID().toString())
- .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
- .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
- .defaultHeader(HttpHeaders.USER_AGENT, "I'm a teapot")
- .filter(ExchangeFilterFunctions.basicAuthentication("rieckpil", UUID.randomUUID().toString()))
- .filter(logRequest())
- .filter(logResponse())
- .build();
+ .baseUrl(BASE_URL)
+ .clientConnector(new ReactorClientHttpConnector(httpClient))
+ .defaultCookie("cookieKey", "cookieValue", "teapot", "amsterdam")
+ .defaultCookie("secretToken", UUID.randomUUID().toString())
+ .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
+ .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
+ .defaultHeader(HttpHeaders.USER_AGENT, "I'm a teapot")
+ .filter(
+ ExchangeFilterFunctions.basicAuthentication("rieckpil", UUID.randomUUID().toString()))
+ .filter(logRequest())
+ .filter(logResponse())
+ .build();
}
@Bean
public WebClient webClientFromScratch() {
- HttpClient httpClient = HttpClient.create()
- .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 2_000) // millis
- .doOnConnected(connection ->
- connection
- .addHandlerLast(new ReadTimeoutHandler(2)) // seconds
- .addHandlerLast(new WriteTimeoutHandler(2))); // seconds
+ HttpClient httpClient =
+ HttpClient.create()
+ .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 2_000) // millis
+ .doOnConnected(
+ connection ->
+ connection
+ .addHandlerLast(new ReadTimeoutHandler(2)) // seconds
+ .addHandlerLast(new WriteTimeoutHandler(2))); // seconds
return WebClient.builder()
- .baseUrl(BASE_URL)
- .clientConnector(new ReactorClientHttpConnector(httpClient))
- .defaultCookie("cookieKey", "cookieValue", "teapot", "amsterdam")
- .defaultCookie("secretToken", UUID.randomUUID().toString())
- .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
- .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
- .defaultHeader(HttpHeaders.USER_AGENT, "I'm a teapot")
- .filter(ExchangeFilterFunctions.basicAuthentication("rieckpil", UUID.randomUUID().toString()))
- .filter(logRequest())
- .filter(logResponse())
- .build();
+ .baseUrl(BASE_URL)
+ .clientConnector(new ReactorClientHttpConnector(httpClient))
+ .defaultCookie("cookieKey", "cookieValue", "teapot", "amsterdam")
+ .defaultCookie("secretToken", UUID.randomUUID().toString())
+ .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
+ .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
+ .defaultHeader(HttpHeaders.USER_AGENT, "I'm a teapot")
+ .filter(
+ ExchangeFilterFunctions.basicAuthentication("rieckpil", UUID.randomUUID().toString()))
+ .filter(logRequest())
+ .filter(logResponse())
+ .build();
}
private ExchangeFilterFunction logRequest() {
@@ -88,18 +92,27 @@ private ExchangeFilterFunction logRequest() {
}
private ExchangeFilterFunction authHeader(Function token) {
- return (request, next) -> next.exchange(ClientRequest.from(request).headers((headers) -> {
- headers.setBearerAuth(token.apply("xyz"));
- }).build());
+ return (request, next) ->
+ next.exchange(
+ ClientRequest.from(request)
+ .headers(
+ (headers) -> {
+ headers.setBearerAuth(token.apply("xyz"));
+ })
+ .build());
}
private ExchangeFilterFunction logResponse() {
- return ExchangeFilterFunction.ofResponseProcessor(clientResponse -> {
- logger.info("Response: {}", clientResponse.statusCode());
- clientResponse.headers().asHttpHeaders()
- .forEach((name, values) -> values.forEach(value -> logger.info("{}={}", name, value)));
- return Mono.just(clientResponse);
- });
+ return ExchangeFilterFunction.ofResponseProcessor(
+ clientResponse -> {
+ logger.info("Response: {}", clientResponse.statusCode());
+ clientResponse
+ .headers()
+ .asHttpHeaders()
+ .forEach(
+ (name, values) -> values.forEach(value -> logger.info("{}={}", name, value)));
+ return Mono.just(clientResponse);
+ });
}
private void logHeader(String name, List values) {
diff --git a/spring-web-client-demo/src/test/java/de/rieckpil/blog/ApplicationTests.java b/spring-web-client-demo/src/test/java/de/rieckpil/blog/ApplicationTests.java
index 50e12cfb..4f1f1cf4 100644
--- a/spring-web-client-demo/src/test/java/de/rieckpil/blog/ApplicationTests.java
+++ b/spring-web-client-demo/src/test/java/de/rieckpil/blog/ApplicationTests.java
@@ -7,6 +7,5 @@
class ApplicationTests {
@Test
- void contextLoads() {
- }
+ void contextLoads() {}
}
diff --git a/spring-web-client-demo/src/test/java/de/rieckpil/blog/CustomerControllerIT.java b/spring-web-client-demo/src/test/java/de/rieckpil/blog/CustomerControllerIT.java
index 0b18062d..0c1cc164 100644
--- a/spring-web-client-demo/src/test/java/de/rieckpil/blog/CustomerControllerIT.java
+++ b/spring-web-client-demo/src/test/java/de/rieckpil/blog/CustomerControllerIT.java
@@ -9,17 +9,23 @@
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class CustomerControllerIT {
- @Autowired
- private WebTestClient webTestClient;
+ @Autowired private WebTestClient webTestClient;
@Test
void shouldReturnCustomerOne() {
- this.webTestClient.get().uri("/api/customers/1") // the base URL is already configured for us
- .accept(MediaType.APPLICATION_JSON)
- .exchange().expectStatus().isOk()
- .expectHeader().contentType(MediaType.APPLICATION_JSON)
- .expectBody()
- .jsonPath("$.customerId").isNotEmpty()
- .jsonPath("$.name").isNotEmpty();
+ this.webTestClient
+ .get()
+ .uri("/api/customers/1") // the base URL is already configured for us
+ .accept(MediaType.APPLICATION_JSON)
+ .exchange()
+ .expectStatus()
+ .isOk()
+ .expectHeader()
+ .contentType(MediaType.APPLICATION_JSON)
+ .expectBody()
+ .jsonPath("$.customerId")
+ .isNotEmpty()
+ .jsonPath("$.name")
+ .isNotEmpty();
}
}
diff --git a/spring-web-client-demo/src/test/java/de/rieckpil/blog/SimpleApiClientTest.java b/spring-web-client-demo/src/test/java/de/rieckpil/blog/SimpleApiClientTest.java
index 03d96396..174181ed 100644
--- a/spring-web-client-demo/src/test/java/de/rieckpil/blog/SimpleApiClientTest.java
+++ b/spring-web-client-demo/src/test/java/de/rieckpil/blog/SimpleApiClientTest.java
@@ -1,7 +1,10 @@
package de.rieckpil.blog;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
+import java.io.IOException;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import okhttp3.mockwebserver.RecordedRequest;
@@ -9,10 +12,6 @@
import org.junit.jupiter.api.Test;
import org.springframework.web.reactive.function.client.WebClient;
-import java.io.IOException;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
class SimpleApiClientTest {
private MockWebServer mockWebServer;
@@ -22,16 +21,18 @@ class SimpleApiClientTest {
void setup() throws IOException {
this.mockWebServer = new MockWebServer();
this.mockWebServer.start();
- this.cut = new SimpleApiClient(WebClient
- .builder()
- .baseUrl(mockWebServer.url("http://github.com/").toString()).build(), new ObjectMapper());
+ this.cut =
+ new SimpleApiClient(
+ WebClient.builder().baseUrl(mockWebServer.url("http://github.com/").toString()).build(),
+ new ObjectMapper());
}
@Test
void testGetUserById() throws InterruptedException {
- MockResponse mockResponse = new MockResponse()
- .addHeader("Content-Type", "application/json; charset=utf-8")
- .setBody("{\"id\": 1, \"name\":\"write good tests\"}");
+ MockResponse mockResponse =
+ new MockResponse()
+ .addHeader("Content-Type", "application/json; charset=utf-8")
+ .setBody("{\"id\": 1, \"name\":\"write good tests\"}");
mockWebServer.enqueue(mockResponse);
diff --git a/spring-web-client-exchange-retrieve/pom.xml b/spring-web-client-exchange-retrieve/pom.xml
index 084ab044..4614acc4 100644
--- a/spring-web-client-exchange-retrieve/pom.xml
+++ b/spring-web-client-exchange-retrieve/pom.xml
@@ -4,21 +4,19 @@
4.0.0
- org.springframework.boot
- spring-boot-starter-parent
- 2.4.0
-
+ de.rieckpil.blog
+ blog-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
- de.rieckpil.blog
spring-web-client-exchange-retrieve
0.0.1-SNAPSHOT
spring-web-client-exchange-retrieve
Spring WebClient exchange vs. retrieve
- 11
- 2.27.1
+ 2.27.2
@@ -38,7 +36,7 @@
com.github.tomakehurst
- wiremock-jre8
+ wiremock-standalone
${wiremock.version}
test
diff --git a/spring-web-client-exchange-retrieve/src/main/java/de/rieckpil/blog/Application.java b/spring-web-client-exchange-retrieve/src/main/java/de/rieckpil/blog/Application.java
index f1eb68af..d245e7b1 100644
--- a/spring-web-client-exchange-retrieve/src/main/java/de/rieckpil/blog/Application.java
+++ b/spring-web-client-exchange-retrieve/src/main/java/de/rieckpil/blog/Application.java
@@ -12,7 +12,10 @@ public class Application implements CommandLineRunner {
private final RetrieveWebClient retrieveWebClient;
private final ObjectMapper objectMapper;
- public Application(ExchangeWebClient exchangeWebClient, RetrieveWebClient retrieveWebClient, ObjectMapper objectMapper) {
+ public Application(
+ ExchangeWebClient exchangeWebClient,
+ RetrieveWebClient retrieveWebClient,
+ ObjectMapper objectMapper) {
this.exchangeWebClient = exchangeWebClient;
this.retrieveWebClient = retrieveWebClient;
this.objectMapper = objectMapper;
@@ -27,12 +30,12 @@ public void run(String... args) throws Exception {
System.out.println(retrieveWebClient.getTodos());
System.out.println(exchangeWebClient.getTodos());
- System.out.println(exchangeWebClient.createTodo(objectMapper
- .createObjectNode()
- .put("task", "learn Spring Boot")));
+ System.out.println(
+ exchangeWebClient.createTodo(
+ objectMapper.createObjectNode().put("task", "learn Spring Boot")));
- System.out.println(retrieveWebClient.createTodo(objectMapper
- .createObjectNode()
- .put("task", "learn Spring Boot")));
+ System.out.println(
+ retrieveWebClient.createTodo(
+ objectMapper.createObjectNode().put("task", "learn Spring Boot")));
}
}
diff --git a/spring-web-client-exchange-retrieve/src/main/java/de/rieckpil/blog/ExchangeWebClient.java b/spring-web-client-exchange-retrieve/src/main/java/de/rieckpil/blog/ExchangeWebClient.java
index e3933431..5da83cc0 100644
--- a/spring-web-client-exchange-retrieve/src/main/java/de/rieckpil/blog/ExchangeWebClient.java
+++ b/spring-web-client-exchange-retrieve/src/main/java/de/rieckpil/blog/ExchangeWebClient.java
@@ -17,31 +17,37 @@ public ExchangeWebClient(WebClient jsonPlaceholderWebClient) {
}
public JsonNode getTodo(String id) {
- return this.jsonPlaceholderWebClient.get()
- .uri("/todos/{id}", id)
- .exchange()
- .flatMap(clientResponse -> clientResponse.bodyToMono(JsonNode.class))
- .block();
+ return this.jsonPlaceholderWebClient
+ .get()
+ .uri("/todos/{id}", id)
+ .exchange()
+ .flatMap(clientResponse -> clientResponse.bodyToMono(JsonNode.class))
+ .block();
}
public JsonNode getTodos() {
- return this.jsonPlaceholderWebClient.get()
- .uri("/todos")
- .exchange()
- .flatMap(clientResponse -> clientResponse.bodyToMono(JsonNode.class))
- .block();
+ return this.jsonPlaceholderWebClient
+ .get()
+ .uri("/todos")
+ .exchange()
+ .flatMap(clientResponse -> clientResponse.bodyToMono(JsonNode.class))
+ .block();
}
public boolean createTodo(JsonNode payload) {
- ClientResponse response = this.jsonPlaceholderWebClient
- .post()
- .uri("/todos")
- .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
- .bodyValue(payload)
- .exchange()
- .doOnSuccess(clientResponse ->
- System.out.println("Location header: " + clientResponse.headers().header(HttpHeaders.LOCATION)))
- .block();
+ ClientResponse response =
+ this.jsonPlaceholderWebClient
+ .post()
+ .uri("/todos")
+ .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
+ .bodyValue(payload)
+ .exchange()
+ .doOnSuccess(
+ clientResponse ->
+ System.out.println(
+ "Location header: "
+ + clientResponse.headers().header(HttpHeaders.LOCATION)))
+ .block();
if (response.statusCode().value() == 201) {
return !response.headers().header(HttpHeaders.LOCATION).isEmpty();
@@ -49,5 +55,4 @@ public boolean createTodo(JsonNode payload) {
return false;
}
}
-
}
diff --git a/spring-web-client-exchange-retrieve/src/main/java/de/rieckpil/blog/RetrieveWebClient.java b/spring-web-client-exchange-retrieve/src/main/java/de/rieckpil/blog/RetrieveWebClient.java
index 811cd08c..d0935572 100644
--- a/spring-web-client-exchange-retrieve/src/main/java/de/rieckpil/blog/RetrieveWebClient.java
+++ b/spring-web-client-exchange-retrieve/src/main/java/de/rieckpil/blog/RetrieveWebClient.java
@@ -2,7 +2,7 @@
import com.fasterxml.jackson.databind.JsonNode;
import org.springframework.http.HttpHeaders;
-import org.springframework.http.HttpStatus;
+import org.springframework.http.HttpStatusCode;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
@@ -19,32 +19,41 @@ public RetrieveWebClient(WebClient jsonPlaceholderWebClient) {
}
public JsonNode getTodo(String id) {
- return this.jsonPlaceholderWebClient.get()
- .uri("/todos/{id}", id)
- .retrieve()
- .onStatus(HttpStatus::is4xxClientError, response -> response.rawStatusCode() == 418 ? Mono.empty() : Mono.error(new RuntimeException("Error")))
- .onStatus(HttpStatus::is5xxServerError, response -> Mono.error(new RuntimeException("Error")))
- .bodyToMono(JsonNode.class)
- .block();
+ return this.jsonPlaceholderWebClient
+ .get()
+ .uri("/todos/{id}", id)
+ .retrieve()
+ .onStatus(
+ HttpStatusCode::is4xxClientError,
+ response ->
+ response.statusCode().value() == 418
+ ? Mono.empty()
+ : Mono.error(new RuntimeException("Error")))
+ .onStatus(
+ HttpStatusCode::is5xxServerError, response -> Mono.error(new RuntimeException("Error")))
+ .bodyToMono(JsonNode.class)
+ .block();
}
public JsonNode getTodos() {
- return this.jsonPlaceholderWebClient.get()
- .uri("/todos")
- .retrieve()
- .bodyToMono(JsonNode.class)
- .block();
+ return this.jsonPlaceholderWebClient
+ .get()
+ .uri("/todos")
+ .retrieve()
+ .bodyToMono(JsonNode.class)
+ .block();
}
public boolean createTodo(JsonNode payload) {
- ResponseEntity response = this.jsonPlaceholderWebClient
- .post()
- .uri("/todos")
- .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
- .bodyValue(payload)
- .retrieve()
- .toEntity(JsonNode.class)
- .block();
+ ResponseEntity response =
+ this.jsonPlaceholderWebClient
+ .post()
+ .uri("/todos")
+ .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
+ .bodyValue(payload)
+ .retrieve()
+ .toEntity(JsonNode.class)
+ .block();
response.getHeaders().forEach((key, value) -> System.out.println(key + ":" + value));
diff --git a/spring-web-client-exchange-retrieve/src/main/java/de/rieckpil/blog/WebClientConfig.java b/spring-web-client-exchange-retrieve/src/main/java/de/rieckpil/blog/WebClientConfig.java
index 11a6a5a0..aa67f3cb 100644
--- a/spring-web-client-exchange-retrieve/src/main/java/de/rieckpil/blog/WebClientConfig.java
+++ b/spring-web-client-exchange-retrieve/src/main/java/de/rieckpil/blog/WebClientConfig.java
@@ -1,5 +1,7 @@
package de.rieckpil.blog;
+import static io.netty.channel.ChannelOption.CONNECT_TIMEOUT_MILLIS;
+
import io.netty.handler.timeout.ReadTimeoutHandler;
import io.netty.handler.timeout.WriteTimeoutHandler;
import org.springframework.beans.factory.annotation.Value;
@@ -10,8 +12,6 @@
import reactor.netty.http.client.HttpClient;
import reactor.netty.tcp.TcpClient;
-import static io.netty.channel.ChannelOption.CONNECT_TIMEOUT_MILLIS;
-
@Configuration
public class WebClientConfig {
@@ -19,19 +19,20 @@ public class WebClientConfig {
@Bean
public WebClient jsonPlaceholderWebClient(
- @Value("${todo_url}") String todoBaseUrl,
- WebClient.Builder webClientBuilder) {
+ @Value("${todo_url}") String todoBaseUrl, WebClient.Builder webClientBuilder) {
- TcpClient tcpClient = TcpClient.create()
- .option(CONNECT_TIMEOUT_MILLIS, TIMEOUT_IN_SECONDS * 1000)
- .doOnConnected(connection ->
- connection
- .addHandlerLast(new ReadTimeoutHandler(TIMEOUT_IN_SECONDS))
- .addHandlerLast(new WriteTimeoutHandler(TIMEOUT_IN_SECONDS)));
+ TcpClient tcpClient =
+ TcpClient.create()
+ .option(CONNECT_TIMEOUT_MILLIS, TIMEOUT_IN_SECONDS * 1000)
+ .doOnConnected(
+ connection ->
+ connection
+ .addHandlerLast(new ReadTimeoutHandler(TIMEOUT_IN_SECONDS))
+ .addHandlerLast(new WriteTimeoutHandler(TIMEOUT_IN_SECONDS)));
return webClientBuilder
- .clientConnector(new ReactorClientHttpConnector(HttpClient.from(tcpClient)))
- .baseUrl(todoBaseUrl)
- .build();
+ .clientConnector(new ReactorClientHttpConnector(HttpClient.from(tcpClient)))
+ .baseUrl(todoBaseUrl)
+ .build();
}
}
diff --git a/spring-web-client-exchange-retrieve/src/test/java/de/rieckpil/blog/ApplicationTests.java b/spring-web-client-exchange-retrieve/src/test/java/de/rieckpil/blog/ApplicationTests.java
index 8471832e..fbfbd938 100644
--- a/spring-web-client-exchange-retrieve/src/test/java/de/rieckpil/blog/ApplicationTests.java
+++ b/spring-web-client-exchange-retrieve/src/test/java/de/rieckpil/blog/ApplicationTests.java
@@ -9,7 +9,5 @@
class ApplicationTests {
@Test
- void contextLoads() {
- }
-
+ void contextLoads() {}
}
diff --git a/spring-web-client-exchange-retrieve/src/test/java/de/rieckpil/blog/WireMockInitializer.java b/spring-web-client-exchange-retrieve/src/test/java/de/rieckpil/blog/WireMockInitializer.java
index 0439b350..fc160aa2 100644
--- a/spring-web-client-exchange-retrieve/src/test/java/de/rieckpil/blog/WireMockInitializer.java
+++ b/spring-web-client-exchange-retrieve/src/test/java/de/rieckpil/blog/WireMockInitializer.java
@@ -1,5 +1,7 @@
package de.rieckpil.blog;
+import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
+
import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.client.WireMock;
import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
@@ -9,41 +11,43 @@
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.http.MediaType;
-import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
-
-public class WireMockInitializer implements ApplicationContextInitializer {
+public class WireMockInitializer
+ implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
WireMockServer wireMockServer = new WireMockServer(new WireMockConfiguration().dynamicPort());
wireMockServer.start();
- configurableApplicationContext.getBeanFactory().registerSingleton("wireMockServer", wireMockServer);
+ configurableApplicationContext
+ .getBeanFactory()
+ .registerSingleton("wireMockServer", wireMockServer);
- configurableApplicationContext.addApplicationListener(applicationEvent -> {
- if (applicationEvent instanceof ContextClosedEvent) {
- wireMockServer.stop();
- }
- });
+ configurableApplicationContext.addApplicationListener(
+ applicationEvent -> {
+ if (applicationEvent instanceof ContextClosedEvent) {
+ wireMockServer.stop();
+ }
+ });
- TestPropertyValues
- .of("todo_url:http://localhost:" + wireMockServer.port() + "/")
- .applyTo(configurableApplicationContext);
+ TestPropertyValues.of("todo_url:http://localhost:" + wireMockServer.port() + "/")
+ .applyTo(configurableApplicationContext);
wireMockServer.stubFor(
- WireMock.get("/todos")
- .willReturn(aResponse()
- .withHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE)
- .withBody("[{\"userId\": 1,\"id\": 1,\"title\": \"Learn Spring Boot 3.0\", \"completed\": false}," +
- "{\"userId\": 1,\"id\": 2,\"title\": \"Learn WireMock\", \"completed\": true}]"))
- );
+ WireMock.get("/todos")
+ .willReturn(
+ aResponse()
+ .withHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE)
+ .withBody(
+ "[{\"userId\": 1,\"id\": 1,\"title\": \"Learn Spring Boot 3.0\", \"completed\": false},"
+ + "{\"userId\": 1,\"id\": 2,\"title\": \"Learn WireMock\", \"completed\": true}]")));
wireMockServer.stubFor(
- WireMock.post("/todos")
- .willReturn(aResponse()
- .withStatus(201)
- .withHeader("Location", "http://localhost/" + wireMockServer.port() + "/todos42"))
- );
-
+ WireMock.post("/todos")
+ .willReturn(
+ aResponse()
+ .withStatus(201)
+ .withHeader(
+ "Location", "http://localhost/" + wireMockServer.port() + "/todos42")));
}
}
diff --git a/spring-web-client-expose-metrics/README.md b/spring-web-client-expose-metrics/README.md
index 4860b056..f1932720 100644
--- a/spring-web-client-expose-metrics/README.md
+++ b/spring-web-client-expose-metrics/README.md
@@ -1,8 +1,8 @@
-# Codebase for the blog post [#HOWTO: Expose Metrics of Spring WebClient using Spring Boot Actuator](https://rieckpil.de/expose-metrics-of-spring-webclient-using-spring-boot-actuator)
+# Codebase for the blog post [Expose Metrics of Spring WebClient using Spring Boot Actuator](https://rieckpil.de/expose-metrics-of-spring-webclient-using-spring-boot-actuator)
Steps to run this project:
1. Clone this Git repository
2. Navigate to the folder `spring-web-client-expose-metrics`
3. Run the application with `mvn spring-boot:run`
-4. Access http://localhost:8080/actuator/metrics/http.client.requests in your browser
\ No newline at end of file
+4. Access http://localhost:8080/actuator/metrics/http.client.requests in your browser
diff --git a/spring-web-client-expose-metrics/pom.xml b/spring-web-client-expose-metrics/pom.xml
index 7d981906..47848005 100644
--- a/spring-web-client-expose-metrics/pom.xml
+++ b/spring-web-client-expose-metrics/pom.xml
@@ -1,62 +1,53 @@
- 4.0.0
-
- org.springframework.boot
- spring-boot-starter-parent
- 2.2.2.RELEASE
-
-
+ 4.0.0
+
+
de.rieckpil.blog
- spring-web-client-expose-metrics
+ blog-parent
0.0.1-SNAPSHOT
- spring-web-client-expose-metrics
- Spring WebClient Expose Metrics
+ ../pom.xml
+
-
- 11
-
+ spring-web-client-expose-metrics
+ 0.0.1-SNAPSHOT
+ spring-web-client-expose-metrics
+ Spring WebClient Expose Metrics
-
-
- org.springframework.boot
- spring-boot-starter-actuator
-
-
- org.springframework.boot
- spring-boot-starter-web
-
-
- org.springframework.boot
- spring-boot-starter-webflux
-
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-webflux
+
-
- org.springframework.boot
- spring-boot-starter-test
- test
-
-
- org.junit.vintage
- junit-vintage-engine
-
-
-
-
- io.projectreactor
- reactor-test
- test
-
-
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ io.projectreactor
+ reactor-test
+ test
+
+
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
-
-
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
diff --git a/spring-web-client-expose-metrics/src/main/java/de/rieckpil/blog/RandomQuoteClient.java b/spring-web-client-expose-metrics/src/main/java/de/rieckpil/blog/RandomQuoteClient.java
index 5c5ed75c..dba6bd04 100644
--- a/spring-web-client-expose-metrics/src/main/java/de/rieckpil/blog/RandomQuoteClient.java
+++ b/spring-web-client-expose-metrics/src/main/java/de/rieckpil/blog/RandomQuoteClient.java
@@ -15,10 +15,10 @@ public RandomQuoteClient(WebClient webClient) {
public JsonNode fetchRandomQuotes() {
return webClient
- .get()
- .uri("https://quotes.rest/qod")
- .retrieve()
- .bodyToMono(JsonNode.class)
- .block();
+ .get()
+ .uri("https://quotes.rest/qod")
+ .retrieve()
+ .bodyToMono(JsonNode.class)
+ .block();
}
}
diff --git a/spring-web-client-expose-metrics/src/main/java/de/rieckpil/blog/RandomUserClient.java b/spring-web-client-expose-metrics/src/main/java/de/rieckpil/blog/RandomUserClient.java
index 164306bc..2d1ad35d 100644
--- a/spring-web-client-expose-metrics/src/main/java/de/rieckpil/blog/RandomUserClient.java
+++ b/spring-web-client-expose-metrics/src/main/java/de/rieckpil/blog/RandomUserClient.java
@@ -15,10 +15,10 @@ public RandomUserClient(WebClient webClient) {
public JsonNode getRandomUserById(int id) {
return webClient
- .get()
- .uri("https://jsonplaceholder.typicode.com/todos/%7Bid%7D", id)
- .retrieve()
- .bodyToMono(JsonNode.class)
- .block();
+ .get()
+ .uri("https://jsonplaceholder.typicode.com/todos/%7Bid%7D", id)
+ .retrieve()
+ .bodyToMono(JsonNode.class)
+ .block();
}
}
diff --git a/spring-web-client-expose-metrics/src/main/java/de/rieckpil/blog/WebClientConfiguration.java b/spring-web-client-expose-metrics/src/main/java/de/rieckpil/blog/WebClientConfiguration.java
index 8bf35022..82028648 100644
--- a/spring-web-client-expose-metrics/src/main/java/de/rieckpil/blog/WebClientConfiguration.java
+++ b/spring-web-client-expose-metrics/src/main/java/de/rieckpil/blog/WebClientConfiguration.java
@@ -9,22 +9,24 @@
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.netty.http.client.HttpClient;
-import reactor.netty.tcp.TcpClient;
@Configuration
public class WebClientConfiguration {
@Bean
public WebClient webClient(WebClient.Builder webClientBuilder) {
- TcpClient tcpClient = TcpClient.create()
- .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 2_000)
- .doOnConnected(connection ->
- connection.addHandlerLast(new ReadTimeoutHandler(2))
- .addHandlerLast(new WriteTimeoutHandler(2)));
+ HttpClient httpClient =
+ HttpClient.create()
+ .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 4_000)
+ .doOnConnected(
+ connection ->
+ connection
+ .addHandlerLast(new ReadTimeoutHandler(4))
+ .addHandlerLast(new WriteTimeoutHandler(4)));
return webClientBuilder
- .defaultHeader(HttpHeaders.USER_AGENT, "SAMPLE_APP")
- .clientConnector(new ReactorClientHttpConnector(HttpClient.from(tcpClient)))
- .build();
+ .defaultHeader(HttpHeaders.USER_AGENT, "SAMPLE_APP")
+ .clientConnector(new ReactorClientHttpConnector(httpClient))
+ .build();
}
}
diff --git a/spring-web-client-oauth2-reactive-stack/pom.xml b/spring-web-client-oauth2-reactive-stack/pom.xml
index 5ec79490..0663bece 100644
--- a/spring-web-client-oauth2-reactive-stack/pom.xml
+++ b/spring-web-client-oauth2-reactive-stack/pom.xml
@@ -2,22 +2,18 @@
4.0.0
-
- org.springframework.boot
- spring-boot-starter-parent
- 2.2.2.RELEASE
-
-
+
de.rieckpil.blog
+ blog-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
+
+
spring-web-client-oauth2-reactive-stack
0.0.1-SNAPSHOT
spring-web-client-oauth2-reactive-stack
-
- 11
-
-
org.springframework.boot
@@ -40,12 +36,6 @@
org.springframework.boot
spring-boot-starter-test
test
-
-
- org.junit.vintage
- junit-vintage-engine
-
-
io.projectreactor
diff --git a/spring-web-client-oauth2-reactive-stack/src/main/java/de/rieckpil/blog/GitHubController.java b/spring-web-client-oauth2-reactive-stack/src/main/java/de/rieckpil/blog/GitHubController.java
index f2c1ad65..93935d8c 100644
--- a/spring-web-client-oauth2-reactive-stack/src/main/java/de/rieckpil/blog/GitHubController.java
+++ b/spring-web-client-oauth2-reactive-stack/src/main/java/de/rieckpil/blog/GitHubController.java
@@ -1,6 +1,9 @@
package de.rieckpil.blog;
+import static org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction.oauth2AuthorizedClient;
+
import com.fasterxml.jackson.databind.JsonNode;
+import java.util.List;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
@@ -13,48 +16,40 @@
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;
-import java.util.List;
-
-import static org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction.oauth2AuthorizedClient;
-
@Controller
@RequestMapping("/")
public class GitHubController {
- private static final String GITHUB_API_URL = "https://api.github.com/";
-
- private WebClient webClient;
-
- public GitHubController(WebClient webClient) {
- this.webClient = webClient;
- }
-
- @GetMapping
- public String index(@RegisteredOAuth2AuthorizedClient OAuth2AuthorizedClient authorizedClient,
- @AuthenticationPrincipal OAuth2User oauth2User,
- Model model) {
-
- model.addAttribute("repositories", fetchAllRepositories(authorizedClient));
- model.addAttribute("username", oauth2User.getAttributes().get("login"));
-
- return "index";
- }
-
- private Flux fetchAllRepositories(OAuth2AuthorizedClient authorizedClient) {
- return this.webClient
- .get()
- .uri(GITHUB_API_URL, uriBuilder ->
- uriBuilder
- .path("/user/repos")
- .queryParam("per_page", 100)
- .build()
- )
- .attributes(oauth2AuthorizedClient(authorizedClient))
- .retrieve()
- .bodyToMono(new ParameterizedTypeReference>() {
- })
- .flatMapMany(Flux::fromIterable)
- .map(jsonNode -> jsonNode.get("full_name").asText());
- }
-
+ private static final String GITHUB_API_URL = "https://api.github.com/";
+
+ private WebClient webClient;
+
+ public GitHubController(WebClient webClient) {
+ this.webClient = webClient;
+ }
+
+ @GetMapping
+ public String index(
+ @RegisteredOAuth2AuthorizedClient OAuth2AuthorizedClient authorizedClient,
+ @AuthenticationPrincipal OAuth2User oauth2User,
+ Model model) {
+
+ model.addAttribute("repositories", fetchAllRepositories(authorizedClient));
+ model.addAttribute("username", oauth2User.getAttributes().get("login"));
+
+ return "index";
+ }
+
+ private Flux fetchAllRepositories(OAuth2AuthorizedClient authorizedClient) {
+ return this.webClient
+ .get()
+ .uri(
+ GITHUB_API_URL,
+ uriBuilder -> uriBuilder.path("/user/repos").queryParam("per_page", 100).build())
+ .attributes(oauth2AuthorizedClient(authorizedClient))
+ .retrieve()
+ .bodyToMono(new ParameterizedTypeReference>() {})
+ .flatMapMany(Flux::fromIterable)
+ .map(jsonNode -> jsonNode.get("full_name").asText());
+ }
}
diff --git a/spring-web-client-oauth2-reactive-stack/src/main/java/de/rieckpil/blog/SecurityConfiguration.java b/spring-web-client-oauth2-reactive-stack/src/main/java/de/rieckpil/blog/SecurityConfiguration.java
index d0d6727d..ac32faee 100644
--- a/spring-web-client-oauth2-reactive-stack/src/main/java/de/rieckpil/blog/SecurityConfiguration.java
+++ b/spring-web-client-oauth2-reactive-stack/src/main/java/de/rieckpil/blog/SecurityConfiguration.java
@@ -2,22 +2,22 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.Customizer;
+import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;
-import static org.springframework.security.config.Customizer.withDefaults;
-
@Configuration
+@EnableWebFluxSecurity
public class SecurityConfiguration {
- @Bean
- SecurityWebFilterChain configure(ServerHttpSecurity http) {
- return http
- .authorizeExchange(exchanges ->
- exchanges.anyExchange().authenticated()
- )
- .oauth2Login(withDefaults())
- .oauth2Client(withDefaults())
- .build();
- }
+ @Bean
+ public SecurityWebFilterChain configure(ServerHttpSecurity http) {
+ http.authorizeExchange(
+ authorizeExchangeSpec -> authorizeExchangeSpec.anyExchange().authenticated())
+ .oauth2Client(Customizer.withDefaults())
+ .oauth2Login(Customizer.withDefaults());
+
+ return http.build();
+ }
}
diff --git a/spring-web-client-oauth2-reactive-stack/src/main/java/de/rieckpil/blog/SpringWebClientOauth2Application.java b/spring-web-client-oauth2-reactive-stack/src/main/java/de/rieckpil/blog/SpringWebClientOauth2Application.java
index 1ec957f1..e17ddb0b 100644
--- a/spring-web-client-oauth2-reactive-stack/src/main/java/de/rieckpil/blog/SpringWebClientOauth2Application.java
+++ b/spring-web-client-oauth2-reactive-stack/src/main/java/de/rieckpil/blog/SpringWebClientOauth2Application.java
@@ -6,8 +6,7 @@
@SpringBootApplication
public class SpringWebClientOauth2Application {
- public static void main(String[] args) {
- SpringApplication.run(SpringWebClientOauth2Application.class, args);
- }
-
+ public static void main(String[] args) {
+ SpringApplication.run(SpringWebClientOauth2Application.class, args);
+ }
}
diff --git a/spring-web-client-oauth2-reactive-stack/src/main/java/de/rieckpil/blog/WebClientConfig.java b/spring-web-client-oauth2-reactive-stack/src/main/java/de/rieckpil/blog/WebClientConfig.java
index 0f61adee..19bd4932 100644
--- a/spring-web-client-oauth2-reactive-stack/src/main/java/de/rieckpil/blog/WebClientConfig.java
+++ b/spring-web-client-oauth2-reactive-stack/src/main/java/de/rieckpil/blog/WebClientConfig.java
@@ -14,31 +14,27 @@
@Configuration
public class WebClientConfig {
- @Bean
- public WebClient webClient(ReactiveOAuth2AuthorizedClientManager authorizedClientManager) {
- ServerOAuth2AuthorizedClientExchangeFilterFunction oauth =
- new ServerOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
- return WebClient.builder()
- .filter(oauth)
- .build();
- }
-
- @Bean
- public ReactiveOAuth2AuthorizedClientManager authorizedClientManager(
- ReactiveClientRegistrationRepository clientRegistrationRepository,
- ServerOAuth2AuthorizedClientRepository authorizedClientRepository) {
-
- ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider =
- ReactiveOAuth2AuthorizedClientProviderBuilder.builder()
- .authorizationCode()
- .build();
-
- DefaultReactiveOAuth2AuthorizedClientManager authorizedClientManager =
- new DefaultReactiveOAuth2AuthorizedClientManager(
- clientRegistrationRepository, authorizedClientRepository);
-
- authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
-
- return authorizedClientManager;
- }
+ @Bean
+ public WebClient webClient(ReactiveOAuth2AuthorizedClientManager authorizedClientManager) {
+ ServerOAuth2AuthorizedClientExchangeFilterFunction oauth =
+ new ServerOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
+ return WebClient.builder().filter(oauth).build();
+ }
+
+ @Bean
+ public ReactiveOAuth2AuthorizedClientManager authorizedClientManager(
+ ReactiveClientRegistrationRepository clientRegistrationRepository,
+ ServerOAuth2AuthorizedClientRepository authorizedClientRepository) {
+
+ ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider =
+ ReactiveOAuth2AuthorizedClientProviderBuilder.builder().authorizationCode().build();
+
+ DefaultReactiveOAuth2AuthorizedClientManager authorizedClientManager =
+ new DefaultReactiveOAuth2AuthorizedClientManager(
+ clientRegistrationRepository, authorizedClientRepository);
+
+ authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
+
+ return authorizedClientManager;
+ }
}
diff --git a/spring-web-client-oauth2-reactive-stack/src/test/java/de/rieckpil/blog/SpringWebClientOauth2ApplicationTests.java b/spring-web-client-oauth2-reactive-stack/src/test/java/de/rieckpil/blog/SpringWebClientOauth2ApplicationTests.java
index 4658a301..301542be 100644
--- a/spring-web-client-oauth2-reactive-stack/src/test/java/de/rieckpil/blog/SpringWebClientOauth2ApplicationTests.java
+++ b/spring-web-client-oauth2-reactive-stack/src/test/java/de/rieckpil/blog/SpringWebClientOauth2ApplicationTests.java
@@ -6,8 +6,6 @@
@SpringBootTest
class SpringWebClientOauth2ApplicationTests {
- @Test
- void contextLoads() {
- }
-
+ @Test
+ void contextLoads() {}
}
diff --git a/spring-web-client-oauth2-servlet-stack/pom.xml b/spring-web-client-oauth2-servlet-stack/pom.xml
index 6078a8e5..3558b0af 100644
--- a/spring-web-client-oauth2-servlet-stack/pom.xml
+++ b/spring-web-client-oauth2-servlet-stack/pom.xml
@@ -2,22 +2,18 @@
4.0.0
-
- org.springframework.boot
- spring-boot-starter-parent
- 2.2.2.RELEASE
-
-
+
de.rieckpil.blog
+ blog-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
+
+
spring-web-client-oauth2-servlet-stack
0.0.1-SNAPSHOT
spring-web-client-oauth2-servlet-stack
-
- 11
-
-
org.springframework.boot
diff --git a/spring-web-client-oauth2-servlet-stack/src/main/java/de/rieckpil/blog/GitHubController.java b/spring-web-client-oauth2-servlet-stack/src/main/java/de/rieckpil/blog/GitHubController.java
index 8f71c896..d9467e02 100644
--- a/spring-web-client-oauth2-servlet-stack/src/main/java/de/rieckpil/blog/GitHubController.java
+++ b/spring-web-client-oauth2-servlet-stack/src/main/java/de/rieckpil/blog/GitHubController.java
@@ -1,6 +1,10 @@
package de.rieckpil.blog;
+import static org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction.oauth2AuthorizedClient;
+
import com.fasterxml.jackson.databind.node.ArrayNode;
+import java.util.ArrayList;
+import java.util.List;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
import org.springframework.security.oauth2.client.annotation.RegisteredOAuth2AuthorizedClient;
@@ -11,52 +15,44 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.reactive.function.client.WebClient;
-import java.util.ArrayList;
-import java.util.List;
-
-import static org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction.oauth2AuthorizedClient;
-
@Controller
@RequestMapping("/")
public class GitHubController {
- private static final String GITHUB_API_URL = "https://api.github.com/";
-
- private WebClient webClient;
+ private static final String GITHUB_API_URL = "https://api.github.com/";
- public GitHubController(WebClient webClient) {
- this.webClient = webClient;
- }
+ private WebClient webClient;
- @GetMapping
- public String index(@RegisteredOAuth2AuthorizedClient OAuth2AuthorizedClient authorizedClient,
- @AuthenticationPrincipal OAuth2User oauth2User,
- Model model) {
+ public GitHubController(WebClient webClient) {
+ this.webClient = webClient;
+ }
- model.addAttribute("repositories", fetchAllRepositories(authorizedClient));
- model.addAttribute("username", oauth2User.getAttributes().get("login"));
+ @GetMapping
+ public String index(
+ @RegisteredOAuth2AuthorizedClient OAuth2AuthorizedClient authorizedClient,
+ @AuthenticationPrincipal OAuth2User oauth2User,
+ Model model) {
- return "index";
- }
+ model.addAttribute("repositories", fetchAllRepositories(authorizedClient));
+ model.addAttribute("username", oauth2User.getAttributes().get("login"));
- private List fetchAllRepositories(OAuth2AuthorizedClient authorizedClient) {
- List repositoryNames = new ArrayList<>();
+ return "index";
+ }
- this.webClient
- .get()
- .uri(GITHUB_API_URL, uriBuilder ->
- uriBuilder
- .path("/user/repos")
- .queryParam("per_page", 100)
- .build()
- )
- .attributes(oauth2AuthorizedClient(authorizedClient))
- .retrieve()
- .bodyToMono(ArrayNode.class)
- .block()
- .forEach(jsonNode -> repositoryNames.add(jsonNode.get("full_name").asText()));
+ private List fetchAllRepositories(OAuth2AuthorizedClient authorizedClient) {
+ List repositoryNames = new ArrayList<>();
- return repositoryNames;
- }
+ this.webClient
+ .get()
+ .uri(
+ GITHUB_API_URL,
+ uriBuilder -> uriBuilder.path("/user/repos").queryParam("per_page", 100).build())
+ .attributes(oauth2AuthorizedClient(authorizedClient))
+ .retrieve()
+ .bodyToMono(ArrayNode.class)
+ .block()
+ .forEach(jsonNode -> repositoryNames.add(jsonNode.get("full_name").asText()));
+ return repositoryNames;
+ }
}
diff --git a/spring-web-client-oauth2-servlet-stack/src/main/java/de/rieckpil/blog/SecurityConfiguration.java b/spring-web-client-oauth2-servlet-stack/src/main/java/de/rieckpil/blog/SecurityConfiguration.java
index ffb3c25d..1870f6ca 100644
--- a/spring-web-client-oauth2-servlet-stack/src/main/java/de/rieckpil/blog/SecurityConfiguration.java
+++ b/spring-web-client-oauth2-servlet-stack/src/main/java/de/rieckpil/blog/SecurityConfiguration.java
@@ -1,21 +1,23 @@
package de.rieckpil.blog;
+import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
-import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.web.SecurityFilterChain;
@Configuration
-public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
+public class SecurityConfiguration {
- @Override
- protected void configure(HttpSecurity http) throws Exception {
- http
- .authorizeRequests()
- .anyRequest().authenticated()
- .and()
- .oauth2Client()
- .and()
- .oauth2Login();
- }
+ @Bean
+ public SecurityFilterChain configure(HttpSecurity http) throws Exception {
+ http.authorizeRequests()
+ .anyRequest()
+ .authenticated()
+ .and()
+ .oauth2Client(Customizer.withDefaults())
+ .oauth2Login(Customizer.withDefaults());
+ return http.build();
+ }
}
diff --git a/spring-web-client-oauth2-servlet-stack/src/main/java/de/rieckpil/blog/SpringWebClientOauth2Application.java b/spring-web-client-oauth2-servlet-stack/src/main/java/de/rieckpil/blog/SpringWebClientOauth2Application.java
index 1ec957f1..e17ddb0b 100644
--- a/spring-web-client-oauth2-servlet-stack/src/main/java/de/rieckpil/blog/SpringWebClientOauth2Application.java
+++ b/spring-web-client-oauth2-servlet-stack/src/main/java/de/rieckpil/blog/SpringWebClientOauth2Application.java
@@ -6,8 +6,7 @@
@SpringBootApplication
public class SpringWebClientOauth2Application {
- public static void main(String[] args) {
- SpringApplication.run(SpringWebClientOauth2Application.class, args);
- }
-
+ public static void main(String[] args) {
+ SpringApplication.run(SpringWebClientOauth2Application.class, args);
+ }
}
diff --git a/spring-web-client-oauth2-servlet-stack/src/main/java/de/rieckpil/blog/WebClientConfig.java b/spring-web-client-oauth2-servlet-stack/src/main/java/de/rieckpil/blog/WebClientConfig.java
index c8a70283..29e4e345 100644
--- a/spring-web-client-oauth2-servlet-stack/src/main/java/de/rieckpil/blog/WebClientConfig.java
+++ b/spring-web-client-oauth2-servlet-stack/src/main/java/de/rieckpil/blog/WebClientConfig.java
@@ -13,26 +13,25 @@
@Configuration
public class WebClientConfig {
- @Bean
- public WebClient webClient(OAuth2AuthorizedClientManager authorizedClientManager) {
- ServletOAuth2AuthorizedClientExchangeFilterFunction oauth =
- new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
- return WebClient.builder()
- .filter(oauth)
- .build();
- }
+ @Bean
+ public WebClient webClient(OAuth2AuthorizedClientManager authorizedClientManager) {
+ ServletOAuth2AuthorizedClientExchangeFilterFunction oauth =
+ new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
+ return WebClient.builder().filter(oauth).build();
+ }
- @Bean
- public OAuth2AuthorizedClientManager authorizedClientManager(
- ClientRegistrationRepository clientRegistrationRepository,
- OAuth2AuthorizedClientRepository authorizedClientRepository) {
+ @Bean
+ public OAuth2AuthorizedClientManager authorizedClientManager(
+ ClientRegistrationRepository clientRegistrationRepository,
+ OAuth2AuthorizedClientRepository authorizedClientRepository) {
- DefaultOAuth2AuthorizedClientManager authorizedClientManager =
- new DefaultOAuth2AuthorizedClientManager(
- clientRegistrationRepository, authorizedClientRepository);
+ DefaultOAuth2AuthorizedClientManager authorizedClientManager =
+ new DefaultOAuth2AuthorizedClientManager(
+ clientRegistrationRepository, authorizedClientRepository);
- authorizedClientManager.setAuthorizedClientProvider(new AuthorizationCodeOAuth2AuthorizedClientProvider());
+ authorizedClientManager.setAuthorizedClientProvider(
+ new AuthorizationCodeOAuth2AuthorizedClientProvider());
- return authorizedClientManager;
- }
+ return authorizedClientManager;
+ }
}
diff --git a/spring-web-client-oauth2-servlet-stack/src/test/java/de/rieckpil/blog/SpringWebClientOauth2ApplicationTests.java b/spring-web-client-oauth2-servlet-stack/src/test/java/de/rieckpil/blog/SpringWebClientOauth2ApplicationTests.java
index 4658a301..301542be 100644
--- a/spring-web-client-oauth2-servlet-stack/src/test/java/de/rieckpil/blog/SpringWebClientOauth2ApplicationTests.java
+++ b/spring-web-client-oauth2-servlet-stack/src/test/java/de/rieckpil/blog/SpringWebClientOauth2ApplicationTests.java
@@ -6,8 +6,6 @@
@SpringBootTest
class SpringWebClientOauth2ApplicationTests {
- @Test
- void contextLoads() {
- }
-
+ @Test
+ void contextLoads() {}
}
diff --git a/spring-web-client-testing-with-mockwebserver/pom.xml b/spring-web-client-testing-with-mockwebserver/pom.xml
index 8dbe95a1..385a797f 100644
--- a/spring-web-client-testing-with-mockwebserver/pom.xml
+++ b/spring-web-client-testing-with-mockwebserver/pom.xml
@@ -3,20 +3,18 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0%20https://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
- org.springframework.boot
- spring-boot-starter-parent
- 2.3.0.RELEASE
-
+ de.rieckpil.blog
+ blog-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
- de.rieckpil.blog
spring-web-client-testing-with-mockwebserver
0.0.1-SNAPSHOT
spring-web-client-testing-with-mockwebserver
Demo project for Spring Boot
- 11
4.7.2
4.7.2
diff --git a/spring-web-client-testing-with-mockwebserver/src/main/java/de/rieckpil/blog/Application.java b/spring-web-client-testing-with-mockwebserver/src/main/java/de/rieckpil/blog/Application.java
index ad872b65..478dedf1 100644
--- a/spring-web-client-testing-with-mockwebserver/src/main/java/de/rieckpil/blog/Application.java
+++ b/spring-web-client-testing-with-mockwebserver/src/main/java/de/rieckpil/blog/Application.java
@@ -6,8 +6,6 @@
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
-import java.math.BigDecimal;
-
@SpringBootApplication
public class Application implements CommandLineRunner {
@@ -19,7 +17,6 @@ public Application(UsersClient usersClient, ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
-
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@@ -31,10 +28,9 @@ public void run(String... args) throws Exception {
ObjectNode objectNode = objectMapper.createObjectNode();
objectNode.put("name", "duke");
objectNode.put("email", "duke@java.io");
- objectNode.set("address",
- objectMapper.createObjectNode()
- .put("street", "main")
- .put("postalCode", "91074"));
+ objectNode.set(
+ "address",
+ objectMapper.createObjectNode().put("street", "main").put("postalCode", "91074"));
objectNode.set("hobbies", objectMapper.createArrayNode().add("sports").add("bowling"));
System.out.println(usersClient.createNewUser(objectNode));
diff --git a/spring-web-client-testing-with-mockwebserver/src/main/java/de/rieckpil/blog/RetryClient.java b/spring-web-client-testing-with-mockwebserver/src/main/java/de/rieckpil/blog/RetryClient.java
index cda37645..70f59d97 100644
--- a/spring-web-client-testing-with-mockwebserver/src/main/java/de/rieckpil/blog/RetryClient.java
+++ b/spring-web-client-testing-with-mockwebserver/src/main/java/de/rieckpil/blog/RetryClient.java
@@ -3,37 +3,38 @@
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
+import java.time.Duration;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import reactor.util.retry.Retry;
-import java.time.Duration;
-
@Component
public class RetryClient {
private final WebClient webClient;
private final ObjectMapper objectMapper;
- public RetryClient(WebClient.Builder builder,
- @Value("${clients.users.url}") String usersBaseUrl, ObjectMapper objectMapper) {
+ public RetryClient(
+ WebClient.Builder builder,
+ @Value("${clients.users.url}") String usersBaseUrl,
+ ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
this.webClient = builder.baseUrl(usersBaseUrl).build();
}
public JsonNode getData() {
- Mono fallback = Mono.just(this.objectMapper.createObjectNode().put("message", "fallback"));
+ Mono fallback =
+ Mono.just(this.objectMapper.createObjectNode().put("message", "fallback"));
return this.webClient
- .get()
- .uri("/data")
- .retrieve()
- .bodyToMono(JsonNode.class)
- .retryWhen(Retry.fixedDelay(2, Duration.ofMillis(100)))
- .timeout(Duration.ofSeconds(2),
- fallback)
- .block();
+ .get()
+ .uri("/data")
+ .retrieve()
+ .bodyToMono(JsonNode.class)
+ .retryWhen(Retry.fixedDelay(2, Duration.ofMillis(100)))
+ .timeout(Duration.ofSeconds(2), fallback)
+ .block();
}
}
diff --git a/spring-web-client-testing-with-mockwebserver/src/main/java/de/rieckpil/blog/UsersClient.java b/spring-web-client-testing-with-mockwebserver/src/main/java/de/rieckpil/blog/UsersClient.java
index 3dd31602..5b596128 100644
--- a/spring-web-client-testing-with-mockwebserver/src/main/java/de/rieckpil/blog/UsersClient.java
+++ b/spring-web-client-testing-with-mockwebserver/src/main/java/de/rieckpil/blog/UsersClient.java
@@ -14,28 +14,29 @@ public class UsersClient {
private final WebClient webClient;
- public UsersClient(WebClient.Builder builder,
- @Value("${clients.users.url}") String usersBaseUrl) {
+ public UsersClient(
+ WebClient.Builder builder, @Value("${clients.users.url}") String usersBaseUrl) {
this.webClient = builder.baseUrl(usersBaseUrl).build();
}
public JsonNode getUserById(Long id) {
return this.webClient
- .get()
- .uri("/users/{id}", id)
- .retrieve()
- .bodyToMono(JsonNode.class)
- .block();
+ .get()
+ .uri("/users/{id}", id)
+ .retrieve()
+ .bodyToMono(JsonNode.class)
+ .block();
}
public JsonNode createNewUser(JsonNode payload) {
- ClientResponse clientResponse = this.webClient
- .post()
- .uri("/users")
- .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
- .bodyValue(payload)
- .exchange()
- .block();
+ ClientResponse clientResponse =
+ this.webClient
+ .post()
+ .uri("/users")
+ .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
+ .bodyValue(payload)
+ .exchange()
+ .block();
if (clientResponse.statusCode().equals(HttpStatus.CREATED)) {
return clientResponse.bodyToMono(JsonNode.class).block();
diff --git a/spring-web-client-testing-with-mockwebserver/src/test/java/de/rieckpil/blog/RetryClientTest.java b/spring-web-client-testing-with-mockwebserver/src/test/java/de/rieckpil/blog/RetryClientTest.java
index cc43761b..d3956c78 100644
--- a/spring-web-client-testing-with-mockwebserver/src/test/java/de/rieckpil/blog/RetryClientTest.java
+++ b/spring-web-client-testing-with-mockwebserver/src/test/java/de/rieckpil/blog/RetryClientTest.java
@@ -1,18 +1,17 @@
package de.rieckpil.blog;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.web.reactive.function.client.WebClient;
-import java.io.IOException;
-import java.util.concurrent.TimeUnit;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
class RetryClientTest {
private MockWebServer mockWebServer;
@@ -22,21 +21,22 @@ class RetryClientTest {
public void setup() throws IOException {
this.mockWebServer = new MockWebServer();
this.mockWebServer.start();
- this.retryClient = new RetryClient(WebClient.builder(), mockWebServer.url("http://github.com/").toString(), new ObjectMapper());
+ this.retryClient =
+ new RetryClient(WebClient.builder(), mockWebServer.url("http://github.com/").toString(), new ObjectMapper());
}
@Test
public void testRetry() {
- MockResponse failureResponse = new MockResponse()
- .setResponseCode(500);
+ MockResponse failureResponse = new MockResponse().setResponseCode(500);
mockWebServer.enqueue(failureResponse);
mockWebServer.enqueue(failureResponse);
- MockResponse mockResponse = new MockResponse()
- .addHeader("Content-Type", "application/json; charset=utf-8")
- .setBody("{\"id\": 1, \"name\":\"duke\"}")
- .throttleBody(16, 5000, TimeUnit.MILLISECONDS);
+ MockResponse mockResponse =
+ new MockResponse()
+ .addHeader("Content-Type", "application/json; charset=utf-8")
+ .setBody("{\"id\": 1, \"name\":\"duke\"}")
+ .throttleBody(16, 5000, TimeUnit.MILLISECONDS);
mockWebServer.enqueue(mockResponse);
@@ -45,5 +45,4 @@ public void testRetry() {
System.out.println(result);
assertEquals("fallback", result.get("message").asText());
}
-
}
diff --git a/spring-web-client-testing-with-mockwebserver/src/test/java/de/rieckpil/blog/UsersClientTest.java b/spring-web-client-testing-with-mockwebserver/src/test/java/de/rieckpil/blog/UsersClientTest.java
index 7567bf88..b10bee3d 100644
--- a/spring-web-client-testing-with-mockwebserver/src/test/java/de/rieckpil/blog/UsersClientTest.java
+++ b/spring-web-client-testing-with-mockwebserver/src/test/java/de/rieckpil/blog/UsersClientTest.java
@@ -1,7 +1,12 @@
package de.rieckpil.blog;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
import okhttp3.mockwebserver.Dispatcher;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
@@ -11,12 +16,6 @@
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.WebClientResponseException;
-import java.io.IOException;
-import java.util.concurrent.TimeUnit;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-
class UsersClientTest {
private MockWebServer mockWebServer;
@@ -31,10 +30,11 @@ public void setup() throws IOException {
@Test
public void testGetUserById() throws InterruptedException {
- MockResponse mockResponse = new MockResponse()
- .addHeader("Content-Type", "application/json; charset=utf-8")
- .setBody("{\"id\": 1, \"name\":\"duke\"}")
- .throttleBody(16, 5, TimeUnit.SECONDS);
+ MockResponse mockResponse =
+ new MockResponse()
+ .addHeader("Content-Type", "application/json; charset=utf-8")
+ .setBody("{\"id\": 1, \"name\":\"duke\"}")
+ .throttleBody(16, 5, TimeUnit.SECONDS);
mockWebServer.enqueue(mockResponse);
@@ -49,15 +49,17 @@ public void testGetUserById() throws InterruptedException {
@Test
public void testCreatingUsers() {
- MockResponse mockResponse = new MockResponse()
- .addHeader("Content-Type", "application/json; charset=utf-8")
- .setBody("{\"id\": 1, \"name\":\"duke\"}")
- .throttleBody(16, 5, TimeUnit.SECONDS)
- .setResponseCode(201);
+ MockResponse mockResponse =
+ new MockResponse()
+ .addHeader("Content-Type", "application/json; charset=utf-8")
+ .setBody("{\"id\": 1, \"name\":\"duke\"}")
+ .throttleBody(16, 5, TimeUnit.SECONDS)
+ .setResponseCode(201);
mockWebServer.enqueue(mockResponse);
- JsonNode result = usersClient.createNewUser(new ObjectMapper().createObjectNode().put("name", "duke"));
+ JsonNode result =
+ usersClient.createNewUser(new ObjectMapper().createObjectNode().put("name", "duke"));
assertEquals(1, result.get("id").asInt());
assertEquals("duke", result.get("name").asText());
@@ -65,37 +67,39 @@ public void testCreatingUsers() {
@Test
public void testCreatingUsersWithNon201ResponseCode() {
- MockResponse mockResponse = new MockResponse()
- .setResponseCode(204);
+ MockResponse mockResponse = new MockResponse().setResponseCode(204);
mockWebServer.enqueue(mockResponse);
- assertThrows(RuntimeException.class, () ->
- usersClient.createNewUser(new ObjectMapper().createObjectNode().put("name", "duke")));
+ assertThrows(
+ RuntimeException.class,
+ () -> usersClient.createNewUser(new ObjectMapper().createObjectNode().put("name", "duke")));
}
@Test
public void testMultipleResponseCodes() {
- final Dispatcher dispatcher = new Dispatcher() {
- @Override
- public MockResponse dispatch(RecordedRequest request) {
- switch (request.getPath()) {
- case "/users/1":
- return new MockResponse().setResponseCode(200);
- case "/users/2":
- return new MockResponse().setResponseCode(500);
- case "/users/3":
- return new MockResponse().setResponseCode(200).setBody("{\"id\": 1, \"name\":\"duke\"}");
- }
- return new MockResponse().setResponseCode(404);
- }
- };
+ final Dispatcher dispatcher =
+ new Dispatcher() {
+ @Override
+ public MockResponse dispatch(RecordedRequest request) {
+ switch (request.getPath()) {
+ case "/users/1":
+ return new MockResponse().setResponseCode(200);
+ case "/users/2":
+ return new MockResponse().setResponseCode(500);
+ case "/users/3":
+ return new MockResponse()
+ .setResponseCode(200)
+ .setBody("{\"id\": 1, \"name\":\"duke\"}");
+ }
+ return new MockResponse().setResponseCode(404);
+ }
+ };
mockWebServer.setDispatcher(dispatcher);
assertThrows(WebClientResponseException.class, () -> usersClient.getUserById(2L));
assertThrows(WebClientResponseException.class, () -> usersClient.getUserById(4L));
}
-
}
diff --git a/spring-web-mvc-cheat-sheet/pom.xml b/spring-web-mvc-cheat-sheet/pom.xml
index e1fee627..f8fd8c2b 100644
--- a/spring-web-mvc-cheat-sheet/pom.xml
+++ b/spring-web-mvc-cheat-sheet/pom.xml
@@ -2,22 +2,19 @@
4.0.0
+
- org.springframework.boot
- spring-boot-starter-parent
- 2.2.6.RELEASE
-
+ de.rieckpil.blog
+ blog-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
- de.rieckpil.blog
+
spring-web-mvc-cheat-sheet
0.0.1-SNAPSHOT
spring-web-mvc-cheat-sheet
Spring Web MVC Cheat Sheet
-
- 11
-
-
org.springframework.boot
@@ -27,6 +24,10 @@
org.springframework.boot
spring-boot-starter-web
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
org.springframework.boot
spring-boot-starter-webflux
@@ -46,6 +47,10 @@
+
+ jakarta.xml.bind
+ jakarta.xml.bind-api
+
diff --git a/spring-web-mvc-cheat-sheet/src/main/java/de/rieckpil/blog/Application.java b/spring-web-mvc-cheat-sheet/src/main/java/de/rieckpil/blog/Application.java
index bd5e4c56..6511f3c1 100644
--- a/spring-web-mvc-cheat-sheet/src/main/java/de/rieckpil/blog/Application.java
+++ b/spring-web-mvc-cheat-sheet/src/main/java/de/rieckpil/blog/Application.java
@@ -9,5 +9,4 @@ public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
-
}
diff --git a/spring-web-mvc-cheat-sheet/src/main/java/de/rieckpil/blog/FileHandlingController.java b/spring-web-mvc-cheat-sheet/src/main/java/de/rieckpil/blog/FileHandlingController.java
index 99f7eaed..e60433f8 100644
--- a/spring-web-mvc-cheat-sheet/src/main/java/de/rieckpil/blog/FileHandlingController.java
+++ b/spring-web-mvc-cheat-sheet/src/main/java/de/rieckpil/blog/FileHandlingController.java
@@ -1,5 +1,6 @@
package de.rieckpil.blog;
+import java.io.IOException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
@@ -7,8 +8,6 @@
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
-import java.io.IOException;
-
@RestController
@RequestMapping("/files")
public class FileHandlingController {
@@ -34,6 +33,5 @@ public void upload(@RequestParam("file") MultipartFile multipartFile) throws IOE
System.out.println("Size: " + multipartFile.getSize());
byte[] content = multipartFile.getBytes();
-
}
}
diff --git a/spring-web-mvc-cheat-sheet/src/main/java/de/rieckpil/blog/JsonPayloadController.java b/spring-web-mvc-cheat-sheet/src/main/java/de/rieckpil/blog/JsonPayloadController.java
index ee2ae366..e159f3cc 100644
--- a/spring-web-mvc-cheat-sheet/src/main/java/de/rieckpil/blog/JsonPayloadController.java
+++ b/spring-web-mvc-cheat-sheet/src/main/java/de/rieckpil/blog/JsonPayloadController.java
@@ -1,5 +1,8 @@
package de.rieckpil.blog;
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Set;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
@@ -7,20 +10,16 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
-import java.time.LocalDateTime;
-import java.util.List;
-import java.util.Set;
-
@RestController
@RequestMapping("/json")
public class JsonPayloadController {
@GetMapping(path = "/orders", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity> getOrders() {
- List orders = List.of(
- new Order("42L", Set.of("foreign", "books"), 1L, LocalDateTime.now()),
- new Order("58B", Set.of("fractile", "computer"), 48L, LocalDateTime.now())
- );
+ List orders =
+ List.of(
+ new Order("42L", Set.of("foreign", "books"), 1L, LocalDateTime.now()),
+ new Order("58B", Set.of("fractile", "computer"), 48L, LocalDateTime.now()));
return ResponseEntity.status(HttpStatus.I_AM_A_TEAPOT).body(orders);
}
}
diff --git a/spring-web-mvc-cheat-sheet/src/main/java/de/rieckpil/blog/MixMediaTypeController.java b/spring-web-mvc-cheat-sheet/src/main/java/de/rieckpil/blog/MixMediaTypeController.java
index e8e93d75..c0e4665e 100644
--- a/spring-web-mvc-cheat-sheet/src/main/java/de/rieckpil/blog/MixMediaTypeController.java
+++ b/spring-web-mvc-cheat-sheet/src/main/java/de/rieckpil/blog/MixMediaTypeController.java
@@ -1,25 +1,25 @@
package de.rieckpil.blog;
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Set;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
-import java.time.LocalDateTime;
-import java.util.List;
-import java.util.Set;
-
@RestController
@RequestMapping("/mix")
public class MixMediaTypeController {
- @GetMapping(path = "/orders", produces = {MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE})
+ @GetMapping(
+ path = "/orders",
+ produces = {MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE})
public List getOrders() {
- List orders = List.of(
- new Order("42L", Set.of("foreign", "books"), 1L, LocalDateTime.now()),
- new Order("58B", Set.of("fractile", "computer"), 48L, LocalDateTime.now())
- );
+ List orders =
+ List.of(
+ new Order("42L", Set.of("foreign", "books"), 1L, LocalDateTime.now()),
+ new Order("58B", Set.of("fractile", "computer"), 48L, LocalDateTime.now()));
return orders;
}
-
}
diff --git a/spring-web-mvc-cheat-sheet/src/main/java/de/rieckpil/blog/Order.java b/spring-web-mvc-cheat-sheet/src/main/java/de/rieckpil/blog/Order.java
index 40a63098..049a5bb9 100644
--- a/spring-web-mvc-cheat-sheet/src/main/java/de/rieckpil/blog/Order.java
+++ b/spring-web-mvc-cheat-sheet/src/main/java/de/rieckpil/blog/Order.java
@@ -1,6 +1,6 @@
package de.rieckpil.blog;
-import javax.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlRootElement;
import java.time.LocalDateTime;
import java.util.Set;
@@ -12,8 +12,7 @@ public class Order {
private Long customerId;
private LocalDateTime orderAt;
- public Order() {
- }
+ public Order() {}
public Order(String id, Set tags, Long customerId, LocalDateTime orderAt) {
this.id = id;
diff --git a/spring-web-mvc-cheat-sheet/src/main/java/de/rieckpil/blog/Payload.java b/spring-web-mvc-cheat-sheet/src/main/java/de/rieckpil/blog/Payload.java
index 42b6373b..161638dc 100644
--- a/spring-web-mvc-cheat-sheet/src/main/java/de/rieckpil/blog/Payload.java
+++ b/spring-web-mvc-cheat-sheet/src/main/java/de/rieckpil/blog/Payload.java
@@ -1,20 +1,17 @@
package de.rieckpil.blog;
-import javax.validation.constraints.Email;
-import javax.validation.constraints.Future;
-import javax.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Email;
+import jakarta.validation.constraints.Future;
+import jakarta.validation.constraints.NotBlank;
import java.time.LocalDateTime;
public class Payload {
- @NotBlank
- private String message;
+ @NotBlank private String message;
- @Email
- private String email;
+ @Email private String email;
- @Future
- private LocalDateTime memberSince;
+ @Future private LocalDateTime memberSince;
public String getMessage() {
return message;
diff --git a/spring-web-mvc-cheat-sheet/src/main/java/de/rieckpil/blog/ValidationController.java b/spring-web-mvc-cheat-sheet/src/main/java/de/rieckpil/blog/ValidationController.java
index 7673f34d..42b00179 100644
--- a/spring-web-mvc-cheat-sheet/src/main/java/de/rieckpil/blog/ValidationController.java
+++ b/spring-web-mvc-cheat-sheet/src/main/java/de/rieckpil/blog/ValidationController.java
@@ -1,15 +1,14 @@
package de.rieckpil.blog;
+import jakarta.validation.ConstraintViolationException;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.Positive;
+import jakarta.validation.constraints.Size;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
-import javax.validation.ConstraintViolationException;
-import javax.validation.Valid;
-import javax.validation.constraints.Positive;
-import javax.validation.constraints.Size;
-
@Validated
@RestController
@RequestMapping("/validation")
@@ -17,16 +16,16 @@ public class ValidationController {
@GetMapping("/{message}")
public String validateParameters(
- @PathVariable("message") @Size(min = 5, max = 10) String message,
- @RequestParam("size") @Positive Long size) {
+ @PathVariable("message") @Size(min = 5, max = 10) String message,
+ @RequestParam("size") @Positive Long size) {
return "Query parameters where valid";
}
-@PostMapping
-public String validatePayload(@Valid @RequestBody Payload payload) {
- return "Payload is valid";
-}
+ @PostMapping
+ public String validatePayload(@Valid @RequestBody Payload payload) {
+ return "Payload is valid";
+ }
@ExceptionHandler(ConstraintViolationException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@@ -34,4 +33,3 @@ ResponseEntity handleConstraintViolationException(ConstraintViolationExc
return new ResponseEntity<>("Validation Error: " + e.getMessage(), HttpStatus.BAD_REQUEST);
}
}
-
diff --git a/spring-web-mvc-cheat-sheet/src/main/java/de/rieckpil/blog/XmlPayloadController.java b/spring-web-mvc-cheat-sheet/src/main/java/de/rieckpil/blog/XmlPayloadController.java
index d025a298..eb8153c3 100644
--- a/spring-web-mvc-cheat-sheet/src/main/java/de/rieckpil/blog/XmlPayloadController.java
+++ b/spring-web-mvc-cheat-sheet/src/main/java/de/rieckpil/blog/XmlPayloadController.java
@@ -1,24 +1,23 @@
package de.rieckpil.blog;
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Set;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
-import java.time.LocalDateTime;
-import java.util.List;
-import java.util.Set;
-
@RestController
@RequestMapping("/xml")
public class XmlPayloadController {
@GetMapping(path = "/orders", produces = MediaType.APPLICATION_XML_VALUE)
public List getOrders() {
- List orders = List.of(
- new Order("42L", Set.of("foreign", "books"), 1L, LocalDateTime.now()),
- new Order("58B", Set.of("fractile", "computer"), 48L, LocalDateTime.now())
- );
+ List orders =
+ List.of(
+ new Order("42L", Set.of("foreign", "books"), 1L, LocalDateTime.now()),
+ new Order("58B", Set.of("fractile", "computer"), 48L, LocalDateTime.now()));
return orders;
}
}
diff --git a/spring-web-mvc-cheat-sheet/src/test/java/de/rieckpil/blog/ApplicationTest.java b/spring-web-mvc-cheat-sheet/src/test/java/de/rieckpil/blog/ApplicationTest.java
index 24eea4ab..b6751e0d 100644
--- a/spring-web-mvc-cheat-sheet/src/test/java/de/rieckpil/blog/ApplicationTest.java
+++ b/spring-web-mvc-cheat-sheet/src/test/java/de/rieckpil/blog/ApplicationTest.java
@@ -7,7 +7,5 @@
class ApplicationTest {
@Test
- void contextLoads() {
- }
-
+ void contextLoads() {}
}
diff --git a/spring-web-test-client/README.md b/spring-web-test-client/README.md
index 3a8aa16f..bfe1070e 100644
--- a/spring-web-test-client/README.md
+++ b/spring-web-test-client/README.md
@@ -1,7 +1,7 @@
-# Codebase for the blog post [#HOWTO: Spring WebTestClient for efficient testing of your REST API](https://rieckpil.de/spring-webtestclient-for-efficient-testing-of-your-rest-api/)
+# Codebase for the blog post [Spring WebTestClient for Efficient REST API Testing](https://rieckpil.de/spring-webtestclient-for-efficient-testing-of-your-rest-api/)
Steps to run this project:
1. Clone this Git repository
2. Navigate to the folder `spring-web-test-client`
-3. Run `mvn clean verify` to execute the integration tests
\ No newline at end of file
+3. Run `mvn clean verify` to execute the integration tests
diff --git a/spring-web-test-client/pom.xml b/spring-web-test-client/pom.xml
index e1b9f09d..b9e382f7 100644
--- a/spring-web-test-client/pom.xml
+++ b/spring-web-test-client/pom.xml
@@ -2,43 +2,36 @@
4.0.0
+
- org.springframework.boot
- spring-boot-starter-parent
- 2.2.2.RELEASE
-
+ de.rieckpil.blog
+ blog-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
- de.rieckpil.blog
spring-web-test-client
0.0.1-SNAPSHOT
spring-web-test-client
Test Endpoints using WebTestClient
-
- 11
-
-
org.springframework.boot
spring-boot-starter-web
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
org.springframework.boot
spring-boot-starter-webflux
- test
org.springframework.boot
spring-boot-starter-test
test
-
-
- org.junit.vintage
- junit-vintage-engine
-
-
@@ -51,6 +44,14 @@
org.apache.maven.plugins
maven-failsafe-plugin
+
+
+
+ integration-test
+ verify
+
+
+
diff --git a/spring-web-test-client/src/main/java/de/rieckpil/blog/Application.java b/spring-web-test-client/src/main/java/de/rieckpil/blog/Application.java
new file mode 100644
index 00000000..6511f3c1
--- /dev/null
+++ b/spring-web-test-client/src/main/java/de/rieckpil/blog/Application.java
@@ -0,0 +1,12 @@
+package de.rieckpil.blog;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+}
diff --git a/spring-web-test-client/src/main/java/de/rieckpil/blog/User.java b/spring-web-test-client/src/main/java/de/rieckpil/blog/User.java
index 040ae8d9..854c8b10 100644
--- a/spring-web-test-client/src/main/java/de/rieckpil/blog/User.java
+++ b/spring-web-test-client/src/main/java/de/rieckpil/blog/User.java
@@ -1,21 +1,18 @@
package de.rieckpil.blog;
-import javax.validation.constraints.NotEmpty;
-import javax.validation.constraints.NotNull;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
import java.util.Objects;
import java.util.Set;
class User {
- @NotNull
- private Long id;
+ @NotNull private Long id;
- @NotEmpty
- private String name;
+ @NotEmpty private String name;
private Set tags;
- public User() {
- }
+ public User() {}
public User(Long id, String name, Set tags) {
this.name = name;
@@ -52,9 +49,9 @@ public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
- return Objects.equals(id, user.id) &&
- Objects.equals(name, user.name) &&
- Objects.equals(tags, user.tags);
+ return Objects.equals(id, user.id)
+ && Objects.equals(name, user.name)
+ && Objects.equals(tags, user.tags);
}
@Override
diff --git a/spring-web-test-client/src/main/java/de/rieckpil/blog/UserController.java b/spring-web-test-client/src/main/java/de/rieckpil/blog/UserController.java
index 5151ea3e..682e262f 100644
--- a/spring-web-test-client/src/main/java/de/rieckpil/blog/UserController.java
+++ b/spring-web-test-client/src/main/java/de/rieckpil/blog/UserController.java
@@ -1,15 +1,14 @@
package de.rieckpil.blog;
+import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
+
+import java.util.List;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;
-import java.util.List;
-
-import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
-
@RestController
@RequestMapping(value = "/api/users", produces = APPLICATION_JSON_VALUE)
public class UserController {
@@ -28,18 +27,24 @@ public List getAllUsers() {
@GetMapping("/{id}")
public User getUserById(@PathVariable("id") Long id) {
return userService
- .getUserById(id)
- .orElseThrow(() -> new UserNotFoundException(String.format("User with id [%s] not found", id)));
+ .getUserById(id)
+ .orElseThrow(
+ () -> new UserNotFoundException(String.format("User with id [%s] not found", id)));
}
@PostMapping(consumes = APPLICATION_JSON_VALUE)
- public ResponseEntity createNewUser(@RequestBody @Validated User user, UriComponentsBuilder uriComponentsBuilder) {
- User addedUser = this.userService.addNewUser(user)
- .orElseThrow(() -> new UserAlreadyExistsException(
- String.format("User with id [%s] is already present", user.getId())));
+ public ResponseEntity createNewUser(
+ @RequestBody @Validated User user, UriComponentsBuilder uriComponentsBuilder) {
+ User addedUser =
+ this.userService
+ .addNewUser(user)
+ .orElseThrow(
+ () ->
+ new UserAlreadyExistsException(
+ String.format("User with id [%s] is already present", user.getId())));
UriComponents uriComponents =
- uriComponentsBuilder.path("/api/users/{id}").buildAndExpand(addedUser.getId());
+ uriComponentsBuilder.path("/api/users/{id}").buildAndExpand(addedUser.getId());
return ResponseEntity.created(uriComponents.toUri()).build();
}
@@ -49,4 +54,3 @@ public void deleteUser(@PathVariable("id") Long id) {
this.userService.deleteUserById(id);
}
}
-
diff --git a/spring-web-test-client/src/main/java/de/rieckpil/blog/UserService.java b/spring-web-test-client/src/main/java/de/rieckpil/blog/UserService.java
index bf0d8989..cbb2ffdd 100644
--- a/spring-web-test-client/src/main/java/de/rieckpil/blog/UserService.java
+++ b/spring-web-test-client/src/main/java/de/rieckpil/blog/UserService.java
@@ -1,12 +1,11 @@
package de.rieckpil.blog;
-import org.springframework.stereotype.Service;
-
-import javax.annotation.PostConstruct;
+import jakarta.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
+import org.springframework.stereotype.Service;
@Service
public class UserService {
@@ -26,9 +25,7 @@ public List getAllUsers() {
}
public Optional getUserById(Long id) {
- return this.userList.stream()
- .filter(user -> user.getId() == id)
- .findFirst();
+ return this.userList.stream().filter(user -> user.getId() == id).findFirst();
}
public Optional addNewUser(User user) {
diff --git a/spring-web-test-client/src/test/java/de/rieckpil/blog/ApplicationIT.java b/spring-web-test-client/src/test/java/de/rieckpil/blog/ApplicationIT.java
new file mode 100644
index 00000000..c8455621
--- /dev/null
+++ b/spring-web-test-client/src/test/java/de/rieckpil/blog/ApplicationIT.java
@@ -0,0 +1,11 @@
+package de.rieckpil.blog;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class ApplicationIT {
+
+ @Test
+ void contextLoads() {}
+}
diff --git a/spring-web-test-client/src/test/java/de/rieckpil/blog/UserControllerIT.java b/spring-web-test-client/src/test/java/de/rieckpil/blog/UserControllerIT.java
index 1154a67d..415e584a 100644
--- a/spring-web-test-client/src/test/java/de/rieckpil/blog/UserControllerIT.java
+++ b/spring-web-test-client/src/test/java/de/rieckpil/blog/UserControllerIT.java
@@ -1,5 +1,10 @@
package de.rieckpil.blog;
+import static org.springframework.http.HttpHeaders.*;
+import static org.springframework.http.HttpStatus.*;
+import static org.springframework.http.MediaType.*;
+
+import java.util.Set;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@@ -7,89 +12,84 @@
import org.springframework.test.web.reactive.server.WebTestClient;
import reactor.core.publisher.Mono;
-import java.util.Set;
-
-import static org.springframework.http.HttpHeaders.*;
-import static org.springframework.http.HttpStatus.*;
-import static org.springframework.http.MediaType.*;
-
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class UserControllerIT {
- @Autowired
- private WebTestClient webTestClient;
+ @Autowired private WebTestClient webTestClient;
@Test
- public void shouldReturnThreeDefaultUsers() {
+ void shouldReturnThreeDefaultUsers() {
this.webTestClient
- .get()
- .uri("/api/users")
- .header(ACCEPT, APPLICATION_JSON_VALUE)
- .exchange()
- .expectStatus()
- .is2xxSuccessful()
- .expectHeader()
- .contentType(APPLICATION_JSON)
- .expectBody()
- .jsonPath("$.length()").isEqualTo(3)
- .jsonPath("$[0].id").isEqualTo(1)
- .jsonPath("$[0].name").isEqualTo("duke")
- .jsonPath("$[0].tags").isNotEmpty();
+ .get()
+ .uri("/api/users")
+ .header(ACCEPT, APPLICATION_JSON_VALUE)
+ .exchange()
+ .expectStatus()
+ .is2xxSuccessful()
+ .expectHeader()
+ .contentType(APPLICATION_JSON)
+ .expectBody()
+ .jsonPath("$.length()")
+ .isEqualTo(3)
+ .jsonPath("$[0].id")
+ .isEqualTo(1)
+ .jsonPath("$[0].name")
+ .isEqualTo("duke")
+ .jsonPath("$[0].tags")
+ .isNotEmpty();
}
@Test
- public void shouldNotSupportMediaTypeXML() {
+ void shouldNotSupportMediaTypeXML() {
this.webTestClient
- .get()
- .uri("/api/users")
- .header(ACCEPT, APPLICATION_XML_VALUE)
- .exchange()
- .expectStatus()
- .isEqualTo(NOT_ACCEPTABLE);
+ .get()
+ .uri("/api/users")
+ .header(ACCEPT, APPLICATION_XML_VALUE)
+ .exchange()
+ .expectStatus()
+ .isEqualTo(NOT_ACCEPTABLE);
}
-@Test
-public void shouldCreateNewUser() {
+ @Test
+ void shouldCreateNewUser() {
- var newUser = new User(10L, "test", Set.of("testing", "webtestclient"));
+ var newUser = new User(10L, "test", Set.of("testing", "webtestclient"));
- var userCreationResponse = this.webTestClient
- .post()
- .uri("/api/users")
- .body(Mono.just(newUser), User.class)
- .header(CONTENT_TYPE, APPLICATION_JSON_VALUE)
- .header(ACCEPT, APPLICATION_JSON_VALUE)
- .exchange()
- .expectStatus()
- .isEqualTo(CREATED)
- .returnResult(Void.class);
+ var userCreationResponse =
+ this.webTestClient
+ .post()
+ .uri("/api/users")
+ .body(Mono.just(newUser), User.class)
+ .header(CONTENT_TYPE, APPLICATION_JSON_VALUE)
+ .header(ACCEPT, APPLICATION_JSON_VALUE)
+ .exchange()
+ .expectStatus()
+ .isEqualTo(CREATED)
+ .returnResult(Void.class);
- var locationUrlOfNewUser = userCreationResponse.getResponseHeaders().get(LOCATION).get(0);
+ var locationUrlOfNewUser = userCreationResponse.getResponseHeaders().get(LOCATION).get(0);
- this.webTestClient
- .get()
- .uri(locationUrlOfNewUser)
- .header(ACCEPT, APPLICATION_JSON_VALUE)
- .exchange()
- .expectStatus()
- .isEqualTo(OK)
- .expectBody(User.class)
- .isEqualTo(newUser);
+ this.webTestClient
+ .get()
+ .uri(locationUrlOfNewUser)
+ .header(ACCEPT, APPLICATION_JSON_VALUE)
+ .exchange()
+ .expectStatus()
+ .isEqualTo(OK)
+ .expectBody(User.class)
+ .isEqualTo(newUser);
- this.webTestClient
- .delete()
- .uri("/api/users/{id}", newUser.getId())
- .exchange();
-}
+ this.webTestClient.delete().uri("/api/users/{id}", newUser.getId()).exchange();
+ }
@Test
- public void shouldReturnNotFoundForUnknownUserId() {
+ void shouldReturnNotFoundForUnknownUserId() {
this.webTestClient
- .get()
- .uri("/api/users/{id}", 42)
- .header(CONTENT_TYPE, APPLICATION_JSON_VALUE)
- .exchange()
- .expectStatus()
- .isEqualTo(NOT_FOUND);
+ .get()
+ .uri("/api/users/{id}", 42)
+ .header(CONTENT_TYPE, APPLICATION_JSON_VALUE)
+ .exchange()
+ .expectStatus()
+ .isEqualTo(NOT_FOUND);
}
}
diff --git a/spring-websocket-integration-tests/.mvn/wrapper/maven-wrapper.jar b/spring-websocket-integration-tests/.mvn/wrapper/maven-wrapper.jar
index 2cc7d4a5..c1dd12f1 100644
Binary files a/spring-websocket-integration-tests/.mvn/wrapper/maven-wrapper.jar and b/spring-websocket-integration-tests/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-websocket-integration-tests/.mvn/wrapper/maven-wrapper.properties b/spring-websocket-integration-tests/.mvn/wrapper/maven-wrapper.properties
index 642d572c..57bb5843 100644
--- a/spring-websocket-integration-tests/.mvn/wrapper/maven-wrapper.properties
+++ b/spring-websocket-integration-tests/.mvn/wrapper/maven-wrapper.properties
@@ -1,2 +1,18 @@
-distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
-wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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
+#
+# http://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.
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.6/apache-maven-3.8.6-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar
diff --git a/spring-websocket-integration-tests/README.md b/spring-websocket-integration-tests/README.md
index a684cca6..682493aa 100644
--- a/spring-websocket-integration-tests/README.md
+++ b/spring-websocket-integration-tests/README.md
@@ -4,4 +4,4 @@ Steps to run this project:
1. Clone this Git repository
2. Navigate to the folder `spring-websocket-integration-tests`
-3. Run `mvn test`
+3. Run all tests with `./mvnw test`
diff --git a/spring-websocket-integration-tests/mvnw b/spring-websocket-integration-tests/mvnw
index 3c8a5537..5643201c 100755
--- a/spring-websocket-integration-tests/mvnw
+++ b/spring-websocket-integration-tests/mvnw
@@ -8,7 +8,7 @@
# "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
+# http://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
@@ -34,135 +34,132 @@
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
-if [ -z "$MAVEN_SKIP_RC" ]; then
+if [ -z "$MAVEN_SKIP_RC" ] ; then
- if [ -f /etc/mavenrc ]; then
+ if [ -f /usr/local/etc/mavenrc ] ; then
+ . /usr/local/etc/mavenrc
+ fi
+
+ if [ -f /etc/mavenrc ] ; then
. /etc/mavenrc
fi
- if [ -f "$HOME/.mavenrc" ]; then
+ if [ -f "$HOME/.mavenrc" ] ; then
. "$HOME/.mavenrc"
fi
fi
# OS specific support. $var _must_ be set to either true or false.
-cygwin=false
-darwin=false
+cygwin=false;
+darwin=false;
mingw=false
-case "$(uname)" in
-CYGWIN*) cygwin=true ;;
-MINGW*) mingw=true ;;
-Darwin*)
- darwin=true
- # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
- # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
- if [ -z "$JAVA_HOME" ]; then
- if [ -x "/usr/libexec/java_home" ]; then
- export JAVA_HOME="$(/usr/libexec/java_home)"
- else
- export JAVA_HOME="/Library/Java/Home"
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ export JAVA_HOME="`/usr/libexec/java_home`"
+ else
+ export JAVA_HOME="/Library/Java/Home"
+ fi
fi
- fi
- ;;
+ ;;
esac
-if [ -z "$JAVA_HOME" ]; then
- if [ -r /etc/gentoo-release ]; then
- JAVA_HOME=$(java-config --jre-home)
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=`java-config --jre-home`
fi
fi
-if [ -z "$M2_HOME" ]; then
+if [ -z "$M2_HOME" ] ; then
## resolve links - $0 may be a link to maven's home
PRG="$0"
# need this for relative symlinks
- while [ -h "$PRG" ]; do
- ls=$(ls -ld "$PRG")
- link=$(expr "$ls" : '.*-> \(.*\)$')
- if expr "$link" : '/.*' >/dev/null; then
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
- PRG="$(dirname "$PRG")/$link"
+ PRG="`dirname "$PRG"`/$link"
fi
done
- saveddir=$(pwd)
+ saveddir=`pwd`
- M2_HOME=$(dirname "$PRG")/..
+ M2_HOME=`dirname "$PRG"`/..
# make it fully qualified
- M2_HOME=$(cd "$M2_HOME" && pwd)
+ M2_HOME=`cd "$M2_HOME" && pwd`
cd "$saveddir"
# echo Using m2 at $M2_HOME
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
-if $cygwin; then
+if $cygwin ; then
[ -n "$M2_HOME" ] &&
- M2_HOME=$(cygpath --unix "$M2_HOME")
+ M2_HOME=`cygpath --unix "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
- JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
+ JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
- CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
+ CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
fi
# For Mingw, ensure paths are in UNIX format before anything is touched
-if $mingw; then
+if $mingw ; then
[ -n "$M2_HOME" ] &&
- M2_HOME="$( (
- cd "$M2_HOME"
- pwd
- ))"
+ M2_HOME="`(cd "$M2_HOME"; pwd)`"
[ -n "$JAVA_HOME" ] &&
- JAVA_HOME="$( (
- cd "$JAVA_HOME"
- pwd
- ))"
+ JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
fi
if [ -z "$JAVA_HOME" ]; then
- javaExecutable="$(which javac)"
- if [ -n "$javaExecutable" ] && ! [ "$(expr \"$javaExecutable\" : '\([^ ]*\)')" = "no" ]; then
+ javaExecutable="`which javac`"
+ if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
# readlink(1) is not available as standard on Solaris 10.
- readLink=$(which readlink)
- if [ ! $(expr "$readLink" : '\([^ ]*\)') = "no" ]; then
- if $darwin; then
- javaHome="$(dirname \"$javaExecutable\")"
- javaExecutable="$(cd \"$javaHome\" && pwd -P)/javac"
+ readLink=`which readlink`
+ if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+ if $darwin ; then
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
else
- javaExecutable="$(readlink -f \"$javaExecutable\")"
+ javaExecutable="`readlink -f \"$javaExecutable\"`"
fi
- javaHome="$(dirname \"$javaExecutable\")"
- javaHome=$(expr "$javaHome" : '\(.*\)/bin')
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaHome=`expr "$javaHome" : '\(.*\)/bin'`
JAVA_HOME="$javaHome"
export JAVA_HOME
fi
fi
fi
-if [ -z "$JAVACMD" ]; then
- if [ -n "$JAVA_HOME" ]; then
- if [ -x "$JAVA_HOME/jre/sh/java" ]; then
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
- JAVACMD="$(which java)"
+ JAVACMD="`\\unset -f command; \\command -v java`"
fi
fi
-if [ ! -x "$JAVACMD" ]; then
+if [ ! -x "$JAVACMD" ] ; then
echo "Error: JAVA_HOME is not defined correctly." >&2
echo " We cannot execute $JAVACMD" >&2
exit 1
fi
-if [ -z "$JAVA_HOME" ]; then
+if [ -z "$JAVA_HOME" ] ; then
echo "Warning: JAVA_HOME environment variable is not set."
fi
@@ -172,24 +169,22 @@ CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
- if [ -z "$1" ]; then
+ if [ -z "$1" ]
+ then
echo "Path not specified to find_maven_basedir"
return 1
fi
basedir="$1"
wdir="$1"
- while [ "$wdir" != '/' ]; do
- if [ -d "$wdir"/.mvn ]; then
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
basedir=$wdir
break
fi
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
if [ -d "${wdir}" ]; then
- wdir=$(
- cd "$wdir/.."
- pwd
- )
+ wdir=`cd "$wdir/.."; pwd`
fi
# end of workaround
done
@@ -199,13 +194,13 @@ find_maven_basedir() {
# concatenates all lines of a file
concat_lines() {
if [ -f "$1" ]; then
- echo "$(tr -s '\n' ' ' <"$1")"
+ echo "$(tr -s '\n' ' ' < "$1")"
fi
}
-BASE_DIR=$(find_maven_basedir "$(pwd)")
+BASE_DIR=`find_maven_basedir "$(pwd)"`
if [ -z "$BASE_DIR" ]; then
- exit 1
+ exit 1;
fi
##########################################################################################
@@ -213,78 +208,75 @@ fi
# This allows using the maven wrapper in projects that prohibit checking in binary data.
##########################################################################################
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
- if [ "$MVNW_VERBOSE" = true ]; then
- echo "Found .mvn/wrapper/maven-wrapper.jar"
- fi
-else
- if [ "$MVNW_VERBOSE" = true ]; then
- echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
- fi
- if [ -n "$MVNW_REPOURL" ]; then
- jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
- else
- jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
- fi
- while IFS="=" read key value; do
- case "$key" in wrapperUrl)
- jarUrl="$value"
- break
- ;;
- esac
- done <"$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
- if [ "$MVNW_VERBOSE" = true ]; then
- echo "Downloading from: $jarUrl"
- fi
- wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
- if $cygwin; then
- wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
- fi
-
- if command -v wget >/dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
- echo "Found wget ... using wget"
- fi
- if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
- wget "$jarUrl" -O "$wrapperJarPath"
- else
- wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
+ echo "Found .mvn/wrapper/maven-wrapper.jar"
fi
- elif command -v curl >/dev/null; then
+else
if [ "$MVNW_VERBOSE" = true ]; then
- echo "Found curl ... using curl"
+ echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
fi
- if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
- curl -o "$wrapperJarPath" "$jarUrl" -f
+ if [ -n "$MVNW_REPOURL" ]; then
+ jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
else
- curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
+ jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
fi
-
- else
+ while IFS="=" read key value; do
+ case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
+ esac
+ done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
if [ "$MVNW_VERBOSE" = true ]; then
- echo "Falling back to using Java to download"
+ echo "Downloading from: $jarUrl"
fi
- javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
- # For Cygwin, switch paths to Windows format before running javac
+ wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
if $cygwin; then
- javaClass=$(cygpath --path --windows "$javaClass")
+ wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
fi
- if [ -e "$javaClass" ]; then
- if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+
+ if command -v wget > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
- echo " - Compiling MavenWrapperDownloader.java ..."
+ echo "Found wget ... using wget"
fi
- # Compiling the Java class
- ("$JAVA_HOME/bin/javac" "$javaClass")
- fi
- if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
- # Running the downloader
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ else
+ wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ fi
+ elif command -v curl > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
- echo " - Running MavenWrapperDownloader.java ..."
+ echo "Found curl ... using curl"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl -o "$wrapperJarPath" "$jarUrl" -f
+ else
+ curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
+ fi
+
+ else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Falling back to using Java to download"
+ fi
+ javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaClass=`cygpath --path --windows "$javaClass"`
+ fi
+ if [ -e "$javaClass" ]; then
+ if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Compiling MavenWrapperDownloader.java ..."
+ fi
+ # Compiling the Java class
+ ("$JAVA_HOME/bin/javac" "$javaClass")
+ fi
+ if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ # Running the downloader
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Running MavenWrapperDownloader.java ..."
+ fi
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+ fi
fi
- ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
- fi
fi
- fi
fi
##########################################################################################
# End of extension
@@ -299,13 +291,13 @@ MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
[ -n "$M2_HOME" ] &&
- M2_HOME=$(cygpath --path --windows "$M2_HOME")
+ M2_HOME=`cygpath --path --windows "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
- JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
+ JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
- CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
+ CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
- MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
+ MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
fi
# Provide a "standardized" way to retrieve the CLI args that will
@@ -317,6 +309,8 @@ WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
exec "$JAVACMD" \
$MAVEN_OPTS \
+ $MAVEN_DEBUG_OPTS \
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
- "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ "-Dmaven.home=${M2_HOME}" \
+ "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/spring-websocket-integration-tests/mvnw.cmd b/spring-websocket-integration-tests/mvnw.cmd
index c8d43372..8a15b7f3 100644
--- a/spring-websocket-integration-tests/mvnw.cmd
+++ b/spring-websocket-integration-tests/mvnw.cmd
@@ -7,7 +7,7 @@
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
-@REM https://www.apache.org/licenses/LICENSE-2.0
+@REM http://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@@ -46,8 +46,8 @@ if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
-if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
-if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
+if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
+if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
:skipRcPre
@setlocal
@@ -120,9 +120,9 @@ SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
-set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
-FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
)
@@ -134,7 +134,7 @@ if exist %WRAPPER_JAR% (
)
) else (
if not "%MVNW_REPOURL%" == "" (
- SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
)
if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
@@ -158,7 +158,13 @@ if exist %WRAPPER_JAR% (
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*
-%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+%MAVEN_JAVA_EXE% ^
+ %JVM_CONFIG_MAVEN_PROPS% ^
+ %MAVEN_OPTS% ^
+ %MAVEN_DEBUG_OPTS% ^
+ -classpath %WRAPPER_JAR% ^
+ "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
+ %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
@@ -168,15 +174,15 @@ set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
-if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
+if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
-if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
-if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
+if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
+if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
-if "%MAVEN_BATCH_PAUSE%" == "on" pause
+if "%MAVEN_BATCH_PAUSE%"=="on" pause
-if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
+if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
-exit /B %ERROR_CODE%
+cmd /C exit /B %ERROR_CODE%
diff --git a/spring-websocket-integration-tests/pom.xml b/spring-websocket-integration-tests/pom.xml
index 3722d5df..dfd35169 100644
--- a/spring-websocket-integration-tests/pom.xml
+++ b/spring-websocket-integration-tests/pom.xml
@@ -4,22 +4,17 @@
4.0.0
- org.springframework.boot
- spring-boot-starter-parent
- 2.3.0.RELEASE
-
+ de.rieckpil.blog
+ blog-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
- de.rieckpil.blog
spring-websocket-integration-tests
0.0.1-SNAPSHOT
spring-websocket-integration-tests
Demo project for Spring Boot
-
- 11
-
-
org.springframework.boot
@@ -29,21 +24,6 @@
org.springframework.boot
spring-boot-starter-test
test
-
-
- org.junit.vintage
- junit-vintage-engine
-
-
-
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
-
-
diff --git a/spring-websocket-integration-tests/src/main/java/de/rieckpil/blog/Application.java b/spring-websocket-integration-tests/src/main/java/de/rieckpil/blog/Application.java
index bd5e4c56..6511f3c1 100644
--- a/spring-websocket-integration-tests/src/main/java/de/rieckpil/blog/Application.java
+++ b/spring-websocket-integration-tests/src/main/java/de/rieckpil/blog/Application.java
@@ -9,5 +9,4 @@ public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
-
}
diff --git a/spring-websocket-integration-tests/src/main/java/de/rieckpil/blog/GreetingController.java b/spring-websocket-integration-tests/src/main/java/de/rieckpil/blog/GreetingController.java
index 860e09db..d7dab440 100644
--- a/spring-websocket-integration-tests/src/main/java/de/rieckpil/blog/GreetingController.java
+++ b/spring-websocket-integration-tests/src/main/java/de/rieckpil/blog/GreetingController.java
@@ -1,5 +1,7 @@
package de.rieckpil.blog;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.annotation.SubscribeMapping;
@@ -8,10 +10,12 @@
@Controller
public class GreetingController {
+ private static final Logger LOG = LoggerFactory.getLogger(GreetingController.class);
+
@MessageMapping("/welcome")
@SendTo("/topic/greetings")
public String greeting(String payload) {
- System.out.println("Generating new greeting message for " + payload);
+ LOG.info("Generating new greeting message for {}", payload);
return "Hello, " + payload + "!";
}
@@ -21,5 +25,4 @@ public Message sendWelcomeMessageOnSubscription() {
welcomeMessage.setMessage("Hello World!");
return welcomeMessage;
}
-
}
diff --git a/spring-websocket-integration-tests/src/main/java/de/rieckpil/blog/Message.java b/spring-websocket-integration-tests/src/main/java/de/rieckpil/blog/Message.java
index 9c5ec264..fbd78751 100644
--- a/spring-websocket-integration-tests/src/main/java/de/rieckpil/blog/Message.java
+++ b/spring-websocket-integration-tests/src/main/java/de/rieckpil/blog/Message.java
@@ -14,8 +14,6 @@ public void setMessage(String message) {
@Override
public String toString() {
- return "Message{" +
- "message='" + message + '\'' +
- '}';
+ return "Message{" + "message='" + message + '\'' + '}';
}
}
diff --git a/spring-websocket-integration-tests/src/main/java/de/rieckpil/blog/WebSocketConfig.java b/spring-websocket-integration-tests/src/main/java/de/rieckpil/blog/WebSocketConfig.java
index b8f33741..96baa008 100644
--- a/spring-websocket-integration-tests/src/main/java/de/rieckpil/blog/WebSocketConfig.java
+++ b/spring-websocket-integration-tests/src/main/java/de/rieckpil/blog/WebSocketConfig.java
@@ -18,8 +18,6 @@ public void configureMessageBroker(MessageBrokerRegistry config) {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
- registry.addEndpoint("/ws-endpoint")
- .withSockJS();
+ registry.addEndpoint("/ws-endpoint").withSockJS();
}
-
}
diff --git a/spring-websocket-integration-tests/src/test/java/de/rieckpil/blog/GreetingControllerTest.java b/spring-websocket-integration-tests/src/test/java/de/rieckpil/blog/GreetingControllerTest.java
index 1e4fbf8f..77f76f2c 100644
--- a/spring-websocket-integration-tests/src/test/java/de/rieckpil/blog/GreetingControllerTest.java
+++ b/spring-websocket-integration-tests/src/test/java/de/rieckpil/blog/GreetingControllerTest.java
@@ -1,9 +1,16 @@
package de.rieckpil.blog;
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.awaitility.Awaitility.await;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.lang.reflect.Type;
+import java.util.List;
+import java.util.concurrent.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.boot.web.server.LocalServerPort;
+import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.messaging.converter.MappingJackson2MessageConverter;
import org.springframework.messaging.converter.StringMessageConverter;
import org.springframework.messaging.simp.stomp.StompFrameHandler;
@@ -15,89 +22,84 @@
import org.springframework.web.socket.sockjs.client.SockJsClient;
import org.springframework.web.socket.sockjs.client.WebSocketTransport;
-import java.lang.reflect.Type;
-import java.util.List;
-import java.util.concurrent.*;
-
-import static java.util.concurrent.TimeUnit.SECONDS;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.fail;
-
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class GreetingControllerTest {
- @LocalServerPort
- private Integer port;
+ @LocalServerPort private Integer port;
private WebSocketStompClient webSocketStompClient;
@BeforeEach
- public void setup() {
- this.webSocketStompClient = new WebSocketStompClient(new SockJsClient(
- List.of(new WebSocketTransport(new StandardWebSocketClient()))));
+ void setup() {
+ this.webSocketStompClient =
+ new WebSocketStompClient(
+ new SockJsClient(List.of(new WebSocketTransport(new StandardWebSocketClient()))));
}
@Test
- public void verifyGreetingIsReceived() throws Exception {
+ void verifyGreetingIsReceived() throws Exception {
- BlockingQueue blockingQueue = new ArrayBlockingQueue(1);
+ BlockingQueue blockingQueue = new ArrayBlockingQueue<>(1);
webSocketStompClient.setMessageConverter(new StringMessageConverter());
- StompSession session = webSocketStompClient
- .connect(getWsPath(), new StompSessionHandlerAdapter() {})
- .get(1, SECONDS);
+ StompSession session =
+ webSocketStompClient
+ .connect(getWsPath(), new StompSessionHandlerAdapter() {})
+ .get(1, SECONDS);
- session.subscribe("/topic/greetings", new StompFrameHandler() {
+ session.subscribe(
+ "/topic/greetings",
+ new StompFrameHandler() {
- @Override
- public Type getPayloadType(StompHeaders headers) {
- return String.class;
- }
+ @Override
+ public Type getPayloadType(StompHeaders headers) {
+ return String.class;
+ }
- @Override
- public void handleFrame(StompHeaders headers, Object payload) {
- System.out.println("Received message: " + payload);
- blockingQueue.add((String) payload);
- }
- });
+ @Override
+ public void handleFrame(StompHeaders headers, Object payload) {
+ blockingQueue.add((String) payload);
+ }
+ });
session.send("/app/welcome", "Mike");
- assertEquals("Hello, Mike!", blockingQueue.poll(1, SECONDS));
+ await()
+ .atMost(1, SECONDS)
+ .untilAsserted(() -> assertEquals("Hello, Mike!", blockingQueue.poll()));
}
@Test
- public void verifyWelcomeMessageIsSent() throws Exception {
+ void verifyWelcomeMessageIsSent() throws Exception {
CountDownLatch latch = new CountDownLatch(1);
webSocketStompClient.setMessageConverter(new MappingJackson2MessageConverter());
- StompSession session = webSocketStompClient
- .connect(getWsPath(), new StompSessionHandlerAdapter() {
- })
- .get(1, SECONDS);
+ StompSession session =
+ webSocketStompClient
+ .connect(getWsPath(), new StompSessionHandlerAdapter() {})
+ .get(1, SECONDS);
- session.subscribe("/app/chat", new StompFrameHandler() {
+ session.subscribe(
+ "/app/chat",
+ new StompFrameHandler() {
- @Override
- public Type getPayloadType(StompHeaders headers) {
- return Message.class;
- }
+ @Override
+ public Type getPayloadType(StompHeaders headers) {
+ return Message.class;
+ }
- @Override
- public void handleFrame(StompHeaders headers, Object payload) {
- latch.countDown();
- }
- });
+ @Override
+ public void handleFrame(StompHeaders headers, Object payload) {
+ latch.countDown();
+ }
+ });
- if (!latch.await(1, TimeUnit.SECONDS)) {
- fail("Message not received");
- }
+ await().atMost(1, SECONDS).untilAsserted(() -> assertEquals(0, latch.getCount()));
}
private String getWsPath() {
return String.format("ws://localhost:%d/ws-endpoint", port);
}
}
-
diff --git a/test-java-http-clients/pom.xml b/test-java-http-clients/pom.xml
index 543ff624..ba6a3762 100644
--- a/test-java-http-clients/pom.xml
+++ b/test-java-http-clients/pom.xml
@@ -19,7 +19,7 @@
org.apache.httpcomponents
httpclient
- 4.5.13
+ 4.5.14
com.squareup.okhttp3
@@ -29,7 +29,7 @@
com.fasterxml.jackson.core
jackson-databind
- 2.12.0
+ 2.17.1
diff --git a/testcontainers-introduction/.gitignore b/testcontainers-introduction/.gitignore
new file mode 100644
index 00000000..a2a3040a
--- /dev/null
+++ b/testcontainers-introduction/.gitignore
@@ -0,0 +1,31 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**
+!**/src/test/**
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+
+### VS Code ###
+.vscode/
diff --git a/testcontainers-introduction/.mvn/wrapper/maven-wrapper.jar b/testcontainers-introduction/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 00000000..c1dd12f1
Binary files /dev/null and b/testcontainers-introduction/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/testcontainers-introduction/.mvn/wrapper/maven-wrapper.properties b/testcontainers-introduction/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 00000000..50949db0
--- /dev/null
+++ b/testcontainers-introduction/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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
+#
+# http://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.
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.6/apache-maven-3.8.6-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar
diff --git a/testcontainers-introduction/README.md b/testcontainers-introduction/README.md
new file mode 100644
index 00000000..5425d365
--- /dev/null
+++ b/testcontainers-introduction/README.md
@@ -0,0 +1 @@
+# Testcontainers Introduction
diff --git a/testcontainers-introduction/mvnw b/testcontainers-introduction/mvnw
new file mode 100755
index 00000000..5643201c
--- /dev/null
+++ b/testcontainers-introduction/mvnw
@@ -0,0 +1,316 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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
+#
+# http://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.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# M2_HOME - location of maven2's installed home dir
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /usr/local/etc/mavenrc ] ; then
+ . /usr/local/etc/mavenrc
+ fi
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ export JAVA_HOME="`/usr/libexec/java_home`"
+ else
+ export JAVA_HOME="/Library/Java/Home"
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=`java-config --jre-home`
+ fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+ ## resolve links - $0 may be a link to maven's home
+ PRG="$0"
+
+ # need this for relative symlinks
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG="`dirname "$PRG"`/$link"
+ fi
+ done
+
+ saveddir=`pwd`
+
+ M2_HOME=`dirname "$PRG"`/..
+
+ # make it fully qualified
+ M2_HOME=`cd "$M2_HOME" && pwd`
+
+ cd "$saveddir"
+ # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --unix "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME="`(cd "$M2_HOME"; pwd)`"
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="`which javac`"
+ if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=`which readlink`
+ if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+ if $darwin ; then
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+ else
+ javaExecutable="`readlink -f \"$javaExecutable\"`"
+ fi
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="`\\unset -f command; \\command -v java`"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=`cd "$wdir/.."; pwd`
+ fi
+ # end of workaround
+ done
+ echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ echo "$(tr -s '\n' ' ' < "$1")"
+ fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found .mvn/wrapper/maven-wrapper.jar"
+ fi
+else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+ fi
+ if [ -n "$MVNW_REPOURL" ]; then
+ jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+ else
+ jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+ fi
+ while IFS="=" read key value; do
+ case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
+ esac
+ done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Downloading from: $jarUrl"
+ fi
+ wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+ if $cygwin; then
+ wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
+ fi
+
+ if command -v wget > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found wget ... using wget"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ else
+ wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ fi
+ elif command -v curl > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found curl ... using curl"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl -o "$wrapperJarPath" "$jarUrl" -f
+ else
+ curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
+ fi
+
+ else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Falling back to using Java to download"
+ fi
+ javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaClass=`cygpath --path --windows "$javaClass"`
+ fi
+ if [ -e "$javaClass" ]; then
+ if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Compiling MavenWrapperDownloader.java ..."
+ fi
+ # Compiling the Java class
+ ("$JAVA_HOME/bin/javac" "$javaClass")
+ fi
+ if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ # Running the downloader
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Running MavenWrapperDownloader.java ..."
+ fi
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+if [ "$MVNW_VERBOSE" = true ]; then
+ echo $MAVEN_PROJECTBASEDIR
+fi
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --path --windows "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ $MAVEN_DEBUG_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.home=${M2_HOME}" \
+ "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/testcontainers-introduction/mvnw.cmd b/testcontainers-introduction/mvnw.cmd
new file mode 100644
index 00000000..8a15b7f3
--- /dev/null
+++ b/testcontainers-introduction/mvnw.cmd
@@ -0,0 +1,188 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
+if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Found %WRAPPER_JAR%
+ )
+) else (
+ if not "%MVNW_REPOURL%" == "" (
+ SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+ )
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %DOWNLOAD_URL%
+ )
+
+ powershell -Command "&{"^
+ "$webclient = new-object System.Net.WebClient;"^
+ "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+ "}"^
+ "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
+ "}"
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Finished downloading %WRAPPER_JAR%
+ )
+)
+@REM End of extension
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% ^
+ %JVM_CONFIG_MAVEN_PROPS% ^
+ %MAVEN_OPTS% ^
+ %MAVEN_DEBUG_OPTS% ^
+ -classpath %WRAPPER_JAR% ^
+ "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
+ %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
+if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%"=="on" pause
+
+if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
+
+cmd /C exit /B %ERROR_CODE%
diff --git a/testcontainers-introduction/pom.xml b/testcontainers-introduction/pom.xml
new file mode 100644
index 00000000..120226d9
--- /dev/null
+++ b/testcontainers-introduction/pom.xml
@@ -0,0 +1,139 @@
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.7.0
+
+
+
+ de.rieckpil
+ testcontainers-introduction
+ 1.0-SNAPSHOT
+
+
+ 17
+ 1.17.3
+
+
+
+
+
+ com.google.cloud
+ libraries-bom
+ 26.1.1
+ pom
+ import
+
+
+ org.testcontainers
+ testcontainers-bom
+ ${testcontainers.version}
+ pom
+ import
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.postgresql
+ postgresql
+ runtime
+
+
+ com.google.cloud
+ google-cloud-pubsub
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.mock-server
+ mockserver-client-java-no-dependencies
+ 5.14.0
+ test
+
+
+ com.codeborne
+ selenide
+ 6.19.1
+ test
+
+
+ org.awaitility
+ awaitility
+ test
+
+
+ org.testcontainers
+ postgresql
+ test
+
+
+ org.testcontainers
+ mockserver
+ test
+
+
+ org.testcontainers
+ junit-jupiter
+ test
+
+
+ org.testcontainers
+ selenium
+ test
+
+
+ org.testcontainers
+ gcloud
+ test
+
+
+ org.testcontainers
+ testcontainers
+ 1.17.3
+ test
+
+
+
+
+ testcontainers-introduction
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ maven-compiler-plugin
+ 3.8.1
+
+
+ maven-surefire-plugin
+ 3.0.0-M5
+
+
+ maven-failsafe-plugin
+ 3.0.0-M5
+
+
+
+ integration-test
+ verify
+
+
+
+
+
+
+
diff --git a/testcontainers-introduction/src/main/java/de/rieckpil/blog/Application.java b/testcontainers-introduction/src/main/java/de/rieckpil/blog/Application.java
new file mode 100644
index 00000000..6511f3c1
--- /dev/null
+++ b/testcontainers-introduction/src/main/java/de/rieckpil/blog/Application.java
@@ -0,0 +1,12 @@
+package de.rieckpil.blog;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+}
diff --git a/testcontainers-introduction/src/test/java/de/rieckpil/blog/CommandExecutingExampleTest.java b/testcontainers-introduction/src/test/java/de/rieckpil/blog/CommandExecutingExampleTest.java
new file mode 100644
index 00000000..a57210cb
--- /dev/null
+++ b/testcontainers-introduction/src/test/java/de/rieckpil/blog/CommandExecutingExampleTest.java
@@ -0,0 +1,33 @@
+package de.rieckpil.blog;
+
+import org.junit.jupiter.api.Test;
+import org.testcontainers.containers.Container.ExecResult;
+import org.testcontainers.containers.PostgreSQLContainer;
+import org.testcontainers.junit.jupiter.Container;
+import org.testcontainers.junit.jupiter.Testcontainers;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+@Testcontainers
+class CommandExecutingExampleTest {
+
+ @Container
+ static PostgreSQLContainer> database =
+ new PostgreSQLContainer<>("postgres:14.0")
+ .withDatabaseName("test")
+ .withUsername("duke")
+ .withPassword("s3cret");
+
+ @Test
+ void shouldExecuteCommand() throws Exception {
+ ExecResult commandResult = database.execInContainer("ls", "-al", "/");
+
+ String stdout = commandResult.getStdout();
+ int exitCode = commandResult.getExitCode();
+
+ System.out.println(stdout);
+
+ assertThat(stdout).contains("root");
+ assertThat(exitCode).isZero();
+ }
+}
diff --git a/testcontainers-introduction/src/test/java/de/rieckpil/blog/DatabaseExampleTest.java b/testcontainers-introduction/src/test/java/de/rieckpil/blog/DatabaseExampleTest.java
new file mode 100644
index 00000000..339b27a0
--- /dev/null
+++ b/testcontainers-introduction/src/test/java/de/rieckpil/blog/DatabaseExampleTest.java
@@ -0,0 +1,32 @@
+package de.rieckpil.blog;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+
+import org.junit.jupiter.api.Test;
+import org.testcontainers.containers.PostgreSQLContainer;
+import org.testcontainers.junit.jupiter.Container;
+import org.testcontainers.junit.jupiter.Testcontainers;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+@Testcontainers
+class DatabaseExampleTest {
+
+ @Container
+ static PostgreSQLContainer> database =
+ new PostgreSQLContainer<>("postgres:14.0")
+ .withDatabaseName("test")
+ .withUsername("duke")
+ .withPassword("s3cret");
+
+ @Test
+ void shouldConnectToDatabase() throws Exception {
+ try (Connection connection = DriverManager
+ .getConnection(database.getJdbcUrl(), database.getUsername(), database.getPassword())) {
+
+ assertThat(connection.getMetaData().getDatabaseProductName())
+ .isEqualTo("PostgreSQL");
+ }
+ }
+}
diff --git a/testcontainers-introduction/src/test/java/de/rieckpil/blog/FileMountingExampleTest.java b/testcontainers-introduction/src/test/java/de/rieckpil/blog/FileMountingExampleTest.java
new file mode 100644
index 00000000..926e5946
--- /dev/null
+++ b/testcontainers-introduction/src/test/java/de/rieckpil/blog/FileMountingExampleTest.java
@@ -0,0 +1,41 @@
+package de.rieckpil.blog;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.Statement;
+
+import org.junit.jupiter.api.Test;
+import org.testcontainers.containers.BindMode;
+import org.testcontainers.containers.PostgreSQLContainer;
+import org.testcontainers.junit.jupiter.Container;
+import org.testcontainers.junit.jupiter.Testcontainers;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+@Testcontainers
+class FileMountingExampleTest {
+
+ @Container
+ static PostgreSQLContainer> database =
+ new PostgreSQLContainer<>("postgres:14.0")
+ .withDatabaseName("test")
+ .withUsername("duke")
+ .withPassword("s3cret")
+ .withClasspathResourceMapping("/database-init", "/docker-entrypoint-initdb.d/", BindMode.READ_ONLY);
+
+ @Test
+ void shouldConnectToDatabase() throws Exception {
+ try (Connection connection = DriverManager
+ .getConnection(database.getJdbcUrl(), database.getUsername(), database.getPassword())) {
+
+ Statement stmt = connection.createStatement();
+ ResultSet resultSet = stmt.executeQuery("SELECT * FROM orders");
+
+ while (resultSet.next()) {
+ assertThat(resultSet.getString(2))
+ .isEqualTo("XYZ123");
+ }
+ }
+ }
+}
diff --git a/testcontainers-introduction/src/test/java/de/rieckpil/blog/GenericContainerExampleTest.java b/testcontainers-introduction/src/test/java/de/rieckpil/blog/GenericContainerExampleTest.java
new file mode 100644
index 00000000..9676546b
--- /dev/null
+++ b/testcontainers-introduction/src/test/java/de/rieckpil/blog/GenericContainerExampleTest.java
@@ -0,0 +1,25 @@
+package de.rieckpil.blog;
+
+
+import org.junit.jupiter.api.Test;
+import org.testcontainers.containers.GenericContainer;
+import org.testcontainers.utility.DockerImageName;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class GenericContainerExampleTest {
+
+ static GenericContainer> nginx =
+ new GenericContainer<>(DockerImageName.parse("nginx:1.23.1"));
+
+ @Test
+ void shouldStartContainer() {
+ nginx.start();
+
+ // container is running
+ assertThat(nginx.isRunning())
+ .isTrue();
+
+ nginx.stop();
+ }
+}
diff --git a/testcontainers-introduction/src/test/java/de/rieckpil/blog/GenericContainerInitializedExampleTest.java b/testcontainers-introduction/src/test/java/de/rieckpil/blog/GenericContainerInitializedExampleTest.java
new file mode 100644
index 00000000..4a55c743
--- /dev/null
+++ b/testcontainers-introduction/src/test/java/de/rieckpil/blog/GenericContainerInitializedExampleTest.java
@@ -0,0 +1,39 @@
+package de.rieckpil.blog;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+
+import org.junit.jupiter.api.Test;
+import org.testcontainers.containers.GenericContainer;
+import org.testcontainers.containers.wait.strategy.Wait;
+import org.testcontainers.junit.jupiter.Container;
+import org.testcontainers.junit.jupiter.Testcontainers;
+import org.testcontainers.utility.DockerImageName;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+ @Testcontainers
+ class GenericContainerInitializedExampleTest {
+
+ @Container
+ static GenericContainer> database =
+ new GenericContainer<>(DockerImageName.parse("postgres:14.0"))
+ .withEnv("POSTGRES_PASSWORD", "secret")
+ .withEnv("POSTGRES_USER", "duke")
+ .withEnv("POSTGRES_DB", "test")
+ .withExposedPorts(5432)
+ .waitingFor(Wait.forListeningPort());
+
+ @Test
+ void shouldConnectToDatabase() throws Exception {
+ try (Connection connection = DriverManager
+ .getConnection("jdbc:postgresql://localhost:" +
+ database.getMappedPort(5432) + "/test", "duke", "secret")) {
+
+ assertThat(connection.getMetaData().getDatabaseProductName())
+ .isEqualTo("PostgreSQL");
+ }
+ }
+ }
+
+
diff --git a/testcontainers-introduction/src/test/java/de/rieckpil/blog/ManualLifecycleExampleTest.java b/testcontainers-introduction/src/test/java/de/rieckpil/blog/ManualLifecycleExampleTest.java
new file mode 100644
index 00000000..ace7fd77
--- /dev/null
+++ b/testcontainers-introduction/src/test/java/de/rieckpil/blog/ManualLifecycleExampleTest.java
@@ -0,0 +1,33 @@
+package de.rieckpil.blog;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+
+import org.junit.jupiter.api.Test;
+import org.testcontainers.containers.PostgreSQLContainer;
+import org.testcontainers.junit.jupiter.Container;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class ManualLifecycleExampleTest {
+
+ static PostgreSQLContainer> database = new PostgreSQLContainer<>("postgres:14.0")
+ .withDatabaseName("test")
+ .withUsername("duke")
+ .withPassword("s3cret");
+
+ @Test
+ void shouldConnectToDatabase() throws Exception {
+
+ database.start();
+
+ try (Connection connection = DriverManager
+ .getConnection(database.getJdbcUrl(), database.getUsername(), database.getPassword())) {
+
+ assertThat(connection.getMetaData().getDatabaseProductName())
+ .isEqualTo("PostgreSQL");
+ }
+
+ database.stop();
+ }
+}
diff --git a/testcontainers-introduction/src/test/java/de/rieckpil/blog/MockServerExampleTest.java b/testcontainers-introduction/src/test/java/de/rieckpil/blog/MockServerExampleTest.java
new file mode 100644
index 00000000..1cfe93cf
--- /dev/null
+++ b/testcontainers-introduction/src/test/java/de/rieckpil/blog/MockServerExampleTest.java
@@ -0,0 +1,61 @@
+package de.rieckpil.blog;
+
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.time.Duration;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import org.junit.jupiter.api.Test;
+import org.mockserver.client.MockServerClient;
+import org.mockserver.model.MediaType;
+import org.testcontainers.containers.MockServerContainer;
+import org.testcontainers.junit.jupiter.Container;
+import org.testcontainers.junit.jupiter.Testcontainers;
+import org.testcontainers.utility.DockerImageName;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockserver.model.HttpRequest.request;
+import static org.mockserver.model.HttpResponse.response;
+
+@Testcontainers
+class MockServerExampleTest {
+
+ @Container
+ static MockServerContainer mockServer =
+ new MockServerContainer(DockerImageName.parse("mockserver/mockserver:5.14.0"));
+
+ static final HttpClient httpClient = HttpClient.newBuilder()
+ .version(HttpClient.Version.HTTP_2)
+ .build();
+
+ @Test
+ void shouldStubHttpCall() throws Exception {
+ new MockServerClient(mockServer.getHost(), mockServer.getServerPort())
+ .when(request()
+ .withPath("/orders"))
+ .respond(response()
+ .withBody("""
+ [{
+ "orderId": 42,
+ "customerId": "XYZ1445"
+ }]
+ """, MediaType.APPLICATION_JSON_UTF_8));
+
+ HttpRequest request = HttpRequest.newBuilder()
+ .GET()
+ .uri(URI.create(mockServer.getEndpoint() + "/orders"))
+ .setHeader("Accept", "application/json")
+ .build();
+
+ HttpResponse response = httpClient
+ .send(request, HttpResponse.BodyHandlers.ofString());
+
+ System.out.println("Response: " + response.body());
+
+ assertThat(new ObjectMapper().readValue(response.body(), ArrayNode.class))
+ .hasSize(1);
+ }
+}
diff --git a/testcontainers-introduction/src/test/java/de/rieckpil/blog/PubSubExampleTest.java b/testcontainers-introduction/src/test/java/de/rieckpil/blog/PubSubExampleTest.java
new file mode 100644
index 00000000..61f2c79c
--- /dev/null
+++ b/testcontainers-introduction/src/test/java/de/rieckpil/blog/PubSubExampleTest.java
@@ -0,0 +1,146 @@
+package de.rieckpil.blog;
+
+import java.io.IOException;
+import java.time.Duration;
+
+import com.google.api.gax.core.NoCredentialsProvider;
+import com.google.api.gax.grpc.GrpcTransportChannel;
+import com.google.api.gax.rpc.AlreadyExistsException;
+import com.google.api.gax.rpc.FixedTransportChannelProvider;
+import com.google.api.gax.rpc.TransportChannelProvider;
+import com.google.cloud.pubsub.v1.Publisher;
+import com.google.cloud.pubsub.v1.SubscriptionAdminClient;
+import com.google.cloud.pubsub.v1.SubscriptionAdminSettings;
+import com.google.cloud.pubsub.v1.TopicAdminClient;
+import com.google.cloud.pubsub.v1.TopicAdminSettings;
+import com.google.cloud.pubsub.v1.stub.GrpcSubscriberStub;
+import com.google.cloud.pubsub.v1.stub.SubscriberStub;
+import com.google.cloud.pubsub.v1.stub.SubscriberStubSettings;
+import com.google.protobuf.ByteString;
+import com.google.pubsub.v1.ProjectSubscriptionName;
+import com.google.pubsub.v1.PubsubMessage;
+import com.google.pubsub.v1.PullRequest;
+import com.google.pubsub.v1.PullResponse;
+import com.google.pubsub.v1.PushConfig;
+import com.google.pubsub.v1.TopicName;
+import io.grpc.ManagedChannel;
+import io.grpc.ManagedChannelBuilder;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.testcontainers.containers.PubSubEmulatorContainer;
+import org.testcontainers.junit.jupiter.Container;
+import org.testcontainers.junit.jupiter.Testcontainers;
+import org.testcontainers.utility.DockerImageName;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.awaitility.Awaitility.await;
+
+@Testcontainers
+class PubSubExampleTest {
+
+ @Container
+ static PubSubEmulatorContainer emulator =
+ new PubSubEmulatorContainer(
+ DockerImageName.parse("gcr.io/google.com/cloudsdktool/cloud-sdk:372.0.0-emulators"));
+
+ static final String PROJECT_ID = "test-project";
+ static final String TOPIC_ID = "sample-topic";
+ static final String SUBSCRIPTION_ID = "sample-subscription";
+
+ @BeforeAll
+ static void setupEmulator() throws Exception {
+ ManagedChannel channel = ManagedChannelBuilder.forTarget(emulator.getEmulatorEndpoint()).usePlaintext().build();
+ TransportChannelProvider channelProvider =
+ FixedTransportChannelProvider.create(GrpcTransportChannel.create(channel));
+ NoCredentialsProvider credentialsProvider = NoCredentialsProvider.create();
+
+ createTopic(TOPIC_ID, channelProvider, credentialsProvider);
+ createSubscription(SUBSCRIPTION_ID, TOPIC_ID, channelProvider, credentialsProvider);
+
+ }
+
+ @Test
+ void shouldPublishAndConsumeMessage() throws Exception {
+
+ Publisher publisher =
+ Publisher.newBuilder(TopicName.of(PROJECT_ID, TOPIC_ID))
+ .setChannelProvider(FixedTransportChannelProvider.create(GrpcTransportChannel.create(ManagedChannelBuilder.forTarget(emulator.getEmulatorEndpoint()).usePlaintext().build())))
+ .setCredentialsProvider(NoCredentialsProvider.create())
+ .build();
+
+ publisher
+ .publish(PubsubMessage.newBuilder().setData(ByteString.copyFromUtf8("Hello World!"))
+ .build());
+
+ SubscriberStubSettings subscriberStubSettings =
+ SubscriberStubSettings.newBuilder()
+ .setTransportChannelProvider(FixedTransportChannelProvider.create(GrpcTransportChannel.create(ManagedChannelBuilder.forTarget(emulator.getEmulatorEndpoint()).usePlaintext().build())))
+ .setCredentialsProvider(NoCredentialsProvider.create())
+ .build();
+
+ SubscriberStub subscriber = GrpcSubscriberStub
+ .create(subscriberStubSettings);
+
+ PullRequest pullRequest =
+ PullRequest.newBuilder()
+ .setMaxMessages(1)
+ .setSubscription(ProjectSubscriptionName.format(PROJECT_ID, SUBSCRIPTION_ID))
+ .build();
+
+ await()
+ .atMost(Duration.ofSeconds(3))
+ .untilAsserted(() -> {
+ PullResponse pullResponse = subscriber.pullCallable().call(pullRequest);
+
+ assertThat(pullResponse.getReceivedMessagesList())
+ .hasSize(1);
+
+ assertThat(pullResponse.getReceivedMessagesList().get(0).getMessage().getData().toStringUtf8())
+ .isEqualTo("Hello World!");
+ });
+ }
+
+ private static void createTopic(
+ String topicId,
+ TransportChannelProvider channelProvider,
+ NoCredentialsProvider credentialsProvider)
+ throws IOException {
+ TopicAdminSettings topicAdminSettings =
+ TopicAdminSettings.newBuilder()
+ .setTransportChannelProvider(channelProvider)
+ .setCredentialsProvider(credentialsProvider)
+ .build();
+ try (TopicAdminClient topicAdminClient = TopicAdminClient.create(topicAdminSettings)) {
+ TopicName topicName = TopicName.of(PROJECT_ID, topicId);
+ topicAdminClient.createTopic(topicName);
+ } catch (AlreadyExistsException e) {
+ // The topic already exists -- OK
+ }
+ }
+
+ private static void createSubscription(
+ String subscriptionId,
+ String topicId,
+ TransportChannelProvider channelProvider,
+ NoCredentialsProvider credentialsProvider)
+ throws IOException {
+ SubscriptionAdminSettings subscriptionAdminSettings =
+ SubscriptionAdminSettings.newBuilder()
+ .setTransportChannelProvider(channelProvider)
+ .setCredentialsProvider(credentialsProvider)
+ .build();
+ SubscriptionAdminClient subscriptionAdminClient =
+ SubscriptionAdminClient.create(subscriptionAdminSettings);
+
+ ProjectSubscriptionName subscriptionName =
+ ProjectSubscriptionName.of(PROJECT_ID, subscriptionId);
+
+ try {
+ subscriptionAdminClient.createSubscription(
+ subscriptionName, TopicName.of(PROJECT_ID, topicId), PushConfig.getDefaultInstance(), 10);
+ } catch (AlreadyExistsException e) {
+ // The subscription already exists -- OK
+ }
+ }
+
+}
diff --git a/testcontainers-introduction/src/test/java/de/rieckpil/blog/SeleniumExampleTest.java b/testcontainers-introduction/src/test/java/de/rieckpil/blog/SeleniumExampleTest.java
new file mode 100644
index 00000000..1817b364
--- /dev/null
+++ b/testcontainers-introduction/src/test/java/de/rieckpil/blog/SeleniumExampleTest.java
@@ -0,0 +1,49 @@
+package de.rieckpil.blog;
+
+import java.io.File;
+
+import com.codeborne.selenide.Configuration;
+import com.codeborne.selenide.WebDriverRunner;
+import org.junit.jupiter.api.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.chrome.ChromeOptions;
+import org.openqa.selenium.remote.RemoteWebDriver;
+import org.testcontainers.containers.BrowserWebDriverContainer;
+import org.testcontainers.junit.jupiter.Container;
+import org.testcontainers.junit.jupiter.Testcontainers;
+
+import static com.codeborne.selenide.Selenide.$;
+import static com.codeborne.selenide.Selenide.open;
+import static com.codeborne.selenide.Selenide.screenshot;
+import static org.assertj.core.api.Assertions.assertThat;
+
+@Testcontainers
+class SeleniumExampleTest {
+
+ @Container
+ static BrowserWebDriverContainer> webDriverContainer =
+ new BrowserWebDriverContainer<>()
+ .withRecordingMode(BrowserWebDriverContainer.VncRecordingMode.RECORD_ALL, new File("./target"))
+ .withCapabilities(new ChromeOptions()
+ .addArguments("--no-sandbox")
+ .addArguments("--disable-dev-shm-usage"));
+
+ @Test
+ void shouldAccessHomePage() {
+ Configuration.timeout = 2000;
+ Configuration.baseUrl = "https://www.extenda.com/";
+ Configuration.reportsFolder = "target/selenide-reports";
+
+ RemoteWebDriver remoteWebDriver = webDriverContainer.getWebDriver();
+ WebDriverRunner.setWebDriver(remoteWebDriver);
+
+ open("/contact-us");
+
+ screenshot("contact-us");
+
+ String h1Text = $(By.tagName("h1")).text();
+
+ assertThat(h1Text)
+ .isNotNull();
+ }
+}
diff --git a/testcontainers-introduction/src/test/resources/database-init/ORDERS_TABLE.sql b/testcontainers-introduction/src/test/resources/database-init/ORDERS_TABLE.sql
new file mode 100644
index 00000000..795709d9
--- /dev/null
+++ b/testcontainers-introduction/src/test/resources/database-init/ORDERS_TABLE.sql
@@ -0,0 +1,7 @@
+CREATE TABLE orders (
+ ID BIGSERIAL PRIMARY KEY,
+ CUSTOMER_ID VARCHAR(255) NOT NULL
+);
+
+INSERT INTO orders (CUSTOMER_ID) VALUES ('XYZ123');
+
diff --git a/testcontainers-introduction/src/test/resources/logback-test.xml b/testcontainers-introduction/src/test/resources/logback-test.xml
new file mode 100644
index 00000000..d61571e3
--- /dev/null
+++ b/testcontainers-introduction/src/test/resources/logback-test.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/testcontainers-reuse-existing-containers/.java-version b/testcontainers-reuse-existing-containers/.java-version
deleted file mode 100644
index 2dbc24b3..00000000
--- a/testcontainers-reuse-existing-containers/.java-version
+++ /dev/null
@@ -1 +0,0 @@
-11.0
diff --git a/testcontainers-reuse-existing-containers/README.md b/testcontainers-reuse-existing-containers/README.md
index 29a272e6..e2959747 100644
--- a/testcontainers-reuse-existing-containers/README.md
+++ b/testcontainers-reuse-existing-containers/README.md
@@ -5,6 +5,7 @@ Steps to run this project:
1. Clone this Git repository
2. Navigate to the folder `testcontainers-reuse-existing-containers`
3. Ensure your Docker engine is running (`docker ps`)
-4. Run all integration tests with `mvn verify`
-5. Ensure the Docker containers for PostgreSQL are still running (one for PostgreSQl 9.6 and one for 10)
-6. Re-run the integration tests. They should finish faster now
+4. Opt-in for the reuse feature inside your `~/.testcontainers.properties` file as explained in the blog psot
+5. Run all integration tests with `mvn verify`
+6. Ensure the Docker containers for PostgreSQL are still running (one for PostgreSQl 13 and one for 10) with `docker ps`
+7. Re-run the integration tests. They should finish faster now
diff --git a/testcontainers-reuse-existing-containers/pom.xml b/testcontainers-reuse-existing-containers/pom.xml
index 21a686d9..29c0b1ad 100644
--- a/testcontainers-reuse-existing-containers/pom.xml
+++ b/testcontainers-reuse-existing-containers/pom.xml
@@ -2,24 +2,19 @@
4.0.0
+
- org.springframework.boot
- spring-boot-starter-parent
- 2.3.0.RELEASE
-
+ de.rieckpil.blog
+ blog-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
- de.rieckpil.blog
testcontainers-reuse-existing-containers
0.0.1-SNAPSHOT
testcontainers-reuse-existing-containers
Reuse existing Containers with Testcontainers
-
- 11
- 1.15.1
-
-
org.springframework.boot
@@ -33,7 +28,10 @@
org.flywaydb
flyway-core
-
+
+ org.flywaydb
+ flyway-database-postgresql
+
org.postgresql
postgresql
@@ -49,35 +47,11 @@
org.springframework.boot
spring-boot-starter-test
test
-
-
- org.junit.vintage
- junit-vintage-engine
-
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
-
- org.apache.maven.plugins
- maven-failsafe-plugin
- 3.0.0-M5
-
-
-
- integration-test
- verify
-
-
-
-
-
+
diff --git a/testcontainers-reuse-existing-containers/src/main/java/de/rieckpil/blog/Application.java b/testcontainers-reuse-existing-containers/src/main/java/de/rieckpil/blog/Application.java
index bd5e4c56..6511f3c1 100644
--- a/testcontainers-reuse-existing-containers/src/main/java/de/rieckpil/blog/Application.java
+++ b/testcontainers-reuse-existing-containers/src/main/java/de/rieckpil/blog/Application.java
@@ -9,5 +9,4 @@ public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
-
}
diff --git a/testcontainers-reuse-existing-containers/src/main/java/de/rieckpil/blog/Todo.java b/testcontainers-reuse-existing-containers/src/main/java/de/rieckpil/blog/Todo.java
index 1f08d3dd..7c40f4a5 100644
--- a/testcontainers-reuse-existing-containers/src/main/java/de/rieckpil/blog/Todo.java
+++ b/testcontainers-reuse-existing-containers/src/main/java/de/rieckpil/blog/Todo.java
@@ -1,6 +1,6 @@
package de.rieckpil.blog;
-import javax.persistence.*;
+import jakarta.persistence.*;
import java.time.LocalDateTime;
@Entity
@@ -17,8 +17,7 @@ public class Todo {
@Column(nullable = false)
private LocalDateTime dueDate;
- public Todo() {
- }
+ public Todo() {}
public Todo(String title, LocalDateTime dueDate) {
this.id = null;
diff --git a/testcontainers-reuse-existing-containers/src/main/java/de/rieckpil/blog/TodoController.java b/testcontainers-reuse-existing-containers/src/main/java/de/rieckpil/blog/TodoController.java
index b26e1a25..865b0ef2 100644
--- a/testcontainers-reuse-existing-containers/src/main/java/de/rieckpil/blog/TodoController.java
+++ b/testcontainers-reuse-existing-containers/src/main/java/de/rieckpil/blog/TodoController.java
@@ -1,11 +1,10 @@
package de.rieckpil.blog;
+import java.util.List;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
-import java.util.List;
-
@RestController
@RequestMapping("/todos")
public class TodoController {
diff --git a/testcontainers-reuse-existing-containers/src/main/java/de/rieckpil/blog/TodoRepository.java b/testcontainers-reuse-existing-containers/src/main/java/de/rieckpil/blog/TodoRepository.java
index 8c13c2c3..407bbf80 100644
--- a/testcontainers-reuse-existing-containers/src/main/java/de/rieckpil/blog/TodoRepository.java
+++ b/testcontainers-reuse-existing-containers/src/main/java/de/rieckpil/blog/TodoRepository.java
@@ -2,5 +2,4 @@
import org.springframework.data.jpa.repository.JpaRepository;
-public interface TodoRepository extends JpaRepository {
-}
+public interface TodoRepository extends JpaRepository {}
diff --git a/testcontainers-reuse-existing-containers/src/test/java/de/rieckpil/blog/ApplicationIT.java b/testcontainers-reuse-existing-containers/src/test/java/de/rieckpil/blog/ApplicationIT.java
index 81e7a50f..de307669 100644
--- a/testcontainers-reuse-existing-containers/src/test/java/de/rieckpil/blog/ApplicationIT.java
+++ b/testcontainers-reuse-existing-containers/src/test/java/de/rieckpil/blog/ApplicationIT.java
@@ -1,28 +1,20 @@
package de.rieckpil.blog;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
import com.fasterxml.jackson.databind.JsonNode;
-import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.ResponseEntity;
-import org.springframework.test.context.DynamicPropertyRegistry;
-import org.springframework.test.context.DynamicPropertySource;
-import org.testcontainers.containers.PostgreSQLContainer;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+class ApplicationIT extends BaseIT {
-class ApplicationIT extends BaseIT{
-
- @Autowired
- private TestRestTemplate testRestTemplate;
+ @Autowired private TestRestTemplate testRestTemplate;
@Test
void contextLoads() {
ResponseEntity result = testRestTemplate.getForEntity("/todos", JsonNode.class);
assertEquals(200, result.getStatusCodeValue());
}
-
}
diff --git a/testcontainers-reuse-existing-containers/src/test/java/de/rieckpil/blog/BaseIT.java b/testcontainers-reuse-existing-containers/src/test/java/de/rieckpil/blog/BaseIT.java
index 82dd1cbc..14d4a5eb 100644
--- a/testcontainers-reuse-existing-containers/src/test/java/de/rieckpil/blog/BaseIT.java
+++ b/testcontainers-reuse-existing-containers/src/test/java/de/rieckpil/blog/BaseIT.java
@@ -1,23 +1,25 @@
package de.rieckpil.blog;
+import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
+
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.containers.PostgreSQLContainer;
-
-import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
+import org.testcontainers.utility.DockerImageName;
@SpringBootTest(webEnvironment = RANDOM_PORT)
public abstract class BaseIT {
- static final PostgreSQLContainer postgreSQLContainer;
+ static final PostgreSQLContainer> postgreSQLContainer;
static {
- postgreSQLContainer = (PostgreSQLContainer) new PostgreSQLContainer()
- .withDatabaseName("test")
- .withUsername("duke")
- .withPassword("s3cret")
- .withReuse(true);
+ postgreSQLContainer =
+ new PostgreSQLContainer<>(DockerImageName.parse("postgres:13"))
+ .withDatabaseName("test")
+ .withUsername("duke")
+ .withPassword("s3cret")
+ .withReuse(true);
postgreSQLContainer.start();
}
@@ -28,5 +30,4 @@ static void datasourceConfig(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.password", postgreSQLContainer::getPassword);
registry.add("spring.datasource.username", postgreSQLContainer::getUsername);
}
-
}
diff --git a/testcontainers-reuse-existing-containers/src/test/java/de/rieckpil/blog/SecondApplicationIT.java b/testcontainers-reuse-existing-containers/src/test/java/de/rieckpil/blog/SecondApplicationIT.java
index c1c4f1e6..2193b80d 100644
--- a/testcontainers-reuse-existing-containers/src/test/java/de/rieckpil/blog/SecondApplicationIT.java
+++ b/testcontainers-reuse-existing-containers/src/test/java/de/rieckpil/blog/SecondApplicationIT.java
@@ -1,32 +1,25 @@
package de.rieckpil.blog;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
import com.fasterxml.jackson.databind.node.ArrayNode;
+import java.time.LocalDateTime;
+import java.util.List;
import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.ResponseEntity;
-import org.springframework.test.context.DynamicPropertyRegistry;
-import org.springframework.test.context.DynamicPropertySource;
-import org.testcontainers.containers.PostgreSQLContainer;
-
-import java.time.LocalDateTime;
-import java.util.List;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
-class SecondApplicationIT extends BaseIT{
+class SecondApplicationIT extends BaseIT {
- @Autowired
- private TestRestTemplate testRestTemplate;
+ @Autowired private TestRestTemplate testRestTemplate;
- @Autowired
- private TodoRepository todoRepository;
+ @Autowired private TodoRepository todoRepository;
@AfterEach
public void cleanup() {
@@ -35,13 +28,15 @@ public void cleanup() {
@Test
void contextLoads() {
- this.todoRepository.saveAll(List.of(new Todo("Write blog post", LocalDateTime.now().plusDays(2)),
- new Todo("Clean appartment", LocalDateTime.now().plusDays(4))));
+ this.todoRepository.saveAll(
+ List.of(
+ new Todo("Write blog post", LocalDateTime.now().plusDays(2)),
+ new Todo("Clean apartment", LocalDateTime.now().plusDays(4))));
- ResponseEntity result = this.testRestTemplate.getForEntity("/todos", ArrayNode.class);
+ ResponseEntity result =
+ this.testRestTemplate.getForEntity("/todos", ArrayNode.class);
assertEquals(200, result.getStatusCodeValue());
assertTrue(result.getBody().isArray());
assertEquals(2, result.getBody().size());
}
-
}
diff --git a/testcontainers-reuse-existing-containers/src/test/java/de/rieckpil/blog/ThirdApplicationIT.java b/testcontainers-reuse-existing-containers/src/test/java/de/rieckpil/blog/ThirdApplicationIT.java
index be7cb5c4..c5b408ee 100644
--- a/testcontainers-reuse-existing-containers/src/test/java/de/rieckpil/blog/ThirdApplicationIT.java
+++ b/testcontainers-reuse-existing-containers/src/test/java/de/rieckpil/blog/ThirdApplicationIT.java
@@ -1,6 +1,11 @@
package de.rieckpil.blog;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
import com.fasterxml.jackson.databind.node.ArrayNode;
+import java.time.LocalDateTime;
+import java.util.List;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
@@ -13,26 +18,19 @@
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.containers.PostgreSQLContainer;
-import java.time.LocalDateTime;
-import java.util.List;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class ThirdApplicationIT {
- @Autowired
- private TestRestTemplate testRestTemplate;
+ @Autowired private TestRestTemplate testRestTemplate;
- @Autowired
- private TodoRepository todoRepository;
+ @Autowired private TodoRepository todoRepository;
- static PostgreSQLContainer postgreSQLContainer = (PostgreSQLContainer) new PostgreSQLContainer("postgres:10-alpine")
- .withDatabaseName("test")
- .withUsername("duke")
- .withPassword("s3cret")
- .withReuse(true);
+ static PostgreSQLContainer> postgreSQLContainer =
+ new PostgreSQLContainer<>("postgres:10-alpine")
+ .withDatabaseName("test")
+ .withUsername("duke")
+ .withPassword("s3cret")
+ .withReuse(true);
@DynamicPropertySource
static void datasourceConfig(DynamicPropertyRegistry registry) {
@@ -42,24 +40,26 @@ static void datasourceConfig(DynamicPropertyRegistry registry) {
}
@BeforeAll
- public static void beforeAll() {
+ static void beforeAll() {
postgreSQLContainer.start();
}
@AfterEach
- public void cleanup() {
+ void cleanup() {
this.todoRepository.deleteAll();
}
@Test
void contextLoads() {
- this.todoRepository.saveAll(List.of(new Todo("Write blog post", LocalDateTime.now().plusDays(2)),
- new Todo("Clean appartment", LocalDateTime.now().plusDays(4))));
+ this.todoRepository.saveAll(
+ List.of(
+ new Todo("Write blog post", LocalDateTime.now().plusDays(2)),
+ new Todo("Clean apartment", LocalDateTime.now().plusDays(4))));
- ResponseEntity result = this.testRestTemplate.getForEntity("/todos", ArrayNode.class);
+ ResponseEntity result =
+ this.testRestTemplate.getForEntity("/todos", ArrayNode.class);
assertEquals(200, result.getStatusCodeValue());
assertTrue(result.getBody().isArray());
assertEquals(2, result.getBody().size());
}
-
}
diff --git a/testcontainers-youtube-series/pom.xml b/testcontainers-youtube-series/pom.xml
index 6a738bea..e56edff7 100644
--- a/testcontainers-youtube-series/pom.xml
+++ b/testcontainers-youtube-series/pom.xml
@@ -17,7 +17,7 @@
11
- 1.15.1
+ 1.16.0
@@ -25,7 +25,7 @@
com.amazonaws
aws-java-sdk-bom
- 1.11.959
+ 1.12.740
pom
import
diff --git a/testing-java-applications-with-maven/.mvn/wrapper/MavenWrapperDownloader.java b/testing-java-applications-with-maven/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 00000000..b901097f
--- /dev/null
+++ b/testing-java-applications-with-maven/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2007-present 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
+ *
+ * http://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.
+ */
+import java.net.*;
+import java.io.*;
+import java.nio.channels.*;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ private static final String WRAPPER_VERSION = "0.5.6";
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
+ String username = System.getenv("MVNW_USERNAME");
+ char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
+ Authenticator.setDefault(new Authenticator() {
+ @Override
+ protected PasswordAuthentication getPasswordAuthentication() {
+ return new PasswordAuthentication(username, password);
+ }
+ });
+ }
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/testing-java-applications-with-maven/.mvn/wrapper/maven-wrapper.jar b/testing-java-applications-with-maven/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 00000000..2cc7d4a5
Binary files /dev/null and b/testing-java-applications-with-maven/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/testing-java-applications-with-maven/.mvn/wrapper/maven-wrapper.properties b/testing-java-applications-with-maven/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 00000000..ffdc10e5
--- /dev/null
+++ b/testing-java-applications-with-maven/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,2 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.1/apache-maven-3.8.1-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
diff --git a/testing-java-applications-with-maven/README.md b/testing-java-applications-with-maven/README.md
new file mode 100644
index 00000000..19ef6703
--- /dev/null
+++ b/testing-java-applications-with-maven/README.md
@@ -0,0 +1,7 @@
+# Codebase for the blog post [Maven Setup For Testing Java Applications](https://rieckpil.de/maven-setup-for-testing-java-applications/)
+
+Steps to run this project:
+
+1. Clone this Git repository
+2. Navigate to the folder `testing-java-applications-with-maven`
+3. Build and test the project with `./mvnw verify` (Linux and Mac) or `mvnw.cdm verify` (Windows)
diff --git a/testing-java-applications-with-maven/mvnw b/testing-java-applications-with-maven/mvnw
new file mode 100644
index 00000000..41c0f0c2
--- /dev/null
+++ b/testing-java-applications-with-maven/mvnw
@@ -0,0 +1,310 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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
+#
+# http://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.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# M2_HOME - location of maven2's installed home dir
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ export JAVA_HOME="`/usr/libexec/java_home`"
+ else
+ export JAVA_HOME="/Library/Java/Home"
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=`java-config --jre-home`
+ fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+ ## resolve links - $0 may be a link to maven's home
+ PRG="$0"
+
+ # need this for relative symlinks
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG="`dirname "$PRG"`/$link"
+ fi
+ done
+
+ saveddir=`pwd`
+
+ M2_HOME=`dirname "$PRG"`/..
+
+ # make it fully qualified
+ M2_HOME=`cd "$M2_HOME" && pwd`
+
+ cd "$saveddir"
+ # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --unix "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME="`(cd "$M2_HOME"; pwd)`"
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="`which javac`"
+ if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=`which readlink`
+ if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+ if $darwin ; then
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+ else
+ javaExecutable="`readlink -f \"$javaExecutable\"`"
+ fi
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="`which java`"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=`cd "$wdir/.."; pwd`
+ fi
+ # end of workaround
+ done
+ echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ echo "$(tr -s '\n' ' ' < "$1")"
+ fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found .mvn/wrapper/maven-wrapper.jar"
+ fi
+else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+ fi
+ if [ -n "$MVNW_REPOURL" ]; then
+ jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ else
+ jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ fi
+ while IFS="=" read key value; do
+ case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
+ esac
+ done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Downloading from: $jarUrl"
+ fi
+ wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+ if $cygwin; then
+ wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
+ fi
+
+ if command -v wget > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found wget ... using wget"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget "$jarUrl" -O "$wrapperJarPath"
+ else
+ wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
+ fi
+ elif command -v curl > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found curl ... using curl"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl -o "$wrapperJarPath" "$jarUrl" -f
+ else
+ curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
+ fi
+
+ else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Falling back to using Java to download"
+ fi
+ javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaClass=`cygpath --path --windows "$javaClass"`
+ fi
+ if [ -e "$javaClass" ]; then
+ if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Compiling MavenWrapperDownloader.java ..."
+ fi
+ # Compiling the Java class
+ ("$JAVA_HOME/bin/javac" "$javaClass")
+ fi
+ if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ # Running the downloader
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Running MavenWrapperDownloader.java ..."
+ fi
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+if [ "$MVNW_VERBOSE" = true ]; then
+ echo $MAVEN_PROJECTBASEDIR
+fi
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --path --windows "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/testing-java-applications-with-maven/mvnw.cmd b/testing-java-applications-with-maven/mvnw.cmd
new file mode 100644
index 00000000..86115719
--- /dev/null
+++ b/testing-java-applications-with-maven/mvnw.cmd
@@ -0,0 +1,182 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
+if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+
+FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Found %WRAPPER_JAR%
+ )
+) else (
+ if not "%MVNW_REPOURL%" == "" (
+ SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ )
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %DOWNLOAD_URL%
+ )
+
+ powershell -Command "&{"^
+ "$webclient = new-object System.Net.WebClient;"^
+ "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+ "}"^
+ "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
+ "}"
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Finished downloading %WRAPPER_JAR%
+ )
+)
+@REM End of extension
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
+if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%" == "on" pause
+
+if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
+
+exit /B %ERROR_CODE%
diff --git a/testing-java-applications-with-maven/pom.xml b/testing-java-applications-with-maven/pom.xml
new file mode 100644
index 00000000..8bf9f26d
--- /dev/null
+++ b/testing-java-applications-with-maven/pom.xml
@@ -0,0 +1,83 @@
+
+ 4.0.0
+
+ de.rieckpil.blog
+ testing-java-applications-with-maven
+ 1.0-SNAPSHOT
+
+
+ 11
+ 11
+ UTF-8
+ UTF-8
+ 1.15.3
+ 5.7.2
+ 3.10.0
+
+
+
+
+
+ org.junit
+ junit-bom
+ ${junit-jupiter.version}
+ pom
+ import
+
+
+ org.testcontainers
+ testcontainers-bom
+ ${testcontainers.version}
+ pom
+ import
+
+
+
+
+
+
+ org.junit.jupiter
+ junit-jupiter
+ test
+
+
+ org.mockito
+ mockito-junit-jupiter
+ ${mockito.version}
+ test
+
+
+ org.testcontainers
+ junit-jupiter
+ test
+
+
+
+
+ testing-java-applications-with-maven
+
+
+ maven-compiler-plugin
+ 3.8.1
+
+
+ maven-surefire-plugin
+ 3.0.0-M5
+
+
+ maven-failsafe-plugin
+ 3.0.0-M5
+
+
+
+ integration-test
+ verify
+
+
+
+
+
+
+
diff --git a/testing-java-applications-with-maven/src/main/java/de/rieckpil/blog/Main.java b/testing-java-applications-with-maven/src/main/java/de/rieckpil/blog/Main.java
new file mode 100644
index 00000000..ce9ca7da
--- /dev/null
+++ b/testing-java-applications-with-maven/src/main/java/de/rieckpil/blog/Main.java
@@ -0,0 +1,8 @@
+package de.rieckpil.blog;
+
+public class Main {
+
+ public String format(String input) {
+ return input.toUpperCase();
+ }
+}
diff --git a/testing-java-applications-with-maven/src/test/java/de/rieckpil/blog/MainIT.java b/testing-java-applications-with-maven/src/test/java/de/rieckpil/blog/MainIT.java
new file mode 100644
index 00000000..e343db4b
--- /dev/null
+++ b/testing-java-applications-with-maven/src/test/java/de/rieckpil/blog/MainIT.java
@@ -0,0 +1,23 @@
+package de.rieckpil.blog;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class MainIT {
+
+ private Main cut;
+
+ @BeforeEach
+ void setUp() {
+ this.cut = new Main();
+ }
+
+ @Test
+ void firstTest() {
+ // insert meaningful test here
+
+ System.out.println("Executing an integration test");
+ }
+}
diff --git a/testing-java-applications-with-maven/src/test/java/de/rieckpil/blog/MainTest.java b/testing-java-applications-with-maven/src/test/java/de/rieckpil/blog/MainTest.java
new file mode 100644
index 00000000..e85bef62
--- /dev/null
+++ b/testing-java-applications-with-maven/src/test/java/de/rieckpil/blog/MainTest.java
@@ -0,0 +1,25 @@
+package de.rieckpil.blog;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class MainTest {
+
+ private Main cut;
+
+ @BeforeEach
+ void setUp() {
+ this.cut = new Main();
+ }
+
+ @Test
+ void firstTest() {
+ String input = "duke";
+
+ String result = cut.format(input);
+
+ assertEquals("DUKE", result);
+ }
+}
diff --git a/testing-java-applications-with-maven/target/classes/de/rieckpil/blog/Main.class b/testing-java-applications-with-maven/target/classes/de/rieckpil/blog/Main.class
new file mode 100644
index 00000000..35ecf1ce
Binary files /dev/null and b/testing-java-applications-with-maven/target/classes/de/rieckpil/blog/Main.class differ
diff --git a/testing-java-applications-with-maven/target/test-classes/de/rieckpil/blog/MainIT.class b/testing-java-applications-with-maven/target/test-classes/de/rieckpil/blog/MainIT.class
new file mode 100644
index 00000000..e6b67087
Binary files /dev/null and b/testing-java-applications-with-maven/target/test-classes/de/rieckpil/blog/MainIT.class differ
diff --git a/testing-java-applications-with-maven/target/test-classes/de/rieckpil/blog/MainTest.class b/testing-java-applications-with-maven/target/test-classes/de/rieckpil/blog/MainTest.class
new file mode 100644
index 00000000..59109eec
Binary files /dev/null and b/testing-java-applications-with-maven/target/test-classes/de/rieckpil/blog/MainTest.class differ
diff --git a/testing-json-serialization-spring/pom.xml b/testing-json-serialization-spring/pom.xml
index 484cc327..ee66c329 100644
--- a/testing-json-serialization-spring/pom.xml
+++ b/testing-json-serialization-spring/pom.xml
@@ -2,29 +2,24 @@
4.0.0
+
- org.springframework.boot
- spring-boot-starter-parent
- 2.4.5
-
+ de.rieckpil.blog
+ blog-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
- de.rieckpil.blog
testing-json-serialization-spring
0.0.1-SNAPSHOT
testing-json-serialization-spring
Testing JSON serialization with Spring Boot
-
- 11
-
-
org.springframework.boot
spring-boot-starter-web
-
org.springframework.boot
spring-boot-starter-test
diff --git a/testing-json-serialization-spring/src/main/java/de/rieckpil/blog/CarDetailsJsonSerializer.java b/testing-json-serialization-spring/src/main/java/de/rieckpil/blog/CarDetailsJsonSerializer.java
index dc817910..ea08e3c6 100644
--- a/testing-json-serialization-spring/src/main/java/de/rieckpil/blog/CarDetailsJsonSerializer.java
+++ b/testing-json-serialization-spring/src/main/java/de/rieckpil/blog/CarDetailsJsonSerializer.java
@@ -3,18 +3,19 @@
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
-import org.springframework.boot.jackson.JsonComponent;
-
import java.io.IOException;
+import org.springframework.boot.jackson.JsonComponent;
@JsonComponent
public class CarDetailsJsonSerializer extends JsonSerializer {
@Override
- public void serialize(CarDetails value, JsonGenerator jsonGenerator, SerializerProvider serializers) throws IOException {
+ public void serialize(
+ CarDetails value, JsonGenerator jsonGenerator, SerializerProvider serializers)
+ throws IOException {
jsonGenerator.writeStartObject();
jsonGenerator.writeStringField(
- "type", value.getManufacturer() + "|" + value.getType() + "|" + value.getColor());
+ "type", value.getManufacturer() + "|" + value.getType() + "|" + value.getColor());
jsonGenerator.writeEndObject();
}
}
diff --git a/testing-json-serialization-spring/src/main/java/de/rieckpil/blog/TestingJsonSerializationSpringApplication.java b/testing-json-serialization-spring/src/main/java/de/rieckpil/blog/TestingJsonSerializationSpringApplication.java
index 4a2c4540..3409f4d0 100644
--- a/testing-json-serialization-spring/src/main/java/de/rieckpil/blog/TestingJsonSerializationSpringApplication.java
+++ b/testing-json-serialization-spring/src/main/java/de/rieckpil/blog/TestingJsonSerializationSpringApplication.java
@@ -6,8 +6,7 @@
@SpringBootApplication
public class TestingJsonSerializationSpringApplication {
- public static void main(String[] args) {
- SpringApplication.run(TestingJsonSerializationSpringApplication.class, args);
- }
-
+ public static void main(String[] args) {
+ SpringApplication.run(TestingJsonSerializationSpringApplication.class, args);
+ }
}
diff --git a/testing-json-serialization-spring/src/main/java/de/rieckpil/blog/UserDetails.java b/testing-json-serialization-spring/src/main/java/de/rieckpil/blog/UserDetails.java
index 331a8b91..f557368f 100644
--- a/testing-json-serialization-spring/src/main/java/de/rieckpil/blog/UserDetails.java
+++ b/testing-json-serialization-spring/src/main/java/de/rieckpil/blog/UserDetails.java
@@ -4,7 +4,6 @@
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
-
import java.time.LocalDate;
@JsonNaming(PropertyNamingStrategy.LowerCaseStrategy.class)
@@ -20,7 +19,8 @@ public class UserDetails {
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private boolean enabled;
- public UserDetails(Long id, String firstName, String lastName, LocalDate dateOfBirth, boolean enabled) {
+ public UserDetails(
+ Long id, String firstName, String lastName, LocalDate dateOfBirth, boolean enabled) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
@@ -67,5 +67,4 @@ public boolean isEnabled() {
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
-
}
diff --git a/testing-json-serialization-spring/src/test/java/de/rieckpil/blog/CarDetailsJsonTest.java b/testing-json-serialization-spring/src/test/java/de/rieckpil/blog/CarDetailsJsonTest.java
index 01f7adfd..4dd970b2 100644
--- a/testing-json-serialization-spring/src/test/java/de/rieckpil/blog/CarDetailsJsonTest.java
+++ b/testing-json-serialization-spring/src/test/java/de/rieckpil/blog/CarDetailsJsonTest.java
@@ -1,18 +1,17 @@
package de.rieckpil.blog;
+import static org.assertj.core.api.Assertions.assertThat;
+
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.json.JsonTest;
import org.springframework.boot.test.json.JacksonTester;
import org.springframework.boot.test.json.JsonContent;
-import static org.assertj.core.api.Assertions.assertThat;
-
@JsonTest
class CarDetailsJsonTest {
- @Autowired
- private JacksonTester json;
+ @Autowired private JacksonTester json;
@Test
public void testSerialize() throws Exception {
diff --git a/testing-json-serialization-spring/src/test/java/de/rieckpil/blog/UserDetailsJsonTest.java b/testing-json-serialization-spring/src/test/java/de/rieckpil/blog/UserDetailsJsonTest.java
index 3a271592..bc9f7e46 100644
--- a/testing-json-serialization-spring/src/test/java/de/rieckpil/blog/UserDetailsJsonTest.java
+++ b/testing-json-serialization-spring/src/test/java/de/rieckpil/blog/UserDetailsJsonTest.java
@@ -1,49 +1,46 @@
package de.rieckpil.blog;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.time.LocalDate;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.json.JsonTest;
import org.springframework.boot.test.json.JacksonTester;
import org.springframework.boot.test.json.JsonContent;
-import java.time.LocalDate;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
@JsonTest
class UserDetailsJsonTest {
- @Autowired
- private JacksonTester json;
+ @Autowired private JacksonTester json;
-@Test
-public void testSerialize() throws Exception {
+ @Test
+ public void testSerialize() throws Exception {
- UserDetails userDetails = new UserDetails(1L, "Duke", "Java",
- LocalDate.of(1995, 1, 1), true);
+ UserDetails userDetails = new UserDetails(1L, "Duke", "Java", LocalDate.of(1995, 1, 1), true);
- JsonContent result = this.json.write(userDetails);
+ JsonContent result = this.json.write(userDetails);
- assertThat(result).hasJsonPathStringValue("$.firstname");
- assertThat(result).extractingJsonPathStringValue("$.firstname").isEqualTo("Duke");
- assertThat(result).extractingJsonPathStringValue("$.lastname").isEqualTo("Java");
- assertThat(result).extractingJsonPathStringValue("$.dateofbirth").isEqualTo("01.01.1995");
- assertThat(result).doesNotHaveJsonPath("$.enabled");
-}
+ assertThat(result).hasJsonPathStringValue("$.firstname");
+ assertThat(result).extractingJsonPathStringValue("$.firstname").isEqualTo("Duke");
+ assertThat(result).extractingJsonPathStringValue("$.lastname").isEqualTo("Java");
+ assertThat(result).extractingJsonPathStringValue("$.dateofbirth").isEqualTo("01.01.1995");
+ assertThat(result).doesNotHaveJsonPath("$.enabled");
+ }
-@Test
-public void testDeserialize() throws Exception {
+ @Test
+ public void testDeserialize() throws Exception {
- String jsonContent = "{\"firstname\":\"Mike\", \"lastname\": \"Meyer\", \"dateofbirth\":\"15.05.1990\"," +
- " \"id\": 42, \"enabled\": true}";
+ String jsonContent =
+ "{\"firstname\":\"Mike\", \"lastname\": \"Meyer\", \"dateofbirth\":\"15.05.1990\","
+ + " \"id\": 42, \"enabled\": true}";
- UserDetails result = this.json.parse(jsonContent).getObject();
-
- assertThat(result.getFirstName()).isEqualTo("Mike");
- assertThat(result.getLastName()).isEqualTo("Meyer");
- assertThat(result.getDateOfBirth()).isEqualTo(LocalDate.of(1990, 05, 15));
- assertThat(result.getId()).isEqualTo(42L);
- assertThat(result.isEnabled()).isEqualTo(true);
-}
+ UserDetails result = this.json.parse(jsonContent).getObject();
+ assertThat(result.getFirstName()).isEqualTo("Mike");
+ assertThat(result.getLastName()).isEqualTo("Meyer");
+ assertThat(result.getDateOfBirth()).isEqualTo(LocalDate.of(1990, 05, 15));
+ assertThat(result.getId()).isEqualTo(42L);
+ assertThat(result.isEnabled()).isEqualTo(true);
+ }
}
diff --git a/testing-libraries-overview/docker-compose.yml b/testing-libraries-overview/docker-compose.yml
index aa466cb7..426dad89 100644
--- a/testing-libraries-overview/docker-compose.yml
+++ b/testing-libraries-overview/docker-compose.yml
@@ -1,12 +1,11 @@
-version: '3'
services:
database:
- image: postgres:12.3
+ image: postgres:16.2
environment:
- POSTGRES_USER=testcontainers
- POSTGRES_PASSWORD=secret
keycloak:
- image: jboss/keycloak:11.0.0
+ image: quay.io/keycloak/keycloak:19.0.3-legacy
environment:
- KEYCLOAK_USER=testcontainers
- KEYCLOAK_PASSWORD=secret
diff --git a/testing-libraries-overview/pom.xml b/testing-libraries-overview/pom.xml
index b5c51a1f..ddbd393b 100644
--- a/testing-libraries-overview/pom.xml
+++ b/testing-libraries-overview/pom.xml
@@ -4,68 +4,47 @@
4.0.0
- org.springframework.boot
- spring-boot-starter-parent
- 2.4.2
-
+ de.rieckpil.blog
+ blog-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
- de.rieckpil.blog
testing-libraries-overview
1.0.0
testing-libraries-overview
- 11
4.13.2
- 1.15.2
- 3.7.0
+ 1.19.8
+ 5.11.0
6.8
2.2
- 3.19.0
- 2.5.0
- 1.5.0
+ 3.26.0
+ 2.9.0
+ 1.5.1
2.0.9
- 2.27.2
+ 3.6.0
4.9.0
2.10.0
4.9.0
- 2.8.2
- 5.19.0
- 3.141.59
+ 2.10.0
+ 7.3.2
+ 4.16.1
0.9
4.0.3
- 4.3.3
- 1.6.0
- 3.0.7
+ 5.4.0
+ 1.6.15
+ 4.0.16
2.8.0
-
- org.junit
- junit-bom
- 5.7.0
- pom
- import
-
-
- org.testcontainers
- testcontainers-bom
- ${testcontainers.version}
- pom
- import
-
-
- com.squareup.okio
- okio
- ${okio.version}
-
commons-io
commons-io
- 2.6
+ 2.11.0
@@ -94,7 +73,7 @@
com.sun.mail
jakarta.mail
- 1.6.5
+ 1.6.7
@@ -174,8 +153,8 @@
test
- com.github.tomakehurst
- wiremock-jre8
+ org.wiremock
+ wiremock-standalone
${wiremock.version}
test
diff --git a/testing-libraries-overview/src/main/java/de/rieckpil/blog/client/JavaHttpClient.java b/testing-libraries-overview/src/main/java/de/rieckpil/blog/client/JavaHttpClient.java
index 61f46679..a3f9f0ee 100644
--- a/testing-libraries-overview/src/main/java/de/rieckpil/blog/client/JavaHttpClient.java
+++ b/testing-libraries-overview/src/main/java/de/rieckpil/blog/client/JavaHttpClient.java
@@ -2,7 +2,6 @@
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
-
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
@@ -21,22 +20,25 @@ public JavaHttpClient(String baseUrl) {
public String getRandomQuote() {
HttpClient client = HttpClient.newHttpClient();
- HttpRequest request = HttpRequest.newBuilder()
- .uri(URI.create(baseUrl + "/qod"))
- .header("Accept", "application/json")
- .GET()
- .build();
+ HttpRequest request =
+ HttpRequest.newBuilder()
+ .uri(URI.create(baseUrl + "/qod"))
+ .header("Accept", "application/json")
+ .GET()
+ .build();
try {
- HttpResponse httpResponse = client.send(request, HttpResponse.BodyHandlers.ofString());
+ HttpResponse httpResponse =
+ client.send(request, HttpResponse.BodyHandlers.ofString());
if (httpResponse.statusCode() != 200) {
return DEFAULT_QUOTE;
}
- RandomQuoteResponse responseBody = new ObjectMapper()
- .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
- .readValue(httpResponse.body(), RandomQuoteResponse.class);
+ RandomQuoteResponse responseBody =
+ new ObjectMapper()
+ .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
+ .readValue(httpResponse.body(), RandomQuoteResponse.class);
String randomQuote = responseBody.getContents().getQuotes().get(0).getQuote();
diff --git a/testing-libraries-overview/src/main/java/de/rieckpil/blog/customer/Address.java b/testing-libraries-overview/src/main/java/de/rieckpil/blog/customer/Address.java
index 169b8209..d3416758 100644
--- a/testing-libraries-overview/src/main/java/de/rieckpil/blog/customer/Address.java
+++ b/testing-libraries-overview/src/main/java/de/rieckpil/blog/customer/Address.java
@@ -6,8 +6,7 @@ public class Address {
private String country;
private String postalCode;
- public Address() {
- }
+ public Address() {}
public Address(String city, String country, String postalCode) {
this.city = city;
diff --git a/testing-libraries-overview/src/main/java/de/rieckpil/blog/customer/Customer.java b/testing-libraries-overview/src/main/java/de/rieckpil/blog/customer/Customer.java
index 5cbb6a21..56b3f604 100644
--- a/testing-libraries-overview/src/main/java/de/rieckpil/blog/customer/Customer.java
+++ b/testing-libraries-overview/src/main/java/de/rieckpil/blog/customer/Customer.java
@@ -2,7 +2,6 @@
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
-
import java.util.List;
import java.util.Set;
@@ -21,10 +20,10 @@ public class Customer {
private Address address;
- public Customer() {
- }
+ public Customer() {}
- public Customer(String username, String id, Set tags, List orders, Address address) {
+ public Customer(
+ String username, String id, Set tags, List orders, Address address) {
this.username = username;
this.id = id;
this.tags = tags;
diff --git a/testing-libraries-overview/src/main/java/de/rieckpil/blog/customer/CustomerController.java b/testing-libraries-overview/src/main/java/de/rieckpil/blog/customer/CustomerController.java
index 4b0d8e17..7aadc6be 100644
--- a/testing-libraries-overview/src/main/java/de/rieckpil/blog/customer/CustomerController.java
+++ b/testing-libraries-overview/src/main/java/de/rieckpil/blog/customer/CustomerController.java
@@ -1,15 +1,14 @@
package de.rieckpil.blog.customer;
-import org.springframework.http.MediaType;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.*;
-import org.springframework.web.util.UriComponentsBuilder;
-
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.UUID;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.util.UriComponentsBuilder;
@RestController
@RequestMapping("/api/customers")
@@ -27,56 +26,58 @@ private List createSampleCustomers() {
customerOne.setTags(Set.of("VIP", "PLATINUM_MEMBER", "EARLY_BIRD"));
customerOne.setUsername("duke42");
customerOne.setAddress(new Address("Berlin", "Germany", "12347"));
- customerOne.setOrders(List.of(
- new Order(List.of(
- new Product("MacBook Pro", BigDecimal.valueOf(1499.99), 3L),
- new Product("Kindle Paperwhite", BigDecimal.valueOf(149.00), 10L)
- ), "DEBIT"),
- new Order(List.of(
- new Product("Milk", BigDecimal.valueOf(0.99), 12L),
- new Product("Chocolate", BigDecimal.valueOf(2.99), 42L)
- ), "CREDIT_CARD")));
+ customerOne.setOrders(
+ List.of(
+ new Order(
+ List.of(
+ new Product("MacBook Pro", BigDecimal.valueOf(1499.99), 3L),
+ new Product("Kindle Paperwhite", BigDecimal.valueOf(149.00), 10L)),
+ "DEBIT"),
+ new Order(
+ List.of(
+ new Product("Milk", BigDecimal.valueOf(0.99), 12L),
+ new Product("Chocolate", BigDecimal.valueOf(2.99), 42L)),
+ "CREDIT_CARD")));
Customer customerTwo = new Customer();
customerTwo.setId(UUID.randomUUID().toString());
customerTwo.setTags(Set.of("BRONZE_MEMBER", "DELAYED_PAYMENTS"));
customerTwo.setUsername("alice");
customerTwo.setAddress(new Address("Paris", "France", "75000"));
- customerTwo.setOrders(List.of(
- new Order(List.of(
- new Product("iPhone 12", BigDecimal.valueOf(999.99), 12L),
- new Product("Laptop", BigDecimal.valueOf(649.00), 10L)
- ), "PAYPAL")));
+ customerTwo.setOrders(
+ List.of(
+ new Order(
+ List.of(
+ new Product("iPhone 12", BigDecimal.valueOf(999.99), 12L),
+ new Product("Laptop", BigDecimal.valueOf(649.00), 10L)),
+ "PAYPAL")));
Customer customerThree = new Customer();
customerThree.setId(UUID.randomUUID().toString());
customerThree.setTags(Set.of("GOLD_MEMBER"));
customerThree.setUsername("bob");
customerThree.setAddress(new Address("São Paulo", "Brazil", "17800-000"));
- customerThree.setOrders(List.of(
- new Order(List.of(
- new Product("MacBook Pro", BigDecimal.valueOf(2499.99), 2L),
- new Product("Kindle", BigDecimal.valueOf(99.00), 5L)
- ), "DEBIT"),
- new Order(List.of(
- new Product("Chewing Gum", BigDecimal.valueOf(0.49), 100L)
- ), "DEBIT")));
+ customerThree.setOrders(
+ List.of(
+ new Order(
+ List.of(
+ new Product("MacBook Pro", BigDecimal.valueOf(2499.99), 2L),
+ new Product("Kindle", BigDecimal.valueOf(99.00), 5L)),
+ "DEBIT"),
+ new Order(
+ List.of(new Product("Chewing Gum", BigDecimal.valueOf(0.49), 100L)), "DEBIT")));
return Arrays.asList(customerOne, customerTwo, customerThree);
}
@PostMapping
public ResponseEntity createNewUser(
- @RequestBody CustomerCreationRequest request,
- UriComponentsBuilder uriComponentsBuilder) {
+ @RequestBody CustomerCreationRequest request, UriComponentsBuilder uriComponentsBuilder) {
System.out.println(request);
- return ResponseEntity
- .created(uriComponentsBuilder
- .path("/api/customers/{id}")
- .buildAndExpand("42")
- .toUri())
- .build();
+ return ResponseEntity.created(
+ uriComponentsBuilder.path("/api/customers/{id}").buildAndExpand("42").toUri())
+ .build();
}
}
diff --git a/testing-libraries-overview/src/main/java/de/rieckpil/blog/customer/CustomerCreationRequest.java b/testing-libraries-overview/src/main/java/de/rieckpil/blog/customer/CustomerCreationRequest.java
index 86cdd9aa..19300375 100644
--- a/testing-libraries-overview/src/main/java/de/rieckpil/blog/customer/CustomerCreationRequest.java
+++ b/testing-libraries-overview/src/main/java/de/rieckpil/blog/customer/CustomerCreationRequest.java
@@ -14,8 +14,6 @@ public void setUsername(String username) {
@Override
public String toString() {
- return "CustomerCreationRequest{" +
- "username='" + username + '\'' +
- '}';
+ return "CustomerCreationRequest{" + "username='" + username + '\'' + '}';
}
}
diff --git a/testing-libraries-overview/src/main/java/de/rieckpil/blog/customer/Order.java b/testing-libraries-overview/src/main/java/de/rieckpil/blog/customer/Order.java
index e6ae59d9..f6a3e255 100644
--- a/testing-libraries-overview/src/main/java/de/rieckpil/blog/customer/Order.java
+++ b/testing-libraries-overview/src/main/java/de/rieckpil/blog/customer/Order.java
@@ -2,8 +2,6 @@
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
-
-import java.time.LocalDateTime;
import java.util.List;
public class Order {
@@ -14,8 +12,7 @@ public class Order {
private String paymentMethod;
- public Order() {
- }
+ public Order() {}
public Order(List products, String paymentMethod) {
this.products = products;
@@ -37,5 +34,4 @@ public String getPaymentMethod() {
public void setPaymentMethod(String paymentMethod) {
this.paymentMethod = paymentMethod;
}
-
}
diff --git a/testing-libraries-overview/src/main/java/de/rieckpil/blog/customer/Product.java b/testing-libraries-overview/src/main/java/de/rieckpil/blog/customer/Product.java
index 84f3b74e..df21d8dc 100644
--- a/testing-libraries-overview/src/main/java/de/rieckpil/blog/customer/Product.java
+++ b/testing-libraries-overview/src/main/java/de/rieckpil/blog/customer/Product.java
@@ -1,7 +1,5 @@
package de.rieckpil.blog.customer;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
-
import java.math.BigDecimal;
public class Product {
@@ -10,8 +8,7 @@ public class Product {
private BigDecimal price;
private Long quantity;
- public Product() {
- }
+ public Product() {}
public Product(String name, BigDecimal price, Long quantity) {
this.name = name;
diff --git a/testing-libraries-overview/src/main/java/de/rieckpil/blog/mailing/MailService.java b/testing-libraries-overview/src/main/java/de/rieckpil/blog/mailing/MailService.java
index 441f6c7e..228b000b 100644
--- a/testing-libraries-overview/src/main/java/de/rieckpil/blog/mailing/MailService.java
+++ b/testing-libraries-overview/src/main/java/de/rieckpil/blog/mailing/MailService.java
@@ -1,19 +1,21 @@
package de.rieckpil.blog.mailing;
+import java.util.Properties;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
-import java.util.Properties;
public class MailService {
private final Session session;
- public MailService(String host, Integer smtpPort, Integer imapPort, String username, String password) {
+ public MailService(
+ String host, Integer smtpPort, Integer imapPort, String username, String password) {
this.session = createSession(host, smtpPort, imapPort, username, password);
}
- private Session createSession(String host, Integer smtpPort, Integer imapPort, String username, String password) {
+ private Session createSession(
+ String host, Integer smtpPort, Integer imapPort, String username, String password) {
Properties props = new Properties();
props.put("mail.smtp.host", host);
@@ -26,12 +28,13 @@ private Session createSession(String host, Integer smtpPort, Integer imapPort, S
props.put("mail.imap.auth", "true");
props.put("mail.imap.starttls.enable", "true");
- Authenticator authentication = new Authenticator() {
- @Override
- protected PasswordAuthentication getPasswordAuthentication() {
- return new PasswordAuthentication(username, password);
- }
- };
+ Authenticator authentication =
+ new Authenticator() {
+ @Override
+ protected PasswordAuthentication getPasswordAuthentication() {
+ return new PasswordAuthentication(username, password);
+ }
+ };
return Session.getInstance(props, authentication);
}
@@ -47,7 +50,8 @@ public void sendToUser(String message, String recipient) throws MessagingExcepti
Transport.send(mail);
}
- public String retrieveLatestMailForUser(String recipient, String recipientPassword) throws Exception {
+ public String retrieveLatestMailForUser(String recipient, String recipientPassword)
+ throws Exception {
try (Store store = session.getStore("imap")) {
store.connect(recipient, recipientPassword);
diff --git a/testing-libraries-overview/src/main/java/de/rieckpil/blog/registration/User.java b/testing-libraries-overview/src/main/java/de/rieckpil/blog/registration/User.java
index 5ac02a34..c4882121 100644
--- a/testing-libraries-overview/src/main/java/de/rieckpil/blog/registration/User.java
+++ b/testing-libraries-overview/src/main/java/de/rieckpil/blog/registration/User.java
@@ -8,8 +8,7 @@ public class User {
private String username;
private LocalDateTime createdAt;
- public User() {
- }
+ public User() {}
public User(String username, LocalDateTime createdAt) {
this.username = username;
diff --git a/testing-libraries-overview/src/test/java/de/rieckpil/blog/MyFirstTest.java b/testing-libraries-overview/src/test/java/de/rieckpil/blog/MyFirstTest.java
index d34317f4..26e1a20c 100644
--- a/testing-libraries-overview/src/test/java/de/rieckpil/blog/MyFirstTest.java
+++ b/testing-libraries-overview/src/test/java/de/rieckpil/blog/MyFirstTest.java
@@ -1,9 +1,9 @@
package de.rieckpil.blog;
-import org.junit.jupiter.api.Test;
-
import static org.junit.jupiter.api.Assertions.assertNotNull;
+import org.junit.jupiter.api.Test;
+
class MyFirstTest {
@Test
diff --git a/testing-libraries-overview/src/test/java/de/rieckpil/blog/assertj/AssertJTest.java b/testing-libraries-overview/src/test/java/de/rieckpil/blog/assertj/AssertJTest.java
index 27f56552..2260d02a 100644
--- a/testing-libraries-overview/src/test/java/de/rieckpil/blog/assertj/AssertJTest.java
+++ b/testing-libraries-overview/src/test/java/de/rieckpil/blog/assertj/AssertJTest.java
@@ -1,22 +1,21 @@
package de.rieckpil.blog.assertj;
+import static org.assertj.core.api.Assertions.within;
+
import de.rieckpil.blog.customer.Address;
import de.rieckpil.blog.customer.Customer;
import de.rieckpil.blog.customer.Order;
import de.rieckpil.blog.customer.Product;
import de.rieckpil.blog.registration.User;
-import org.assertj.core.api.Assertions;
-import org.assertj.core.api.SoftAssertions;
-import org.junit.jupiter.api.Test;
-
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Set;
import java.util.UUID;
-
-import static org.assertj.core.api.Assertions.within;
+import org.assertj.core.api.Assertions;
+import org.assertj.core.api.SoftAssertions;
+import org.junit.jupiter.api.Test;
public class AssertJTest {
@@ -28,89 +27,81 @@ void basicAssertions() {
Assertions.assertThat("duke".toUpperCase()).isEqualTo("DUKE");
- Assertions.assertThat("dUkE".toLowerCase())
- .isEqualTo("duke")
- .hasSize(4)
- .endsWith("e");
-
- Assertions
- .assertThatThrownBy(() -> {
- throw new RuntimeException("Can't reach database on port 5432");
- })
- .hasMessageContaining("5432")
- .isInstanceOf(RuntimeException.class)
- .hasNoCause();
+ Assertions.assertThat("dUkE".toLowerCase()).isEqualTo("duke").hasSize(4).endsWith("e");
+
+ Assertions.assertThatThrownBy(
+ () -> {
+ throw new RuntimeException("Can't reach database on port 5432");
+ })
+ .hasMessageContaining("5432")
+ .isInstanceOf(RuntimeException.class)
+ .hasNoCause();
}
@Test
void customErrorMessage() {
- Assertions.assertThatThrownBy(() -> {
- boolean boardingComplete = false;
-
- Assertions
- .assertThat(boardingComplete)
- .withFailMessage("Expecting boarding completed when last passenger enters the plane")
- .isTrue();
- });
+ Assertions.assertThatThrownBy(
+ () -> {
+ boolean boardingComplete = false;
+
+ Assertions.assertThat(boardingComplete)
+ .withFailMessage("Expecting boarding completed when last passenger enters the plane")
+ .isTrue();
+ });
}
@Test
void softAssertions() {
- Assertions.assertThatThrownBy(() -> {
- SoftAssertions softAssertions = new SoftAssertions();
+ Assertions.assertThatThrownBy(
+ () -> {
+ SoftAssertions softAssertions = new SoftAssertions();
- softAssertions.assertThat("duke")
- .hasSize(5)
- .isEqualTo("ekud")
- .startsWith("m");
+ softAssertions.assertThat("duke").hasSize(5).isEqualTo("ekud").startsWith("m");
- softAssertions.assertAll();
- });
+ softAssertions.assertAll();
+ });
}
@Test
void advancedAssertions() {
- Assertions
- .assertThat(List.of("duke", "mike", "alice", "john"))
- .containsAnyOf("mike", "duke")
- .hasSizeBetween(3, 5)
- .hasOnlyElementsOfType(String.class);
-
- Assertions
- .assertThat(List.of(
- new User("duke", LocalDateTime.now().minusMonths(3)),
- new User("alice", LocalDateTime.MIN)))
- .extracting(User::getCreatedAt)
- .filteredOn(createdAt -> createdAt.isBefore(LocalDateTime.now()))
- .hasSize(2);
-
- Assertions
- .assertThat(List.of("duke", "mike", "anna", "john"))
- .allSatisfy(username -> {
- Assertions.assertThat(username).hasSize(4);
- Assertions.assertThat(username).isLowerCase();
- });
-
- Assertions
- .assertThat(List.of("duke", "mike", "alice", "john"))
- .anySatisfy(username -> {
- Assertions.assertThat(username).endsWith("n");
- Assertions.assertThat(username).isSubstringOf("johnny");
- });
-
- Assertions
- .assertThat(LocalDateTime.now())
- .isCloseTo(LocalDateTime.now().plusHours(1), within(2, ChronoUnit.HOURS))
- .isAfter(LocalDateTime.now().minusDays(1))
- .isCloseToUtcNow(within(2, ChronoUnit.HOURS));
-
- Assertions
- .assertThat(BigDecimal.TEN)
- .isNotNegative()
- .isBetween(BigDecimal.ONE, BigDecimal.valueOf(20.0))
- .isGreaterThanOrEqualTo(BigDecimal.ZERO)
- .isNotZero();
+ Assertions.assertThat(List.of("duke", "mike", "alice", "john"))
+ .containsAnyOf("mike", "duke")
+ .hasSizeBetween(3, 5)
+ .hasOnlyElementsOfType(String.class);
+
+ Assertions.assertThat(
+ List.of(
+ new User("duke", LocalDateTime.now().minusMonths(3)),
+ new User("alice", LocalDateTime.MIN)))
+ .extracting(User::getCreatedAt)
+ .filteredOn(createdAt -> createdAt.isBefore(LocalDateTime.now()))
+ .hasSize(2);
+
+ Assertions.assertThat(List.of("duke", "mike", "anna", "john"))
+ .allSatisfy(
+ username -> {
+ Assertions.assertThat(username).hasSize(4);
+ Assertions.assertThat(username).isLowerCase();
+ });
+
+ Assertions.assertThat(List.of("duke", "mike", "alice", "john"))
+ .anySatisfy(
+ username -> {
+ Assertions.assertThat(username).endsWith("n");
+ Assertions.assertThat(username).isSubstringOf("johnny");
+ });
+
+ Assertions.assertThat(LocalDateTime.now())
+ .isCloseTo(LocalDateTime.now().plusHours(1), within(2, ChronoUnit.HOURS))
+ .isAfter(LocalDateTime.now().minusDays(1))
+ .isCloseToUtcNow(within(2, ChronoUnit.HOURS));
+
+ Assertions.assertThat(BigDecimal.TEN)
+ .isNotNegative()
+ .isBetween(BigDecimal.ONE, BigDecimal.valueOf(20.0))
+ .isGreaterThanOrEqualTo(BigDecimal.ZERO)
+ .isNotZero();
}
@Test
@@ -118,13 +109,13 @@ void customAssertions() {
Customer customer = createTestCustomer("duke42");
- CustomerAssert.assertThat(customer)
- .isVIP()
- .hasOrderVolumeGreaterThan(BigDecimal.TEN);
+ CustomerAssert.assertThat(customer).isVIP().hasOrderVolumeGreaterThan(BigDecimal.TEN);
- Assertions.assertThatThrownBy(() -> CustomerAssert.assertThat(customer)
- .isVIP()
- .hasOrderVolumeGreaterThan(BigDecimal.valueOf(9999.99)));
+ Assertions.assertThatThrownBy(
+ () ->
+ CustomerAssert.assertThat(customer)
+ .isVIP()
+ .hasOrderVolumeGreaterThan(BigDecimal.valueOf(9999.99)));
}
private Customer createTestCustomer(String username) {
@@ -133,15 +124,18 @@ private Customer createTestCustomer(String username) {
customer.setTags(Set.of("VIP", "PLATINUM_MEMBER", "EARLY_BIRD"));
customer.setUsername(username);
customer.setAddress(new Address("Berlin", "Germany", "12347"));
- customer.setOrders(List.of(
- new Order(List.of(
- new Product("MacBook Pro", BigDecimal.valueOf(1499.99), 3L),
- new Product("Kindle Paperwhite", BigDecimal.valueOf(149.00), 10L)
- ), "DEBIT"),
- new Order(List.of(
- new Product("Milk", BigDecimal.valueOf(0.99), 12L),
- new Product("Chocolate", BigDecimal.valueOf(2.99), 42L)
- ), "CREDIT_CARD")));
+ customer.setOrders(
+ List.of(
+ new Order(
+ List.of(
+ new Product("MacBook Pro", BigDecimal.valueOf(1499.99), 3L),
+ new Product("Kindle Paperwhite", BigDecimal.valueOf(149.00), 10L)),
+ "DEBIT"),
+ new Order(
+ List.of(
+ new Product("Milk", BigDecimal.valueOf(0.99), 12L),
+ new Product("Chocolate", BigDecimal.valueOf(2.99), 42L)),
+ "CREDIT_CARD")));
return customer;
}
diff --git a/testing-libraries-overview/src/test/java/de/rieckpil/blog/assertj/CustomerAssert.java b/testing-libraries-overview/src/test/java/de/rieckpil/blog/assertj/CustomerAssert.java
index 040dcac4..5b3a25a2 100644
--- a/testing-libraries-overview/src/test/java/de/rieckpil/blog/assertj/CustomerAssert.java
+++ b/testing-libraries-overview/src/test/java/de/rieckpil/blog/assertj/CustomerAssert.java
@@ -2,10 +2,9 @@
import de.rieckpil.blog.customer.Customer;
import de.rieckpil.blog.customer.Order;
-import org.assertj.core.api.AbstractAssert;
-
import java.math.BigDecimal;
import java.util.List;
+import org.assertj.core.api.AbstractAssert;
public class CustomerAssert extends AbstractAssert {
@@ -21,7 +20,9 @@ public CustomerAssert isVIP() {
isNotNull();
if (!this.actual.getTags().contains("VIP")) {
- failWithMessage("Expected customer <%s> to be VIP but not VIP tag was found <%s>", actual.getUsername(), actual.getTags());
+ failWithMessage(
+ "Expected customer <%s> to be VIP but not VIP tag was found <%s>",
+ actual.getUsername(), actual.getTags());
}
return this;
@@ -30,16 +31,17 @@ public CustomerAssert isVIP() {
public CustomerAssert hasOrderVolumeGreaterThan(BigDecimal expected) {
isNotNull();
- BigDecimal orderVolume = this.actual
- .getOrders()
- .stream()
- .map(Order::getProducts)
- .flatMap(List::stream)
- .map(product -> product.getPrice().multiply(BigDecimal.valueOf(product.getQuantity())))
- .reduce(BigDecimal.ZERO, BigDecimal::add);
+ BigDecimal orderVolume =
+ this.actual.getOrders().stream()
+ .map(Order::getProducts)
+ .flatMap(List::stream)
+ .map(product -> product.getPrice().multiply(BigDecimal.valueOf(product.getQuantity())))
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
if (expected.compareTo(orderVolume) > 0) {
- failWithMessage("Expected customer's order volume to be greater than <%s> but was <%s>", expected, orderVolume);
+ failWithMessage(
+ "Expected customer's order volume to be greater than <%s> but was <%s>",
+ expected, orderVolume);
}
return this;
diff --git a/testing-libraries-overview/src/test/java/de/rieckpil/blog/greenmail/MailServiceTest.java b/testing-libraries-overview/src/test/java/de/rieckpil/blog/greenmail/MailServiceTest.java
index d44e1a14..e9b636fd 100644
--- a/testing-libraries-overview/src/test/java/de/rieckpil/blog/greenmail/MailServiceTest.java
+++ b/testing-libraries-overview/src/test/java/de/rieckpil/blog/greenmail/MailServiceTest.java
@@ -1,20 +1,19 @@
package de.rieckpil.blog.greenmail;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
import com.icegreen.greenmail.junit5.GreenMailExtension;
import com.icegreen.greenmail.util.GreenMailUtil;
import com.icegreen.greenmail.util.ServerSetupTest;
import de.rieckpil.blog.mailing.MailService;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.RegisterExtension;
-
import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
class MailServiceTest {
@@ -28,12 +27,13 @@ public void setup() {
greenMail.setUser("admin@java.io", "my_secret");
- this.cut = new MailService(
- greenMail.getSmtp().getBindTo(),
- greenMail.getSmtp().getPort(),
- greenMail.getImap().getPort(),
- "admin@java.io",
- "my_secret");
+ this.cut =
+ new MailService(
+ greenMail.getSmtp().getBindTo(),
+ greenMail.getSmtp().getPort(),
+ greenMail.getImap().getPort(),
+ "admin@java.io",
+ "my_secret");
}
@Test
@@ -53,8 +53,7 @@ void shouldReceiveLastMailForUser() throws Exception {
Message msg = new MimeMessage(smtpSession);
msg.setFrom(new InternetAddress("test@java.io"));
- msg.addRecipient(Message.RecipientType.TO,
- new InternetAddress("mike@java.io"));
+ msg.addRecipient(Message.RecipientType.TO, new InternetAddress("mike@java.io"));
msg.setSubject("Test");
msg.setText("Hello World from GreenMail!");
Transport.send(msg);
diff --git a/testing-libraries-overview/src/test/java/de/rieckpil/blog/hamcrest/HamcrestTest.java b/testing-libraries-overview/src/test/java/de/rieckpil/blog/hamcrest/HamcrestTest.java
index 8fe638b5..a2a33d94 100644
--- a/testing-libraries-overview/src/test/java/de/rieckpil/blog/hamcrest/HamcrestTest.java
+++ b/testing-libraries-overview/src/test/java/de/rieckpil/blog/hamcrest/HamcrestTest.java
@@ -1,29 +1,28 @@
package de.rieckpil.blog.hamcrest;
+import static de.rieckpil.blog.hamcrest.HasOrderVolumeGreaterThan.hasOrderVolumeGreaterThan;
+import static de.rieckpil.blog.hamcrest.IsVIP.isVIP;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
import de.rieckpil.blog.customer.Address;
import de.rieckpil.blog.customer.Customer;
import de.rieckpil.blog.customer.Order;
import de.rieckpil.blog.customer.Product;
-import org.hamcrest.MatcherAssert;
-import org.hamcrest.Matchers;
-import org.junit.jupiter.api.Test;
-import org.w3c.dom.Document;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.io.StringReader;
import java.math.BigDecimal;
import java.util.List;
import java.util.Set;
import java.util.UUID;
-
-import static de.rieckpil.blog.hamcrest.HasOrderVolumeGreaterThan.hasOrderVolumeGreaterThan;
-import static de.rieckpil.blog.hamcrest.IsVIP.isVIP;
-import static org.junit.jupiter.api.Assertions.assertThrows;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import org.hamcrest.MatcherAssert;
+import org.hamcrest.Matchers;
+import org.junit.jupiter.api.Test;
+import org.w3c.dom.Document;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
public class HamcrestTest {
@@ -37,61 +36,59 @@ void basicAssertions() {
MatcherAssert.assertThat("duke".toUpperCase(), Matchers.is(Matchers.equalTo("DUKE")));
MatcherAssert.assertThat("duke".toUpperCase(), Matchers.is("DUKE"));
- MatcherAssert.assertThat("dUkE".toLowerCase(), Matchers.allOf(
- Matchers.equalTo("duke"),
- Matchers.hasLength(4),
- Matchers.endsWith("e")
- ));
+ MatcherAssert.assertThat(
+ "dUkE".toLowerCase(),
+ Matchers.allOf(Matchers.equalTo("duke"), Matchers.hasLength(4), Matchers.endsWith("e")));
}
@Test
void customErrorMessage() {
- assertThrows(AssertionError.class, () -> {
- boolean boardingComplete = false;
-
- MatcherAssert
- .assertThat("Expecting boarding completed when last passenger enters the plane",
- boardingComplete, Matchers.is(true)
- );
- });
+ assertThrows(
+ AssertionError.class,
+ () -> {
+ boolean boardingComplete = false;
+
+ MatcherAssert.assertThat(
+ "Expecting boarding completed when last passenger enters the plane",
+ boardingComplete,
+ Matchers.is(true));
+ });
}
@Test
void advancedAssertions() throws ParserConfigurationException, IOException, SAXException {
- MatcherAssert
- .assertThat(List.of("duke", "mike", "alice", "john"), Matchers.allOf(
- Matchers.containsInAnyOrder("alice", "john", "mike", "duke"),
- Matchers.not(Matchers.emptyIterable())
- ));
-
- MatcherAssert
- .assertThat(List.of("duke", "mike", "alice", "john"),
- Matchers.everyItem(
- Matchers.anyOf(
- Matchers.hasLength(4),
- Matchers.endsWith("e")
- )));
-
- MatcherAssert
- .assertThat(
+ MatcherAssert.assertThat(
+ List.of("duke", "mike", "alice", "john"),
+ Matchers.allOf(
+ Matchers.containsInAnyOrder("alice", "john", "mike", "duke"),
+ Matchers.not(Matchers.emptyIterable())));
+
+ MatcherAssert.assertThat(
+ List.of("duke", "mike", "alice", "john"),
+ Matchers.everyItem(Matchers.anyOf(Matchers.hasLength(4), Matchers.endsWith("e"))));
+
+ MatcherAssert.assertThat(
BigDecimal.valueOf(39.99),
Matchers.closeTo(BigDecimal.valueOf(39.9985), BigDecimal.valueOf(0.01)));
- MatcherAssert
- .assertThat(39.99, Matchers.closeTo(39.9985, 0.01));
+ MatcherAssert.assertThat(39.99, Matchers.closeTo(39.9985, 0.01));
// XPath example
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
- Document xml = builder.parse(new InputSource(new StringReader("duke")));
-
- MatcherAssert
- .assertThat(xml, Matchers.allOf(
- Matchers.hasXPath("/customers/customer[1]/name", Matchers.is("duke")),
- Matchers.hasXPath("//*[@type='VIP']", Matchers.is("duke"))
- ));
+ Document xml =
+ builder.parse(
+ new InputSource(
+ new StringReader(
+ "duke")));
+
+ MatcherAssert.assertThat(
+ xml,
+ Matchers.allOf(
+ Matchers.hasXPath("/customers/customer[1]/name", Matchers.is("duke")),
+ Matchers.hasXPath("//*[@type='VIP']", Matchers.is("duke"))));
}
@Test
@@ -103,8 +100,11 @@ void customAssertions() {
MatcherAssert.assertThat(customer, hasOrderVolumeGreaterThan(BigDecimal.valueOf(999.99)));
- assertThrows(AssertionError.class,
- () -> MatcherAssert.assertThat(customer, hasOrderVolumeGreaterThan(BigDecimal.valueOf(9999.99))));
+ assertThrows(
+ AssertionError.class,
+ () ->
+ MatcherAssert.assertThat(
+ customer, hasOrderVolumeGreaterThan(BigDecimal.valueOf(9999.99))));
}
private Customer createTestCustomer(String username) {
@@ -113,15 +113,18 @@ private Customer createTestCustomer(String username) {
customer.setTags(Set.of("VIP", "PLATINUM_MEMBER", "EARLY_BIRD"));
customer.setUsername(username);
customer.setAddress(new Address("Berlin", "Germany", "12347"));
- customer.setOrders(List.of(
- new Order(List.of(
- new Product("MacBook Pro", BigDecimal.valueOf(1499.99), 3L),
- new Product("Kindle Paperwhite", BigDecimal.valueOf(149.00), 10L)
- ), "DEBIT"),
- new Order(List.of(
- new Product("Milk", BigDecimal.valueOf(0.99), 12L),
- new Product("Chocolate", BigDecimal.valueOf(2.99), 42L)
- ), "CREDIT_CARD")));
+ customer.setOrders(
+ List.of(
+ new Order(
+ List.of(
+ new Product("MacBook Pro", BigDecimal.valueOf(1499.99), 3L),
+ new Product("Kindle Paperwhite", BigDecimal.valueOf(149.00), 10L)),
+ "DEBIT"),
+ new Order(
+ List.of(
+ new Product("Milk", BigDecimal.valueOf(0.99), 12L),
+ new Product("Chocolate", BigDecimal.valueOf(2.99), 42L)),
+ "CREDIT_CARD")));
return customer;
}
diff --git a/testing-libraries-overview/src/test/java/de/rieckpil/blog/hamcrest/HasOrderVolumeGreaterThan.java b/testing-libraries-overview/src/test/java/de/rieckpil/blog/hamcrest/HasOrderVolumeGreaterThan.java
index 70c8408b..b3729d25 100644
--- a/testing-libraries-overview/src/test/java/de/rieckpil/blog/hamcrest/HasOrderVolumeGreaterThan.java
+++ b/testing-libraries-overview/src/test/java/de/rieckpil/blog/hamcrest/HasOrderVolumeGreaterThan.java
@@ -2,13 +2,12 @@
import de.rieckpil.blog.customer.Customer;
import de.rieckpil.blog.customer.Order;
+import java.math.BigDecimal;
+import java.util.List;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;
-import java.math.BigDecimal;
-import java.util.List;
-
public class HasOrderVolumeGreaterThan extends TypeSafeMatcher {
private BigDecimal expected;
@@ -40,11 +39,10 @@ public static Matcher hasOrderVolumeGreaterThan(BigDecimal expected) {
}
private BigDecimal calculateOrderVolume(List orders) {
- return orders
- .stream()
- .map(Order::getProducts)
- .flatMap(List::stream)
- .map(product -> product.getPrice().multiply(BigDecimal.valueOf(product.getQuantity())))
- .reduce(BigDecimal.ZERO, BigDecimal::add);
+ return orders.stream()
+ .map(Order::getProducts)
+ .flatMap(List::stream)
+ .map(product -> product.getPrice().multiply(BigDecimal.valueOf(product.getQuantity())))
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
}
}
diff --git a/testing-libraries-overview/src/test/java/de/rieckpil/blog/jsonassert/JSONAssertTest.java b/testing-libraries-overview/src/test/java/de/rieckpil/blog/jsonassert/JSONAssertTest.java
index b9e45a5f..cd693b7b 100644
--- a/testing-libraries-overview/src/test/java/de/rieckpil/blog/jsonassert/JSONAssertTest.java
+++ b/testing-libraries-overview/src/test/java/de/rieckpil/blog/jsonassert/JSONAssertTest.java
@@ -1,5 +1,9 @@
package de.rieckpil.blog.jsonassert;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.skyscreamer.jsonassert.JSONAssert.assertEquals;
+
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@@ -7,10 +11,6 @@
import org.skyscreamer.jsonassert.JSONAssert;
import org.skyscreamer.jsonassert.JSONCompareMode;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.skyscreamer.jsonassert.JSONAssert.assertEquals;
-
public class JSONAssertTest {
@Test
@@ -25,32 +25,35 @@ void assertionsForJsonObjects() throws JSONException {
// JUnit Jupiter import
assertEquals("JUnit Jupiter", "JUnit Jupiter");
- JSONObject object = new JSONObject()
- .put("name", "duke")
- .put("age", 42);
+ JSONObject object = new JSONObject().put("name", "duke").put("age", 42);
- assertThrows(AssertionError.class, () -> {
- JSONAssert.assertEquals("Missing or wrong id", "{id: 1337}", object, false);
- });
+ assertThrows(
+ AssertionError.class,
+ () -> {
+ JSONAssert.assertEquals("Missing or wrong id", "{id: 1337}", object, false);
+ });
}
@Test
void assertionsForJsonArrays() throws JSONException {
- JSONObject object = new JSONObject()
- .put("name", "duke")
- .put("age", 42)
- .put("tags", new JSONArray().put("VIP").put("Customer"));
+ JSONObject object =
+ new JSONObject()
+ .put("name", "duke")
+ .put("age", 42)
+ .put("tags", new JSONArray().put("VIP").put("Customer"));
JSONAssert.assertEquals("{name: 'duke', tags: ['VIP', 'Customer']}", object, false);
String result = "['mike', 'john', 'alice', 'anna']";
JSONAssert.assertEquals("['alice', 'anna', 'mike', 'john']", result, false);
- assertThrows(AssertionError.class, () -> {
- String failingExample = "['mike', 'john', 'alice', 'anna']";
- JSONAssert.assertEquals("['alice', 'anna', 'john']", failingExample, false);
- });
+ assertThrows(
+ AssertionError.class,
+ () -> {
+ String failingExample = "['mike', 'john', 'alice', 'anna']";
+ JSONAssert.assertEquals("['alice', 'anna', 'john']", failingExample, false);
+ });
}
@Test
@@ -58,9 +61,11 @@ void strictnessExample() throws JSONException {
String result = "{\"name\": \"duke\", \"age\":\"42\"}";
JSONAssert.assertEquals("{\"name\": \"duke\"}", result, false);
- assertThrows(AssertionError.class, () -> {
- JSONAssert.assertEquals("{\"name\": \"duke\"}", result, true);
- });
+ assertThrows(
+ AssertionError.class,
+ () -> {
+ JSONAssert.assertEquals("{\"name\": \"duke\"}", result, true);
+ });
}
@Test
@@ -68,30 +73,38 @@ void strictnessArrayExample() throws JSONException {
String result = "['mike', 'john', 'alice', 'anna']";
JSONAssert.assertEquals("['alice', 'anna', 'mike', 'john']", result, false);
- assertThrows(AssertionError.class, () -> {
- JSONAssert.assertEquals("['mike', 'alice', 'john', 'anna']", result, true);
- });
+ assertThrows(
+ AssertionError.class,
+ () -> {
+ JSONAssert.assertEquals("['mike', 'alice', 'john', 'anna']", result, true);
+ });
}
@Test
void strictnessFurtherExamples() throws JSONException {
String result = "{meetingId: 42, people: ['mike', 'john', 'alice']}";
- JSONAssert.assertEquals("{people: ['mike', 'john', 'alice']}",
- result, JSONCompareMode.STRICT_ORDER);
-
- JSONAssert.assertEquals("{meetingId: 42, people: ['john', 'alice', 'mike']}",
- result, JSONCompareMode.NON_EXTENSIBLE);
-
- assertThrows(AssertionError.class, () -> {
- JSONAssert.assertEquals("{people: ['mike', 'john', 'alice']}",
- result, JSONCompareMode.STRICT);
- JSONAssert.assertEquals("{people: ['john', 'alice', 'mike']}",
- result, JSONCompareMode.NON_EXTENSIBLE);
- });
-
- assertThrows(AssertionError.class, () -> {
- JSONAssert.assertEquals("['mike', 'alice', 'john', 'anna']", result, true);
- });
+ JSONAssert.assertEquals(
+ "{people: ['mike', 'john', 'alice']}", result, JSONCompareMode.STRICT_ORDER);
+
+ JSONAssert.assertEquals(
+ "{meetingId: 42, people: ['john', 'alice', 'mike']}",
+ result,
+ JSONCompareMode.NON_EXTENSIBLE);
+
+ assertThrows(
+ AssertionError.class,
+ () -> {
+ JSONAssert.assertEquals(
+ "{people: ['mike', 'john', 'alice']}", result, JSONCompareMode.STRICT);
+ JSONAssert.assertEquals(
+ "{people: ['john', 'alice', 'mike']}", result, JSONCompareMode.NON_EXTENSIBLE);
+ });
+
+ assertThrows(
+ AssertionError.class,
+ () -> {
+ JSONAssert.assertEquals("['mike', 'alice', 'john', 'anna']", result, true);
+ });
}
}
diff --git a/testing-libraries-overview/src/test/java/de/rieckpil/blog/jsonpath/JsonPayloadTest.java b/testing-libraries-overview/src/test/java/de/rieckpil/blog/jsonpath/JsonPayloadTest.java
index b42b2123..602f9852 100644
--- a/testing-libraries-overview/src/test/java/de/rieckpil/blog/jsonpath/JsonPayloadTest.java
+++ b/testing-libraries-overview/src/test/java/de/rieckpil/blog/jsonpath/JsonPayloadTest.java
@@ -1,15 +1,14 @@
package de.rieckpil.blog.jsonpath;
-import com.jayway.jsonpath.JsonPath;
-import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import com.jayway.jsonpath.JsonPath;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
+import org.junit.jupiter.api.Test;
class JsonPayloadTest {
@@ -17,9 +16,9 @@ class JsonPayloadTest {
static {
try {
- jsonPayload = new String(JsonPayloadTest.class
- .getResourceAsStream("/json/customers.json")
- .readAllBytes());
+ jsonPayload =
+ new String(
+ JsonPayloadTest.class.getResourceAsStream("/json/customers.json").readAllBytes());
} catch (IOException e) {
e.printStackTrace();
}
@@ -31,15 +30,23 @@ void basicAttributeAccess() {
String username = JsonPath.parse(jsonPayload).read("$[0].username");
String city = JsonPath.parse(jsonPayload).read("$[0].address.city");
-
List tags = JsonPath.parse(jsonPayload).read("$..tags[0,1,2]");
List productNames = JsonPath.parse(jsonPayload).read("$[1,2].orders[0]..name");
assertEquals("duke42", username);
assertEquals("Berlin", city);
- assertTrue(tags.containsAll(Arrays.asList("EARLY_BIRD", "VIP", "PLATINUM_MEMBER", "DELAYED_PAYMENTS", "BRONZE_MEMBER", "GOLD_MEMBER")));
- assertTrue(productNames.containsAll(Arrays.asList("iPhone 12", "Laptop", "MacBook Pro", "Kindle")));
+ assertTrue(
+ tags.containsAll(
+ Arrays.asList(
+ "EARLY_BIRD",
+ "VIP",
+ "PLATINUM_MEMBER",
+ "DELAYED_PAYMENTS",
+ "BRONZE_MEMBER",
+ "GOLD_MEMBER")));
+ assertTrue(
+ productNames.containsAll(Arrays.asList("iPhone 12", "Laptop", "MacBook Pro", "Kindle")));
}
@Test
@@ -78,13 +85,14 @@ void filterOperators() {
JsonPath.parse(jsonPayload).read("$[?(@.tags.size() > 2)]");
// We can also combine the expressions with || and &&
- JsonPath.parse(jsonPayload).read("$[?(@.tags.size() > 2 || @.address.city in ['Berlin', 'Paris'])]");
+ JsonPath.parse(jsonPayload)
+ .read("$[?(@.tags.size() > 2 || @.address.city in ['Berlin', 'Paris'])]");
// Which orders have more than one product for the customer duke42?
- JsonPath.parse(jsonPayload).read("$[?(@.username == 'duke42')].orders[?(@.products.length() > 1)]");
+ JsonPath.parse(jsonPayload)
+ .read("$[?(@.username == 'duke42')].orders[?(@.products.length() > 1)]");
// For which customers did we specify the continent as part of the address?
JsonPath.parse(jsonPayload).read("$[?(@.address.continent)]");
-
}
}
diff --git a/testing-libraries-overview/src/test/java/de/rieckpil/blog/junit4/DatabaseTestSuite.java b/testing-libraries-overview/src/test/java/de/rieckpil/blog/junit4/DatabaseTestSuite.java
index 06334cf9..d4da737e 100644
--- a/testing-libraries-overview/src/test/java/de/rieckpil/blog/junit4/DatabaseTestSuite.java
+++ b/testing-libraries-overview/src/test/java/de/rieckpil/blog/junit4/DatabaseTestSuite.java
@@ -1,12 +1,11 @@
package de.rieckpil.blog.junit4;
+import static org.junit.experimental.categories.Categories.*;
+
import org.junit.experimental.categories.Categories;
import org.junit.runner.RunWith;
-import static org.junit.experimental.categories.Categories.*;
-
@RunWith(Categories.class)
@IncludeCategory(DatabaseTests.class)
@SuiteClasses({JUnit4ExampleTest.class, RegistrationWebTest.class})
-public class DatabaseTestSuite {
-}
+public class DatabaseTestSuite {}
diff --git a/testing-libraries-overview/src/test/java/de/rieckpil/blog/junit4/DatabaseTests.java b/testing-libraries-overview/src/test/java/de/rieckpil/blog/junit4/DatabaseTests.java
index eed09c01..acc59092 100644
--- a/testing-libraries-overview/src/test/java/de/rieckpil/blog/junit4/DatabaseTests.java
+++ b/testing-libraries-overview/src/test/java/de/rieckpil/blog/junit4/DatabaseTests.java
@@ -1,4 +1,3 @@
package de.rieckpil.blog.junit4;
-public interface DatabaseTests {
-}
+public interface DatabaseTests {}
diff --git a/testing-libraries-overview/src/test/java/de/rieckpil/blog/junit4/JUnit4ExampleTest.java b/testing-libraries-overview/src/test/java/de/rieckpil/blog/junit4/JUnit4ExampleTest.java
index 39fd0303..0ff53aed 100644
--- a/testing-libraries-overview/src/test/java/de/rieckpil/blog/junit4/JUnit4ExampleTest.java
+++ b/testing-libraries-overview/src/test/java/de/rieckpil/blog/junit4/JUnit4ExampleTest.java
@@ -1,11 +1,10 @@
package de.rieckpil.blog.junit4;
import de.rieckpil.blog.registration.User;
+import java.math.BigDecimal;
import org.junit.*;
import org.junit.experimental.categories.Category;
-import java.math.BigDecimal;
-
public class JUnit4ExampleTest {
@Before
@@ -49,9 +48,7 @@ public void shouldThrowException() {
@Test
@Category(DatabaseTests.class)
- public void testDatabaseQuery() {
-
- }
+ public void testDatabaseQuery() {}
@Test
public void assertionExamples() {
@@ -61,21 +58,22 @@ public void assertionExamples() {
int[] openInvoiceIds = {42, 13, 7};
- Assert.assertEquals("Message on failure", 42L, 40L + 2L);
- Assert.assertNotEquals("duke", "gopher");
-
- Assert.assertTrue("Message on failure", 4 % 2 == 0);
+ Assert.assertEquals("Message on failure", 42L, 40L + 2L);
+ Assert.assertNotEquals("duke", "gopher");
- Assert.assertNotNull(new BigDecimal("42"));
+ Assert.assertTrue("Message on failure", 4 % 2 == 0);
- Assert.assertThrows(ArithmeticException.class, () -> {
- int result = 4 / 0;
- });
+ Assert.assertNotNull(new BigDecimal("42"));
- // checks for equal object references using ==
- Assert.assertSame(userOne, userTwo);
+ Assert.assertThrows(
+ ArithmeticException.class,
+ () -> {
+ int result = 4 / 0;
+ });
- Assert.assertArrayEquals(new int[]{42, 13, 7}, openInvoiceIds);
+ // checks for equal object references using ==
+ Assert.assertSame(userOne, userTwo);
+ Assert.assertArrayEquals(new int[] {42, 13, 7}, openInvoiceIds);
}
}
diff --git a/testing-libraries-overview/src/test/java/de/rieckpil/blog/junit4/RegistrationWebTest.java b/testing-libraries-overview/src/test/java/de/rieckpil/blog/junit4/RegistrationWebTest.java
index 5037b983..aa399b0d 100644
--- a/testing-libraries-overview/src/test/java/de/rieckpil/blog/junit4/RegistrationWebTest.java
+++ b/testing-libraries-overview/src/test/java/de/rieckpil/blog/junit4/RegistrationWebTest.java
@@ -7,7 +7,5 @@
public class RegistrationWebTest {
@Test
- public void shouldRegisterANewUser() {
-
- }
+ public void shouldRegisterANewUser() {}
}
diff --git a/testing-libraries-overview/src/test/java/de/rieckpil/blog/junit4/RuleExampleTest.java b/testing-libraries-overview/src/test/java/de/rieckpil/blog/junit4/RuleExampleTest.java
index d1f816da..574ffcfd 100644
--- a/testing-libraries-overview/src/test/java/de/rieckpil/blog/junit4/RuleExampleTest.java
+++ b/testing-libraries-overview/src/test/java/de/rieckpil/blog/junit4/RuleExampleTest.java
@@ -1,16 +1,14 @@
package de.rieckpil.blog.junit4;
+import java.io.File;
+import java.io.IOException;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
-import java.io.File;
-import java.io.IOException;
-
public class RuleExampleTest {
- @Rule
- public final TemporaryFolder tmpFolder = new TemporaryFolder();
+ @Rule public final TemporaryFolder tmpFolder = new TemporaryFolder();
@Test
public void testFileHandling() throws IOException {
diff --git a/testing-libraries-overview/src/test/java/de/rieckpil/blog/junit4/SmokeTests.java b/testing-libraries-overview/src/test/java/de/rieckpil/blog/junit4/SmokeTests.java
index 3915448f..2ab366e6 100644
--- a/testing-libraries-overview/src/test/java/de/rieckpil/blog/junit4/SmokeTests.java
+++ b/testing-libraries-overview/src/test/java/de/rieckpil/blog/junit4/SmokeTests.java
@@ -1,4 +1,3 @@
package de.rieckpil.blog.junit4;
-public interface SmokeTests {
-}
+public interface SmokeTests {}
diff --git a/testing-libraries-overview/src/test/java/de/rieckpil/blog/junit5/ExtensionExampleTest.java b/testing-libraries-overview/src/test/java/de/rieckpil/blog/junit5/ExtensionExampleTest.java
index fdece3db..687095b5 100644
--- a/testing-libraries-overview/src/test/java/de/rieckpil/blog/junit5/ExtensionExampleTest.java
+++ b/testing-libraries-overview/src/test/java/de/rieckpil/blog/junit5/ExtensionExampleTest.java
@@ -1,10 +1,10 @@
package de.rieckpil.blog.junit5;
+import static de.rieckpil.blog.junit5.RandomUUIDParameterResolver.*;
+
import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.extension.ExtendWith;
-import static de.rieckpil.blog.junit5.RandomUUIDParameterResolver.*;
-
@ExtendWith(RandomUUIDParameterResolver.class)
public class ExtensionExampleTest {
diff --git a/testing-libraries-overview/src/test/java/de/rieckpil/blog/junit5/JUnit5ExampleTest.java b/testing-libraries-overview/src/test/java/de/rieckpil/blog/junit5/JUnit5ExampleTest.java
index 916b464d..0e9feed7 100644
--- a/testing-libraries-overview/src/test/java/de/rieckpil/blog/junit5/JUnit5ExampleTest.java
+++ b/testing-libraries-overview/src/test/java/de/rieckpil/blog/junit5/JUnit5ExampleTest.java
@@ -1,10 +1,10 @@
package de.rieckpil.blog.junit5;
+
// tag::JUnitExampleTest[]
import de.rieckpil.blog.registration.User;
-import org.junit.jupiter.api.*;
-
import java.math.BigDecimal;
+import org.junit.jupiter.api.*;
class JUnit5ExampleTest {
@@ -35,11 +35,13 @@ void basicTestExample() {
@Test
@Timeout(5)
- // default time unit is seconds
+ // default time unit is seconds
void shouldThrowException() {
- Assertions.assertThrows(RuntimeException.class, () -> {
- throw new RuntimeException("Error");
- });
+ Assertions.assertThrows(
+ RuntimeException.class,
+ () -> {
+ throw new RuntimeException("Error");
+ });
}
@Test
@@ -69,15 +71,16 @@ void assertionExamples() {
Assertions.assertNotNull(new BigDecimal("42"));
- Assertions.assertThrows(ArithmeticException.class, () -> {
- int result = 4 / 0;
- });
+ Assertions.assertThrows(
+ ArithmeticException.class,
+ () -> {
+ int result = 4 / 0;
+ });
// checks for equal object references using ==
Assertions.assertSame(userOne, userTwo);
- Assertions.assertArrayEquals(new int[]{42, 13, 7}, openInvoiceIds);
-
+ Assertions.assertArrayEquals(new int[] {42, 13, 7}, openInvoiceIds);
}
}
// end::JUnitExampleTest[]
diff --git a/testing-libraries-overview/src/test/java/de/rieckpil/blog/junit5/RandomUUIDParameterResolver.java b/testing-libraries-overview/src/test/java/de/rieckpil/blog/junit5/RandomUUIDParameterResolver.java
index 167af3ad..4ac29414 100644
--- a/testing-libraries-overview/src/test/java/de/rieckpil/blog/junit5/RandomUUIDParameterResolver.java
+++ b/testing-libraries-overview/src/test/java/de/rieckpil/blog/junit5/RandomUUIDParameterResolver.java
@@ -1,30 +1,29 @@
package de.rieckpil.blog.junit5;
-import org.junit.jupiter.api.extension.ExtensionContext;
-import org.junit.jupiter.api.extension.ParameterContext;
-import org.junit.jupiter.api.extension.ParameterResolutionException;
-import org.junit.jupiter.api.extension.ParameterResolver;
-
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.UUID;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.api.extension.ParameterContext;
+import org.junit.jupiter.api.extension.ParameterResolver;
public class RandomUUIDParameterResolver implements ParameterResolver {
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
- public @interface RandomUUID {
- }
+ public @interface RandomUUID {}
@Override
- public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
+ public boolean supportsParameter(
+ ParameterContext parameterContext, ExtensionContext extensionContext) {
return parameterContext.isAnnotated(RandomUUID.class);
}
@Override
- public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
+ public Object resolveParameter(
+ ParameterContext parameterContext, ExtensionContext extensionContext) {
return UUID.randomUUID().toString();
}
}
diff --git a/testing-libraries-overview/src/test/java/de/rieckpil/blog/junit5/RegistrationWebTest.java b/testing-libraries-overview/src/test/java/de/rieckpil/blog/junit5/RegistrationWebTest.java
index 3dd82f46..1d2ac285 100644
--- a/testing-libraries-overview/src/test/java/de/rieckpil/blog/junit5/RegistrationWebTest.java
+++ b/testing-libraries-overview/src/test/java/de/rieckpil/blog/junit5/RegistrationWebTest.java
@@ -7,7 +7,5 @@
class RegistrationWebTest {
@Test
- void shouldRegisterANewUser() {
-
- }
+ void shouldRegisterANewUser() {}
}
diff --git a/testing-libraries-overview/src/test/java/de/rieckpil/blog/mockwebserver/MockWebServerTest.java b/testing-libraries-overview/src/test/java/de/rieckpil/blog/mockwebserver/MockWebServerTest.java
index d1928bfe..8ad598f7 100644
--- a/testing-libraries-overview/src/test/java/de/rieckpil/blog/mockwebserver/MockWebServerTest.java
+++ b/testing-libraries-overview/src/test/java/de/rieckpil/blog/mockwebserver/MockWebServerTest.java
@@ -1,6 +1,14 @@
package de.rieckpil.blog.mockwebserver;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
import de.rieckpil.blog.client.JavaHttpClient;
+import java.io.IOException;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.util.concurrent.TimeUnit;
import okhttp3.mockwebserver.Dispatcher;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
@@ -9,15 +17,6 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import java.io.IOException;
-import java.net.URI;
-import java.net.http.HttpClient;
-import java.net.http.HttpRequest;
-import java.net.http.HttpResponse;
-import java.util.concurrent.TimeUnit;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
public class MockWebServerTest {
private JavaHttpClient cut;
@@ -27,10 +26,12 @@ public class MockWebServerTest {
static {
try {
- DEFAULT_RESPONSE = new String(MockWebServerTest.class
- .getClassLoader()
- .getResourceAsStream("stubs/random-quote-success.json")
- .readAllBytes());
+ DEFAULT_RESPONSE =
+ new String(
+ MockWebServerTest.class
+ .getClassLoader()
+ .getResourceAsStream("stubs/random-quote-success.json")
+ .readAllBytes());
} catch (IOException e) {
e.printStackTrace();
}
@@ -51,22 +52,25 @@ void shutdown() throws IOException {
@Test
void shouldReturnRandomQuoteOn200Response() throws IOException {
- MockResponse mockResponse = new MockResponse()
- .addHeader("Content-Type", "application/json; charset=utf-8")
- .setBody(DEFAULT_RESPONSE);
+ MockResponse mockResponse =
+ new MockResponse()
+ .addHeader("Content-Type", "application/json; charset=utf-8")
+ .setBody(DEFAULT_RESPONSE);
mockWebServer.enqueue(mockResponse);
String randomQuote = this.cut.getRandomQuote();
- assertEquals(randomQuote, "Vision without action is daydream. Action without vision is nightmare");
+ assertEquals(
+ randomQuote, "Vision without action is daydream. Action without vision is nightmare");
}
@Test
void shouldReturnDefaultQuoteOnRequestFailure() {
- MockResponse mockResponse = new MockResponse()
- .addHeader("X-Error-Reason", "CloudProviderOutOfDiskSpace")
- .setResponseCode(500);
+ MockResponse mockResponse =
+ new MockResponse()
+ .addHeader("X-Error-Reason", "CloudProviderOutOfDiskSpace")
+ .setResponseCode(500);
mockWebServer.enqueue(mockResponse);
@@ -77,30 +81,34 @@ void shouldReturnDefaultQuoteOnRequestFailure() {
@Test
void shouldReturnQuoteOnSlowResponse() throws IOException {
- MockResponse mockResponse = new MockResponse()
- .addHeader("Content-Type", "application/json; charset=utf-8")
- .setBody(DEFAULT_RESPONSE)
- .setBodyDelay(2, TimeUnit.SECONDS);
+ MockResponse mockResponse =
+ new MockResponse()
+ .addHeader("Content-Type", "application/json; charset=utf-8")
+ .setBody(DEFAULT_RESPONSE)
+ .setBodyDelay(2, TimeUnit.SECONDS);
mockWebServer.enqueue(mockResponse);
String randomQuote = this.cut.getRandomQuote();
- assertEquals(randomQuote, "Vision without action is daydream. Action without vision is nightmare");
+ assertEquals(
+ randomQuote, "Vision without action is daydream. Action without vision is nightmare");
}
@Test
void shouldReturnRandomQuoteOn200ResponseVerification() throws IOException, InterruptedException {
- MockResponse mockResponse = new MockResponse()
- .addHeader("Content-Type", "application/json; charset=utf-8")
- .setBody(DEFAULT_RESPONSE);
+ MockResponse mockResponse =
+ new MockResponse()
+ .addHeader("Content-Type", "application/json; charset=utf-8")
+ .setBody(DEFAULT_RESPONSE);
mockWebServer.enqueue(mockResponse);
String randomQuote = this.cut.getRandomQuote();
- assertEquals(randomQuote, "Vision without action is daydream. Action without vision is nightmare");
+ assertEquals(
+ randomQuote, "Vision without action is daydream. Action without vision is nightmare");
RecordedRequest recordedRequest = mockWebServer.takeRequest();
assertEquals("/mock/qod", recordedRequest.getPath());
@@ -111,31 +119,37 @@ void shouldReturnRandomQuoteOn200ResponseVerification() throws IOException, Inte
@Test
void shouldMultipleResponseVerification() throws IOException, InterruptedException {
- MockResponse firstResponse = new MockResponse()
- .addHeader("Content-Type", "application/json; charset=utf-8")
- .setBody(DEFAULT_RESPONSE);
-
- MockResponse secondResponse = new MockResponse()
- .addHeader("Content-Type", "application/json; charset=utf-8")
- .setBody(new String(MockWebServerTest.class
- .getClassLoader()
- .getResourceAsStream("stubs/random-quote-success.json")
- .readAllBytes()));
+ MockResponse firstResponse =
+ new MockResponse()
+ .addHeader("Content-Type", "application/json; charset=utf-8")
+ .setBody(DEFAULT_RESPONSE);
+
+ MockResponse secondResponse =
+ new MockResponse()
+ .addHeader("Content-Type", "application/json; charset=utf-8")
+ .setBody(
+ new String(
+ MockWebServerTest.class
+ .getClassLoader()
+ .getResourceAsStream("stubs/random-quote-success.json")
+ .readAllBytes()));
mockWebServer.enqueue(firstResponse);
mockWebServer.enqueue(secondResponse);
String randomQuote = this.cut.getRandomQuote();
- HttpRequest request = HttpRequest.newBuilder()
- .uri(URI.create(mockWebServer.url("http://github.com/mock") + "/foo"))
- .header("X-Custom-Header", "Duke42")
- .DELETE()
- .build();
+ HttpRequest request =
+ HttpRequest.newBuilder()
+ .uri(URI.create(mockWebServer.url("http://github.com/mock") + "/foo"))
+ .header("X-Custom-Header", "Duke42")
+ .DELETE()
+ .build();
HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
- assertEquals(randomQuote, "Vision without action is daydream. Action without vision is nightmare");
+ assertEquals(
+ randomQuote, "Vision without action is daydream. Action without vision is nightmare");
RecordedRequest recordedRequestOne = mockWebServer.takeRequest();
assertEquals("/mock/qod", recordedRequestOne.getPath());
@@ -151,28 +165,30 @@ void shouldMultipleResponseVerification() throws IOException, InterruptedExcepti
@Test
void dispatcherExample() {
- final Dispatcher dispatcher = new Dispatcher() {
-
- @Override
- public MockResponse dispatch(RecordedRequest request) throws InterruptedException {
-
- switch (request.getPath()) {
- case "/mock/qod":
- return new MockResponse()
- .addHeader("Content-Type", "application/json; charset=utf-8")
- .setBody(DEFAULT_RESPONSE)
- .setResponseCode(200);
- case "/mock/foo":
- return new MockResponse().setResponseCode(500).setBody("SERVER DOWN");
- }
- return new MockResponse().setResponseCode(404);
- }
- };
+ final Dispatcher dispatcher =
+ new Dispatcher() {
+
+ @Override
+ public MockResponse dispatch(RecordedRequest request) throws InterruptedException {
+
+ switch (request.getPath()) {
+ case "/mock/qod":
+ return new MockResponse()
+ .addHeader("Content-Type", "application/json; charset=utf-8")
+ .setBody(DEFAULT_RESPONSE)
+ .setResponseCode(200);
+ case "/mock/foo":
+ return new MockResponse().setResponseCode(500).setBody("SERVER DOWN");
+ }
+ return new MockResponse().setResponseCode(404);
+ }
+ };
mockWebServer.setDispatcher(dispatcher);
String randomQuote = this.cut.getRandomQuote();
- assertEquals(randomQuote, "Vision without action is daydream. Action without vision is nightmare");
+ assertEquals(
+ randomQuote, "Vision without action is daydream. Action without vision is nightmare");
}
}
diff --git a/testing-libraries-overview/src/test/java/de/rieckpil/blog/registration/UserRegistrationServiceTest.java b/testing-libraries-overview/src/test/java/de/rieckpil/blog/registration/UserRegistrationServiceTest.java
index ea373d8c..1e1a74e4 100644
--- a/testing-libraries-overview/src/test/java/de/rieckpil/blog/registration/UserRegistrationServiceTest.java
+++ b/testing-libraries-overview/src/test/java/de/rieckpil/blog/registration/UserRegistrationServiceTest.java
@@ -1,8 +1,12 @@
package de.rieckpil.blog.registration;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
-import org.junit.jupiter.api.extension.RegisterExtension;
import org.mockito.ArgumentMatchers;
import org.mockito.InjectMocks;
import org.mockito.Mock;
@@ -11,20 +15,13 @@
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
class UserRegistrationServiceTest {
- @Mock
- private UserRepository userRepository;
+ @Mock private UserRepository userRepository;
- @InjectMocks
- private UserRegistrationService cut;
+ @InjectMocks private UserRegistrationService cut;
@Test
void shouldNotReCreateExistingUserWrongStubbing() {
@@ -40,31 +37,32 @@ void shouldNotReCreateExistingUser() {
// Or be more generic
Mockito.when(userRepository.findByUsername(ArgumentMatchers.anyString()))
- .thenReturn(new User());
+ .thenReturn(new User());
User result = this.cut.registerUser("duke");
}
-@Test
-void shouldPropagateException() {
- Mockito.when(userRepository.findByUsername("devil"))
- .thenThrow(new RuntimeException("DEVIL'S SQL EXCEPTION"));
+ @Test
+ void shouldPropagateException() {
+ Mockito.when(userRepository.findByUsername("devil"))
+ .thenThrow(new RuntimeException("DEVIL'S SQL EXCEPTION"));
- assertThrows(RuntimeException.class, () -> cut.registerUser("devil"));
+ assertThrows(RuntimeException.class, () -> cut.registerUser("devil"));
- Mockito.verify(userRepository, never()).save(ArgumentMatchers.any(User.class));
- Mockito.verify(userRepository, times(1)).findByUsername("devil");
-}
+ Mockito.verify(userRepository, never()).save(ArgumentMatchers.any(User.class));
+ Mockito.verify(userRepository, times(1)).findByUsername("devil");
+ }
@Test
void shouldCreateUnknownUser() {
Mockito.when(userRepository.findByUsername("duke")).thenReturn(null);
Mockito.when(userRepository.save(ArgumentMatchers.any(User.class)))
- .thenAnswer(context -> {
- User user = context.getArgument(0);
- user.setId(42L);
- return user;
- });
+ .thenAnswer(
+ context -> {
+ User user = context.getArgument(0);
+ user.setId(42L);
+ return user;
+ });
User result = this.cut.registerUser("duke");
diff --git a/testing-libraries-overview/src/test/java/de/rieckpil/blog/restassured/CustomerControllerTest.java b/testing-libraries-overview/src/test/java/de/rieckpil/blog/restassured/CustomerControllerTest.java
index fa7177de..3b8677cc 100644
--- a/testing-libraries-overview/src/test/java/de/rieckpil/blog/restassured/CustomerControllerTest.java
+++ b/testing-libraries-overview/src/test/java/de/rieckpil/blog/restassured/CustomerControllerTest.java
@@ -1,40 +1,41 @@
package de.rieckpil.blog.restassured;
+import static io.restassured.RestAssured.get;
+import static io.restassured.RestAssured.given;
+import static org.hamcrest.Matchers.*;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+
import io.restassured.builder.RequestSpecBuilder;
import io.restassured.builder.ResponseSpecBuilder;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
-import org.junit.jupiter.api.Test;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.boot.web.server.LocalServerPort;
-
import java.net.URI;
import java.util.List;
-
-import static io.restassured.RestAssured.get;
-import static io.restassured.RestAssured.given;
-import static org.hamcrest.Matchers.*;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.web.server.LocalServerPort;
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
+@Disabled("to be fixed, Groovy incompatibility issues")
class CustomerControllerTest {
- @LocalServerPort
- private Integer port;
+ @LocalServerPort private Integer port;
@Test
void basicRESTAssuredJSONExample() {
given()
- .accept("application/json")
- .header("X-Custom-Header", "Duke")
- .auth().basic("duke", "secret")
- .when()
- .get(URI.create("http://localhost/" + port + "/api/customers"))
- .then()
- .statusCode(200)
- .header("Content-Type", equalTo("application/json"))
- .body("[0].username", equalTo("duke42"));
+ .accept("application/json")
+ .header("X-Custom-Header", "Duke")
+ .auth()
+ .basic("duke", "secret")
+ .when()
+ .get(URI.create("http://localhost/" + port + "/api/customers"))
+ .then()
+ .statusCode(200)
+ .header("Content-Type", equalTo("application/json"))
+ .body("[0].username", equalTo("duke42"));
}
@Test
@@ -51,54 +52,54 @@ void advancedRESTAssuredJSONVerification() {
// What is the total order amount for the first customer?
get(uri)
- .then()
- .body("[0].orders.collect{it.products}.flatten().sum{it.price * it.quantity}", greaterThan(6000.00));
+ .then()
+ .body(
+ "[0].orders.collect{it.products}.flatten().sum{it.price * it.quantity}",
+ greaterThan(6000.00));
// Which customer has the most tags?
- get(uri)
- .then()
- .body("max{ it.tags.size() }.username", equalTo("duke42"));
+ get(uri).then().body("max{ it.tags.size() }.username", equalTo("duke42"));
// Which products where ordered with a quantity >= 42?
get(uri)
- .then()
- .body("collectMany{c -> c.orders.collect { it.products }}.flatten().findAll{it.quantity >= 42}.name",
- hasItems("Chocolate", "Chewing Gum"));
-
+ .then()
+ .body(
+ "collectMany{c -> c.orders.collect { it.products }}.flatten().findAll{it.quantity >= 42}.name",
+ hasItems("Chocolate", "Chewing Gum"));
}
@Test
void basicRESTAssuredXMLExample() {
given()
- .accept("application/xml")
- .header("X-Custom-Header", "Duke")
- .auth().basic("duke", "secret")
- .when()
- .get(URI.create("http://localhost/" + port + "/api/customers"))
- .then()
- .statusCode(200)
- .header("Content-Type", equalTo("application/xml"))
- .body("List.item[0].username", equalTo("duke42"));
-
+ .accept("application/xml")
+ .header("X-Custom-Header", "Duke")
+ .auth()
+ .basic("duke", "secret")
+ .when()
+ .get(URI.create("http://localhost/" + port + "/api/customers"))
+ .then()
+ .statusCode(200)
+ .header("Content-Type", equalTo("application/xml"))
+ .body("List.item[0].username", equalTo("duke42"));
}
@Test
void advancedRESTAssuredXMLVerification() {
URI uri = URI.create("http://localhost/" + port + "/api/customers");
- List tagList = given().accept("application/xml")
- .get(uri).xmlPath().getList("List.item[0].tags.tag");
+ List tagList =
+ given().accept("application/xml").get(uri).xmlPath().getList("List.item[0].tags.tag");
assertEquals(3, tagList.size());
// Which customers has the least tags?
given()
- .accept("application/xml")
- .when()
- .get(uri)
- .then()
- .body("List.item.min { it.tags.tag.size() }.username", equalTo("bob"));
+ .accept("application/xml")
+ .when()
+ .get(uri)
+ .then()
+ .body("List.item.min { it.tags.tag.size() }.username", equalTo("bob"));
}
@Test
@@ -118,13 +119,12 @@ void requestAndResponseSpecificationReuse() {
ResponseSpecification entityCreationSpec = responseSpecBuilder.build();
given()
- .spec(entityCreationRequest)
- .header("X-Super-Important", "secret")
- .when()
- .post("/api/customers")
- .then()
- .spec(entityCreationSpec)
- .body(emptyString());
-
+ .spec(entityCreationRequest)
+ .header("X-Super-Important", "secret")
+ .when()
+ .post("/api/customers")
+ .then()
+ .spec(entityCreationSpec)
+ .body(emptyString());
}
}
diff --git a/testing-libraries-overview/src/test/java/de/rieckpil/blog/selenide/DashboardControllerTest.java b/testing-libraries-overview/src/test/java/de/rieckpil/blog/selenide/DashboardControllerTest.java
index 18970252..f85cf604 100644
--- a/testing-libraries-overview/src/test/java/de/rieckpil/blog/selenide/DashboardControllerTest.java
+++ b/testing-libraries-overview/src/test/java/de/rieckpil/blog/selenide/DashboardControllerTest.java
@@ -1,5 +1,7 @@
package de.rieckpil.blog.selenide;
+import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
+
import com.codeborne.selenide.CollectionCondition;
import com.codeborne.selenide.Condition;
import com.codeborne.selenide.Configuration;
@@ -10,16 +12,13 @@
import org.openqa.selenium.By;
import org.openqa.selenium.chrome.ChromeOptions;
import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.boot.web.server.LocalServerPort;
-
-import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
+import org.springframework.boot.test.web.server.LocalServerPort;
@Disabled("Showcase only")
@SpringBootTest(webEnvironment = RANDOM_PORT)
class DashboardControllerWebTest {
- @LocalServerPort
- private Integer port;
+ @LocalServerPort private Integer port;
@BeforeAll
static void configure() {
diff --git a/testing-libraries-overview/src/test/java/de/rieckpil/blog/testcontainers/BasicContainerTest.java b/testing-libraries-overview/src/test/java/de/rieckpil/blog/testcontainers/BasicContainerTest.java
index b26b7a1d..d9a8400c 100644
--- a/testing-libraries-overview/src/test/java/de/rieckpil/blog/testcontainers/BasicContainerTest.java
+++ b/testing-libraries-overview/src/test/java/de/rieckpil/blog/testcontainers/BasicContainerTest.java
@@ -1,5 +1,7 @@
package de.rieckpil.blog.testcontainers;
+import java.io.IOException;
+import java.util.Map;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.BindMode;
import org.testcontainers.containers.Container.ExecResult;
@@ -9,29 +11,26 @@
import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.utility.DockerImageName;
-import java.io.IOException;
-import java.util.Map;
-
@Testcontainers
public class BasicContainerTest {
@Container
static GenericContainer> keycloak =
- new GenericContainer<>(DockerImageName.parse("jboss/keycloak:11.0.0"))
- .waitingFor(Wait.forHttp("/auth").forStatusCode(200))
- .withExposedPorts(8080)
- .withClasspathResourceMapping("/config/test.txt", "/tmp/test.txt", BindMode.READ_WRITE)
- .withEnv(Map.of(
- "KEYCLOAK_USER", "testcontainers",
- "KEYCLOAK_PASSWORD", "testcontainers",
- "DB_VENDOR", "h2"
- ));
+ new GenericContainer<>(DockerImageName.parse("quay.io/keycloak/keycloak:19.0.3-legacy"))
+ .waitingFor(Wait.forHttp("/auth").forStatusCode(200))
+ .withExposedPorts(8080)
+ .withClasspathResourceMapping("/config/test.txt", "/tmp/test.txt", BindMode.READ_WRITE)
+ .withEnv(
+ Map.of(
+ "KEYCLOAK_USER", "testcontainers",
+ "KEYCLOAK_PASSWORD", "testcontainers",
+ "DB_VENDOR", "h2"));
@Test
void testWithKeycloak() throws IOException, InterruptedException {
- ExecResult execResult = keycloak
- .execInContainer("/bin/sh", "-c", "echo \"Admin user is $KEYCLOAK_USER\"");
+ ExecResult execResult =
+ keycloak.execInContainer("/bin/sh", "-c", "echo \"Admin user is $KEYCLOAK_USER\"");
System.out.println("Result: " + execResult.getStdout());
System.out.println("Keycloak is running on port: " + keycloak.getMappedPort(8080));
diff --git a/testing-libraries-overview/src/test/java/de/rieckpil/blog/testcontainers/DockerComposeTest.java b/testing-libraries-overview/src/test/java/de/rieckpil/blog/testcontainers/DockerComposeTest.java
index f006e6bf..1f301ab8 100644
--- a/testing-libraries-overview/src/test/java/de/rieckpil/blog/testcontainers/DockerComposeTest.java
+++ b/testing-libraries-overview/src/test/java/de/rieckpil/blog/testcontainers/DockerComposeTest.java
@@ -1,30 +1,28 @@
package de.rieckpil.blog.testcontainers;
+import java.io.File;
+import java.time.Duration;
import org.junit.jupiter.api.Test;
-import org.testcontainers.containers.DockerComposeContainer;
+import org.testcontainers.containers.ComposeContainer;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
-import java.io.File;
-import java.time.Duration;
-
@Testcontainers
public class DockerComposeTest {
@Container
- static DockerComposeContainer> environment =
- new DockerComposeContainer<>(new File("docker-compose.yml"))
- .withExposedService("database_1", 5432, Wait.forListeningPort())
- .withExposedService("keycloak_1", 8080,
- Wait.forHttp("/auth").forStatusCode(200)
- .withStartupTimeout(Duration.ofSeconds(30)));
-
+ static ComposeContainer environment =
+ new ComposeContainer(new File("docker-compose.yml"))
+ .withExposedService("database-1", 5432, Wait.forListeningPort())
+ .withExposedService(
+ "keycloak-1",
+ 8080,
+ Wait.forHttp("/auth").forStatusCode(200).withStartupTimeout(Duration.ofSeconds(30)));
@Test
void dockerComposeTest() {
- System.out.println(environment.getServicePort("database_1", 5432));
- System.out.println(environment.getServicePort("keycloak_1", 8080));
+ System.out.println(environment.getServicePort("database-1", 5432));
+ System.out.println(environment.getServicePort("keycloak-1", 8080));
}
-
}
diff --git a/testing-libraries-overview/src/test/java/de/rieckpil/blog/testcontainers/ModuleContainerTest.java b/testing-libraries-overview/src/test/java/de/rieckpil/blog/testcontainers/ModuleContainerTest.java
index aec45412..d05e5cc5 100644
--- a/testing-libraries-overview/src/test/java/de/rieckpil/blog/testcontainers/ModuleContainerTest.java
+++ b/testing-libraries-overview/src/test/java/de/rieckpil/blog/testcontainers/ModuleContainerTest.java
@@ -9,11 +9,12 @@
public class ModuleContainerTest {
@Container
- static PostgreSQLContainer database = new PostgreSQLContainer<>("postgres:12")
- .withUsername("duke")
- .withPassword("secret")
- .withInitScript("config/INIT.sql")
- .withDatabaseName("tescontainers");
+ static PostgreSQLContainer database =
+ new PostgreSQLContainer<>("postgres:12")
+ .withUsername("duke")
+ .withPassword("secret")
+ .withInitScript("config/INIT.sql")
+ .withDatabaseName("tescontainers");
@Test
void testPostgreSQLModule() {
diff --git a/testing-libraries-overview/src/test/java/de/rieckpil/blog/testng/ReviewValidationTest.java b/testing-libraries-overview/src/test/java/de/rieckpil/blog/testng/ReviewValidationTest.java
index 21bface4..7e92df66 100644
--- a/testing-libraries-overview/src/test/java/de/rieckpil/blog/testng/ReviewValidationTest.java
+++ b/testing-libraries-overview/src/test/java/de/rieckpil/blog/testng/ReviewValidationTest.java
@@ -1,11 +1,10 @@
package de.rieckpil.blog.testng;
import de.rieckpil.blog.review.ReviewValidation;
+import java.lang.reflect.Method;
import org.testng.Assert;
import org.testng.annotations.*;
-import java.lang.reflect.Method;
-
public class ReviewValidationTest {
private ReviewValidation cut;
@@ -52,7 +51,9 @@ public void shouldAllowTitlesOfHighQuality() {
Assert.assertTrue(result, "A title of high quality was rejected");
}
- @Test(groups = {"windows-only"}, enabled = false)
+ @Test(
+ groups = {"windows-only"},
+ enabled = false)
public void shouldDetectWindows() {
Assert.assertTrue(System.getProperty("os.name").contains("Windows"));
}
@@ -66,10 +67,8 @@ public void shouldFail() throws InterruptedException {
@DataProvider(name = "shortTitles")
public Object[][] createShortReviewTitles(Method method) {
System.out.println("Generating test data for method " + method.getName());
- return new Object[][]{
- {"ABCD"},
- {"Bad book"},
- {":("},
+ return new Object[][] {
+ {"ABCD"}, {"Bad book"}, {":("},
};
}
diff --git a/testing-libraries-overview/src/test/java/de/rieckpil/blog/wiremock/JavaHttpClientTest.java b/testing-libraries-overview/src/test/java/de/rieckpil/blog/wiremock/JavaHttpClientTest.java
index c0aa7dbf..43680368 100644
--- a/testing-libraries-overview/src/test/java/de/rieckpil/blog/wiremock/JavaHttpClientTest.java
+++ b/testing-libraries-overview/src/test/java/de/rieckpil/blog/wiremock/JavaHttpClientTest.java
@@ -1,19 +1,18 @@
package de.rieckpil.blog.wiremock;
+import static com.github.tomakehurst.wiremock.client.WireMock.*;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.client.WireMock;
import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
import com.github.tomakehurst.wiremock.stubbing.ServeEvent;
import com.github.tomakehurst.wiremock.verification.LoggedRequest;
import de.rieckpil.blog.client.JavaHttpClient;
-import org.junit.jupiter.api.*;
-import org.springframework.http.MediaType;
-
import java.io.IOException;
import java.util.List;
-
-import static com.github.tomakehurst.wiremock.client.WireMock.*;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import org.junit.jupiter.api.*;
+import org.springframework.http.MediaType;
class JavaHttpClientTest {
@@ -46,30 +45,30 @@ void tearDown() {
void shouldReturnRandomQuoteOn200Response() throws IOException {
wireMockServer.stubFor(
- WireMock.get("/qod")
- .willReturn(aResponse()
- .withHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE)
- .withBody(new String(JavaHttpClientTest.class
- .getClassLoader()
- .getResourceAsStream("stubs/random-quote-success.json")
- .readAllBytes())))
- );
+ WireMock.get("/qod")
+ .willReturn(
+ aResponse()
+ .withHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE)
+ .withBody(
+ new String(
+ JavaHttpClientTest.class
+ .getClassLoader()
+ .getResourceAsStream("stubs/random-quote-success.json")
+ .readAllBytes()))));
String randomQuote = this.cut.getRandomQuote();
- assertEquals(randomQuote, "Vision without action is daydream. Action without vision is nightmare");
+ assertEquals(
+ randomQuote, "Vision without action is daydream. Action without vision is nightmare");
}
@Test
void shouldReturnDefaultQuoteOnRequestFailure() {
wireMockServer.stubFor(
- WireMock.get("/qod")
- .willReturn(aResponse()
- .withStatus(500)
- .withBody("Server Down!")
- .withFixedDelay(2_000))
- );
+ WireMock.get("/qod")
+ .willReturn(
+ aResponse().withStatus(500).withBody("Server Down!").withFixedDelay(2_000)));
String randomQuote = this.cut.getRandomQuote();
@@ -80,22 +79,23 @@ void shouldReturnDefaultQuoteOnRequestFailure() {
void advancedStubbings() throws IOException {
wireMockServer.stubFor(
- WireMock.any(anyUrl())
- .withHeader("Accept", containing("json"))
- .atPriority(1)
- .willReturn(aResponse().withStatus(500))
- );
+ WireMock.any(anyUrl())
+ .withHeader("Accept", containing("json"))
+ .atPriority(1)
+ .willReturn(aResponse().withStatus(500)));
wireMockServer.stubFor(
- WireMock.get(anyUrl())
- .atPriority(10)
- .willReturn(aResponse()
- .withHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE)
- .withBody(new String(JavaHttpClientTest.class
- .getClassLoader()
- .getResourceAsStream("stubs/random-quote-success.json")
- .readAllBytes())))
- );
+ WireMock.get(anyUrl())
+ .atPriority(10)
+ .willReturn(
+ aResponse()
+ .withHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE)
+ .withBody(
+ new String(
+ JavaHttpClientTest.class
+ .getClassLoader()
+ .getResourceAsStream("stubs/random-quote-success.json")
+ .readAllBytes()))));
// the first stubbing with priority '1' will be used
String randomQuote = this.cut.getRandomQuote();
@@ -107,43 +107,47 @@ void advancedStubbings() throws IOException {
void shouldReturnRandomQuoteOn200ResponseVerification() throws IOException {
wireMockServer.stubFor(
- WireMock.get("/qod")
- .willReturn(aResponse()
- .withHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE)
- .withBody(new String(JavaHttpClientTest.class
- .getClassLoader()
- .getResourceAsStream("stubs/random-quote-success.json")
- .readAllBytes())))
- );
+ WireMock.get("/qod")
+ .willReturn(
+ aResponse()
+ .withHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE)
+ .withBody(
+ new String(
+ JavaHttpClientTest.class
+ .getClassLoader()
+ .getResourceAsStream("stubs/random-quote-success.json")
+ .readAllBytes()))));
String randomQuote = this.cut.getRandomQuote();
- wireMockServer.verify(exactly(1), getRequestedFor(urlEqualTo("/qod"))
- .withHeader("Accept", equalTo("application/json")));
+ wireMockServer.verify(
+ exactly(1),
+ getRequestedFor(urlEqualTo("/qod")).withHeader("Accept", equalTo("application/json")));
List allServeEvents = wireMockServer.getAllServeEvents();
LoggedRequest request = allServeEvents.get(0).getRequest();
assertEquals("", request.getBodyAsString());
- assertEquals(7, request.getAllHeaderKeys().size());
+ assertEquals(6, request.getAllHeaderKeys().size());
List unmatchedRequests = wireMockServer.findAllUnmatchedRequests();
assertEquals(0, unmatchedRequests.size());
- assertEquals(randomQuote, "Vision without action is daydream. Action without vision is nightmare");
+ assertEquals(
+ randomQuote, "Vision without action is daydream. Action without vision is nightmare");
}
@Test
void shouldNotMatchStubbing() {
wireMockServer.stubFor(
- WireMock.get("/differentUrl")
- .willReturn(aResponse()
- .withHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE)
- .withBody("duke42"))
- );
+ WireMock.get("/differentUrl")
+ .willReturn(
+ aResponse()
+ .withHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE)
+ .withBody("duke42")));
String randomQuote = this.cut.getRandomQuote();
}
diff --git a/testing-libraries-overview/src/test/java/de/rieckpil/blog/wiremock/WireMockSetupTest.java b/testing-libraries-overview/src/test/java/de/rieckpil/blog/wiremock/WireMockSetupTest.java
index 03e6a997..b3aee935 100644
--- a/testing-libraries-overview/src/test/java/de/rieckpil/blog/wiremock/WireMockSetupTest.java
+++ b/testing-libraries-overview/src/test/java/de/rieckpil/blog/wiremock/WireMockSetupTest.java
@@ -1,14 +1,14 @@
package de.rieckpil.blog.wiremock;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
public class WireMockSetupTest {
private static WireMockServer wireMockServer;
@@ -29,5 +29,4 @@ void test() {
assertNotNull(wireMockServer);
assertTrue(wireMockServer.isRunning());
}
-
}
diff --git a/testing-libraries-overview/src/test/java/de/rieckpil/blog/xmlunit/XMLUnitTest.java b/testing-libraries-overview/src/test/java/de/rieckpil/blog/xmlunit/XMLUnitTest.java
index 2ba157ff..9db79905 100644
--- a/testing-libraries-overview/src/test/java/de/rieckpil/blog/xmlunit/XMLUnitTest.java
+++ b/testing-libraries-overview/src/test/java/de/rieckpil/blog/xmlunit/XMLUnitTest.java
@@ -1,5 +1,10 @@
package de.rieckpil.blog.xmlunit;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.io.IOException;
+import javax.xml.transform.Source;
import org.assertj.core.util.Streams;
import org.hamcrest.CoreMatchers;
import org.hamcrest.MatcherAssert;
@@ -20,76 +25,76 @@
import org.xmlunit.xpath.JAXPXPathEngine;
import org.xmlunit.xpath.XPathEngine;
-import javax.xml.transform.Source;
-import java.io.IOException;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.jupiter.api.Assertions.*;
-
public class XMLUnitTest {
@Test
void compareTwoDocumentsJUnitJupiter() {
- Source expected = Input.fromStream(this.getClass().getResourceAsStream("/xml/customers.xml")).build();
+ Source expected =
+ Input.fromStream(this.getClass().getResourceAsStream("/xml/customers.xml")).build();
Source actual = Input.fromString("").build();
DifferenceEngine diff = new DOMDifferenceEngine();
- diff.addDifferenceListener((comparison, outcome) ->
- Assertions.fail("XML documents are not similar: " + comparison));
+ diff.addDifferenceListener(
+ (comparison, outcome) -> Assertions.fail("XML documents are not similar: " + comparison));
- assertThrows(AssertionError.class, () -> {
- diff.compare(expected, actual);
- });
+ assertThrows(
+ AssertionError.class,
+ () -> {
+ diff.compare(expected, actual);
+ });
}
@Test
void compareTwoDocumentsHamcrest() {
- Source expected = Input
- .fromStream(this.getClass().getResourceAsStream("/xml/customers.xml"))
- .build();
-
- Source actual = Input
- .fromString("")
- .build();
+ Source expected =
+ Input.fromStream(this.getClass().getResourceAsStream("/xml/customers.xml")).build();
- assertThrows(AssertionError.class, () -> {
- // Hamcrest
- MatcherAssert
- .assertThat(actual, CompareMatcher.isIdenticalTo(expected));
- });
+ Source actual = Input.fromString("").build();
+ assertThrows(
+ AssertionError.class,
+ () -> {
+ // Hamcrest
+ MatcherAssert.assertThat(actual, CompareMatcher.isIdenticalTo(expected));
+ });
}
@Test
void compareTwoDocumentsAssertJ() {
- Source expected = Input.fromStream(this.getClass().getResourceAsStream("/xml/customers.xml")).build();
+ Source expected =
+ Input.fromStream(this.getClass().getResourceAsStream("/xml/customers.xml")).build();
Source actual = Input.fromString("").build();
- assertThrows(AssertionError.class, () -> {
- // AssertJ
- XmlAssert.assertThat(expected)
- .and(actual)
- .areIdentical();
- });
+ assertThrows(
+ AssertionError.class,
+ () -> {
+ // AssertJ
+ XmlAssert.assertThat(expected).and(actual).areIdentical();
+ });
}
@Test
void xPathTestExample() throws IOException {
- Source responseBody = Input
- .fromString(new String(this.getClass().getResourceAsStream("/xml/customers.xml").readAllBytes()))
- .build();
+ Source responseBody =
+ Input.fromString(
+ new String(
+ this.getClass().getResourceAsStream("/xml/customers.xml").readAllBytes()))
+ .build();
XPathEngine xpath = new JAXPXPathEngine();
Iterable allCustomers = xpath.selectNodes("//customer", responseBody);
- Iterable amountOfVIPs = xpath.selectNodes("//customer/tags/tag[text()=\"VIP\"]", responseBody);
- Iterable amountOfLaptopOrders = xpath.selectNodes("//products/product/name[text()=\"Laptop\"]", responseBody);
- String cityNameLastCustomer = xpath.evaluate("//customer[last()]/address/city/text()", responseBody);
+ Iterable amountOfVIPs =
+ xpath.selectNodes("//customer/tags/tag[text()=\"VIP\"]", responseBody);
+ Iterable amountOfLaptopOrders =
+ xpath.selectNodes("//products/product/name[text()=\"Laptop\"]", responseBody);
+ String cityNameLastCustomer =
+ xpath.evaluate("//customer[last()]/address/city/text()", responseBody);
assertEquals(3, Streams.stream(allCustomers).count());
assertEquals(1, Streams.stream(amountOfVIPs).count());
@@ -103,8 +108,10 @@ void xPathTestExample() throws IOException {
MatcherAssert.assertThat(responseBody, HasXPathMatcher.hasXPath("//tags"));
- MatcherAssert.assertThat(responseBody,
- EvaluateXPathMatcher.hasXPath("//customer[last()]/address/city/text()", CoreMatchers.is("São Paulo")));
+ MatcherAssert.assertThat(
+ responseBody,
+ EvaluateXPathMatcher.hasXPath(
+ "//customer[last()]/address/city/text()", CoreMatchers.is("São Paulo")));
MatcherAssert.assertThat(responseBody, CoreMatchers.not(HasXPathMatcher.hasXPath("//cars")));
}
@@ -113,10 +120,12 @@ void xPathTestExample() throws IOException {
void xmlSchemaValidation() {
Validator validator = Validator.forLanguage(Languages.W3C_XML_SCHEMA_NS_URI);
- validator.setSchemaSource(Input.fromStream(XMLUnitTest.class.getResourceAsStream("/xml/customers.xsd")).build());
+ validator.setSchemaSource(
+ Input.fromStream(XMLUnitTest.class.getResourceAsStream("/xml/customers.xsd")).build());
- ValidationResult validationResult = validator
- .validateInstance(Input.fromStream(XMLUnitTest.class.getResourceAsStream("/xml/customers.xml")).build());
+ ValidationResult validationResult =
+ validator.validateInstance(
+ Input.fromStream(XMLUnitTest.class.getResourceAsStream("/xml/customers.xml")).build());
assertTrue(validationResult.isValid(), "XML payload did not match XSD");
}
@@ -124,10 +133,11 @@ void xmlSchemaValidation() {
@Test
void xmlSchemaValidationFailure() {
Validator validator = Validator.forLanguage(Languages.W3C_XML_SCHEMA_NS_URI);
- validator.setSchemaSource(Input.fromStream(XMLUnitTest.class.getResourceAsStream("/xml/customers.xsd")).build());
+ validator.setSchemaSource(
+ Input.fromStream(XMLUnitTest.class.getResourceAsStream("/xml/customers.xsd")).build());
- ValidationResult failingResult = validator
- .validateInstance(Input.fromString("").build());
+ ValidationResult failingResult =
+ validator.validateInstance(Input.fromString("").build());
assertFalse(failingResult.isValid(), "XML payload did match XSD");
diff --git a/testing-spring-boot-applications-with-mockmvc/pom.xml b/testing-spring-boot-applications-with-mockmvc/pom.xml
index 8c89b10a..3da2c208 100644
--- a/testing-spring-boot-applications-with-mockmvc/pom.xml
+++ b/testing-spring-boot-applications-with-mockmvc/pom.xml
@@ -2,22 +2,19 @@
4.0.0
+
- org.springframework.boot
- spring-boot-starter-parent
- 2.3.4.RELEASE
-
+ de.rieckpil.blog
+ blog-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
- de.rieckpil.blog
+
testing-spring-boot-applications-with-mockmvc
0.0.1-SNAPSHOT
testing-spring-boot-applications-with-mockmvc
Testing Spring Boot Applications with MockMvc
-
- 11
-
-
org.springframework.boot
@@ -40,12 +37,6 @@
org.springframework.boot
spring-boot-starter-test
test
-
-
- org.junit.vintage
- junit-vintage-engine
-
-
org.springframework.security
diff --git a/testing-spring-boot-applications-with-mockmvc/src/main/java/de/rieckpil/blog/Application.java b/testing-spring-boot-applications-with-mockmvc/src/main/java/de/rieckpil/blog/Application.java
index bd5e4c56..6511f3c1 100644
--- a/testing-spring-boot-applications-with-mockmvc/src/main/java/de/rieckpil/blog/Application.java
+++ b/testing-spring-boot-applications-with-mockmvc/src/main/java/de/rieckpil/blog/Application.java
@@ -9,5 +9,4 @@ public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
-
}
diff --git a/testing-spring-boot-applications-with-mockmvc/src/main/java/de/rieckpil/blog/SecurityConfig.java b/testing-spring-boot-applications-with-mockmvc/src/main/java/de/rieckpil/blog/SecurityConfig.java
index cc704b2f..850497f1 100644
--- a/testing-spring-boot-applications-with-mockmvc/src/main/java/de/rieckpil/blog/SecurityConfig.java
+++ b/testing-spring-boot-applications-with-mockmvc/src/main/java/de/rieckpil/blog/SecurityConfig.java
@@ -1,22 +1,30 @@
package de.rieckpil.blog;
+import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
+import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
-import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.web.SecurityFilterChain;
@Configuration
-public class SecurityConfig extends WebSecurityConfigurerAdapter {
+public class SecurityConfig {
- @Override
- protected void configure(HttpSecurity http) throws Exception {
- http
- .authorizeRequests(authorize -> authorize
- .mvcMatchers(HttpMethod.GET, "/dashboard").permitAll()
- .mvcMatchers(HttpMethod.GET, "/api/tasks/**").authenticated()
- .mvcMatchers("/api/users/**").permitAll()
- .mvcMatchers("/**").authenticated()
- )
- .httpBasic();
+ @Bean
+ public SecurityFilterChain configure(HttpSecurity http) throws Exception {
+ http.authorizeRequests(
+ authorize ->
+ authorize
+ .requestMatchers(HttpMethod.GET, "/dashboard")
+ .permitAll()
+ .requestMatchers(HttpMethod.GET, "/api/tasks/**")
+ .authenticated()
+ .requestMatchers("/api/users/**")
+ .permitAll()
+ .requestMatchers("/**")
+ .authenticated())
+ .httpBasic(Customizer.withDefaults());
+
+ return http.build();
}
}
diff --git a/testing-spring-boot-applications-with-mockmvc/src/main/java/de/rieckpil/blog/dashboard/DashboardService.java b/testing-spring-boot-applications-with-mockmvc/src/main/java/de/rieckpil/blog/dashboard/DashboardService.java
index 89574e86..5468c94b 100644
--- a/testing-spring-boot-applications-with-mockmvc/src/main/java/de/rieckpil/blog/dashboard/DashboardService.java
+++ b/testing-spring-boot-applications-with-mockmvc/src/main/java/de/rieckpil/blog/dashboard/DashboardService.java
@@ -5,6 +5,6 @@
@Service
public class DashboardService {
public Integer[] getAnalyticsGraphData() {
- return new Integer[]{1, 2, 3, 4, 5, 6};
+ return new Integer[] {1, 2, 3, 4, 5, 6};
}
}
diff --git a/testing-spring-boot-applications-with-mockmvc/src/main/java/de/rieckpil/blog/task/TaskController.java b/testing-spring-boot-applications-with-mockmvc/src/main/java/de/rieckpil/blog/task/TaskController.java
index 4b223e2c..9b0cfc35 100644
--- a/testing-spring-boot-applications-with-mockmvc/src/main/java/de/rieckpil/blog/task/TaskController.java
+++ b/testing-spring-boot-applications-with-mockmvc/src/main/java/de/rieckpil/blog/task/TaskController.java
@@ -1,12 +1,11 @@
package de.rieckpil.blog.task;
import com.fasterxml.jackson.databind.JsonNode;
+import jakarta.annotation.security.RolesAllowed;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.util.UriComponentsBuilder;
-import javax.annotation.security.RolesAllowed;
-
@RestController
@RequestMapping("/api/tasks")
public class TaskController {
@@ -18,13 +17,13 @@ public TaskController(TaskService taskService) {
}
@PostMapping
- public ResponseEntity createNewTask(@RequestBody JsonNode payload, UriComponentsBuilder uriComponentsBuilder) {
+ public ResponseEntity createNewTask(
+ @RequestBody JsonNode payload, UriComponentsBuilder uriComponentsBuilder) {
Long taskId = this.taskService.createTask(payload.get("taskTitle").asText());
- return ResponseEntity
- .created(uriComponentsBuilder.path("/api/tasks/{taskId}").build(taskId))
- .build();
+ return ResponseEntity.created(uriComponentsBuilder.path("/api/tasks/{taskId}").build(taskId))
+ .build();
}
@DeleteMapping
diff --git a/testing-spring-boot-applications-with-mockmvc/src/main/java/de/rieckpil/blog/task/TaskService.java b/testing-spring-boot-applications-with-mockmvc/src/main/java/de/rieckpil/blog/task/TaskService.java
index 3e514a75..d0bf3e86 100644
--- a/testing-spring-boot-applications-with-mockmvc/src/main/java/de/rieckpil/blog/task/TaskService.java
+++ b/testing-spring-boot-applications-with-mockmvc/src/main/java/de/rieckpil/blog/task/TaskService.java
@@ -1,8 +1,7 @@
package de.rieckpil.blog.task;
-import org.springframework.stereotype.Service;
-
import java.util.concurrent.ThreadLocalRandom;
+import org.springframework.stereotype.Service;
@Service
public class TaskService {
diff --git a/testing-spring-boot-applications-with-mockmvc/src/main/java/de/rieckpil/blog/user/User.java b/testing-spring-boot-applications-with-mockmvc/src/main/java/de/rieckpil/blog/user/User.java
index 6169070c..48054caa 100644
--- a/testing-spring-boot-applications-with-mockmvc/src/main/java/de/rieckpil/blog/user/User.java
+++ b/testing-spring-boot-applications-with-mockmvc/src/main/java/de/rieckpil/blog/user/User.java
@@ -1,18 +1,15 @@
package de.rieckpil.blog.user;
-import javax.validation.constraints.Email;
-import javax.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.Email;
+import jakarta.validation.constraints.NotEmpty;
public class User {
- @NotEmpty
- private String username;
+ @NotEmpty private String username;
- @Email
- private String email;
+ @Email private String email;
- public User() {
- }
+ public User() {}
public User(String username, String email) {
this.username = username;
diff --git a/testing-spring-boot-applications-with-mockmvc/src/main/java/de/rieckpil/blog/user/UserController.java b/testing-spring-boot-applications-with-mockmvc/src/main/java/de/rieckpil/blog/user/UserController.java
index 2955d444..7ae2c1be 100644
--- a/testing-spring-boot-applications-with-mockmvc/src/main/java/de/rieckpil/blog/user/UserController.java
+++ b/testing-spring-boot-applications-with-mockmvc/src/main/java/de/rieckpil/blog/user/UserController.java
@@ -1,13 +1,12 @@
package de.rieckpil.blog.user;
+import jakarta.validation.Valid;
+import java.util.List;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.util.UriComponentsBuilder;
-import javax.validation.Valid;
-import java.util.List;
-
@Validated
@RestController
@RequestMapping("/api/users")
@@ -31,10 +30,11 @@ public User getUserByUsername(@PathVariable String username) {
}
@PostMapping
- public ResponseEntity createNewUser(@RequestBody @Valid User user, UriComponentsBuilder uriComponentsBuilder) {
+ public ResponseEntity createNewUser(
+ @RequestBody @Valid User user, UriComponentsBuilder uriComponentsBuilder) {
this.userService.storeNewUser(user);
- return ResponseEntity
- .created(uriComponentsBuilder.path("/api/users/{username}").build(user.getUsername()))
- .build();
+ return ResponseEntity.created(
+ uriComponentsBuilder.path("/api/users/{username}").build(user.getUsername()))
+ .build();
}
}
diff --git a/testing-spring-boot-applications-with-mockmvc/src/main/java/de/rieckpil/blog/user/UserService.java b/testing-spring-boot-applications-with-mockmvc/src/main/java/de/rieckpil/blog/user/UserService.java
index ca7354ea..a32f3c44 100644
--- a/testing-spring-boot-applications-with-mockmvc/src/main/java/de/rieckpil/blog/user/UserService.java
+++ b/testing-spring-boot-applications-with-mockmvc/src/main/java/de/rieckpil/blog/user/UserService.java
@@ -1,10 +1,9 @@
package de.rieckpil.blog.user;
-import org.springframework.stereotype.Service;
-
-import javax.annotation.PostConstruct;
+import jakarta.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
+import org.springframework.stereotype.Service;
@Service
public class UserService {
@@ -23,9 +22,9 @@ public List getAllUsers() {
public User getUserByUsername(String username) {
return inMemoryUserList.stream()
- .filter(user -> user.getUsername().equals(username))
- .findFirst()
- .orElseThrow(() -> new UserNotFoundException("Can't find this user *sad smiley*"));
+ .filter(user -> user.getUsername().equals(username))
+ .findFirst()
+ .orElseThrow(() -> new UserNotFoundException("Can't find this user *sad smiley*"));
}
public void storeNewUser(User user) {
diff --git a/testing-spring-boot-applications-with-mockmvc/src/test/java/de/rieckpil/blog/ApplicationTest.java b/testing-spring-boot-applications-with-mockmvc/src/test/java/de/rieckpil/blog/ApplicationTest.java
index 6660a3cb..804a3803 100644
--- a/testing-spring-boot-applications-with-mockmvc/src/test/java/de/rieckpil/blog/ApplicationTest.java
+++ b/testing-spring-boot-applications-with-mockmvc/src/test/java/de/rieckpil/blog/ApplicationTest.java
@@ -1,5 +1,9 @@
package de.rieckpil.blog;
+import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
@@ -7,25 +11,20 @@
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors;
import org.springframework.test.web.servlet.MockMvc;
-import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
-
@SpringBootTest
@AutoConfigureMockMvc
class ApplicationTest {
- @Autowired
- private MockMvc mockMvc;
+ @Autowired private MockMvc mockMvc;
@Test
public void shouldAllowDeletingReviewsWhenUserIsAdmin() throws Exception {
this.mockMvc
- .perform(
- delete("/api/tasks/42")
- .with(SecurityMockMvcRequestPostProcessors.user("duke").roles("ADMIN", "SUPER_USER"))
- .with(csrf())
- )
- .andExpect(status().isOk());
+ .perform(
+ delete("/api/tasks/42")
+ .with(
+ SecurityMockMvcRequestPostProcessors.user("duke").roles("ADMIN", "SUPER_USER"))
+ .with(csrf()))
+ .andExpect(status().isOk());
}
}
diff --git a/testing-spring-boot-applications-with-mockmvc/src/test/java/de/rieckpil/blog/dashboard/DashboardControllerTest.java b/testing-spring-boot-applications-with-mockmvc/src/test/java/de/rieckpil/blog/dashboard/DashboardControllerTest.java
index 2bd77731..74b425bf 100644
--- a/testing-spring-boot-applications-with-mockmvc/src/test/java/de/rieckpil/blog/dashboard/DashboardControllerTest.java
+++ b/testing-spring-boot-applications-with-mockmvc/src/test/java/de/rieckpil/blog/dashboard/DashboardControllerTest.java
@@ -1,35 +1,36 @@
package de.rieckpil.blog.dashboard;
+import static org.mockito.Mockito.when;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
+
+import de.rieckpil.blog.SecurityConfig;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.context.annotation.Import;
import org.springframework.test.web.servlet.MockMvc;
-import static org.mockito.Mockito.when;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
-
+@Import(SecurityConfig.class)
@WebMvcTest(DashboardController.class)
class DashboardControllerTest {
- @Autowired
- private MockMvc mockMvc;
+ @Autowired private MockMvc mockMvc;
- @MockBean
- private DashboardService dashboardService;
+ @MockBean private DashboardService dashboardService;
@Test
public void shouldReturnViewWithPrefilledData() throws Exception {
- when(dashboardService.getAnalyticsGraphData()).thenReturn(new Integer[]{13, 42});
+ when(dashboardService.getAnalyticsGraphData()).thenReturn(new Integer[] {13, 42});
this.mockMvc
- .perform(get("/dashboard"))
- .andExpect(status().isOk())
- .andExpect(view().name("dashboard"))
- .andExpect(model().attribute("user", "Duke"))
- .andExpect(model().attribute("analyticsGraph", Matchers.arrayContaining(13, 42)))
- .andExpect(model().attributeExists("quickNote"));
+ .perform(get("/dashboard"))
+ .andExpect(status().isOk())
+ .andExpect(view().name("dashboard"))
+ .andExpect(model().attribute("user", "Duke"))
+ .andExpect(model().attribute("analyticsGraph", Matchers.arrayContaining(13, 42)))
+ .andExpect(model().attributeExists("quickNote"));
}
}
diff --git a/testing-spring-boot-applications-with-mockmvc/src/test/java/de/rieckpil/blog/task/TaskControllerSecondTest.java b/testing-spring-boot-applications-with-mockmvc/src/test/java/de/rieckpil/blog/task/TaskControllerSecondTest.java
index 109d411f..e792d809 100644
--- a/testing-spring-boot-applications-with-mockmvc/src/test/java/de/rieckpil/blog/task/TaskControllerSecondTest.java
+++ b/testing-spring-boot-applications-with-mockmvc/src/test/java/de/rieckpil/blog/task/TaskControllerSecondTest.java
@@ -1,54 +1,50 @@
package de.rieckpil.blog.task;
+import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
+import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+import de.rieckpil.blog.SecurityConfig;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.context.annotation.Import;
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
-import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
-import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
-
+@Import(SecurityConfig.class)
@WebMvcTest(TaskController.class)
public class TaskControllerSecondTest {
- @Autowired
- private WebApplicationContext context;
+ @Autowired private WebApplicationContext context;
- @MockBean
- private TaskService taskService;
+ @MockBean private TaskService taskService;
protected MockMvc mockMvc;
@BeforeEach
public void setup() {
- this.mockMvc = MockMvcBuilders
- .webAppContextSetup(this.context)
- .apply(springSecurity())
- .build();
+ this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context).apply(springSecurity()).build();
}
@Test
public void shouldRejectDeletingReviewsWhenUserIsNotAdmin() throws Exception {
- this.mockMvc
- .perform(delete("/api/tasks/42").with(csrf()))
- .andExpect(status().isUnauthorized());
+ this.mockMvc.perform(delete("/api/tasks/42").with(csrf())).andExpect(status().isUnauthorized());
}
@Test
public void shouldAllowDeletingReviewsWhenUserIsAdmin() throws Exception {
this.mockMvc
- .perform(
- delete("/api/tasks/42")
- .with(SecurityMockMvcRequestPostProcessors.user("duke").roles("ADMIN", "SUPER_USER"))
- .with(csrf())
- )
- .andExpect(status().isOk());
+ .perform(
+ delete("/api/tasks/42")
+ .with(
+ SecurityMockMvcRequestPostProcessors.user("duke").roles("ADMIN", "SUPER_USER"))
+ .with(csrf()))
+ .andExpect(status().isOk());
}
}
diff --git a/testing-spring-boot-applications-with-mockmvc/src/test/java/de/rieckpil/blog/task/TaskControllerTest.java b/testing-spring-boot-applications-with-mockmvc/src/test/java/de/rieckpil/blog/task/TaskControllerTest.java
index d732a4f1..04a36050 100644
--- a/testing-spring-boot-applications-with-mockmvc/src/test/java/de/rieckpil/blog/task/TaskControllerTest.java
+++ b/testing-spring-boot-applications-with-mockmvc/src/test/java/de/rieckpil/blog/task/TaskControllerTest.java
@@ -1,15 +1,5 @@
package de.rieckpil.blog.task;
-import org.hamcrest.Matchers;
-import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
-import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.http.MediaType;
-import org.springframework.security.test.context.support.WithMockUser;
-import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors;
-import org.springframework.test.web.servlet.MockMvc;
-
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -20,62 +10,70 @@
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+import de.rieckpil.blog.SecurityConfig;
+import org.hamcrest.Matchers;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.context.annotation.Import;
+import org.springframework.http.MediaType;
+import org.springframework.security.test.context.support.WithMockUser;
+import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors;
+import org.springframework.test.web.servlet.MockMvc;
+
+@Import(SecurityConfig.class)
@WebMvcTest(TaskController.class)
class TaskControllerTest {
- @Autowired
- private MockMvc mockMvc;
+ @Autowired private MockMvc mockMvc;
- @MockBean
- private TaskService taskService;
+ @MockBean private TaskService taskService;
@Test
public void shouldRejectCreatingReviewsWhenUserIsAnonymous() throws Exception {
this.mockMvc
- .perform(
- post("/api/tasks")
- .contentType(MediaType.APPLICATION_JSON)
- .content("{\"taskTitle\": \"Learn MockMvc\"}")
- .with(csrf())
- )
- .andExpect(status().isUnauthorized());
+ .perform(
+ post("/api/tasks")
+ .contentType(MediaType.APPLICATION_JSON)
+ .content("{\"taskTitle\": \"Learn MockMvc\"}")
+ .with(csrf()))
+ .andExpect(status().isUnauthorized());
}
@Test
- public void shouldReturnLocationOfReviewWhenUserIsAuthenticatedAndCreatesReview() throws Exception {
+ public void shouldReturnLocationOfReviewWhenUserIsAuthenticatedAndCreatesReview()
+ throws Exception {
when(taskService.createTask(anyString())).thenReturn(42L);
this.mockMvc
- .perform(
- post("/api/tasks")
- .contentType(MediaType.APPLICATION_JSON)
- .content("{\"taskTitle\": \"Learn MockMvc\"}")
- .with(csrf())
- .with(user("duke"))
- )
- .andExpect(status().isCreated())
- .andExpect(header().exists("Location"))
- .andExpect(header().string("Location", Matchers.containsString("42")));
+ .perform(
+ post("/api/tasks")
+ .contentType(MediaType.APPLICATION_JSON)
+ .content("{\"taskTitle\": \"Learn MockMvc\"}")
+ .with(csrf())
+ .with(user("duke")))
+ .andExpect(status().isCreated())
+ .andExpect(header().exists("Location"))
+ .andExpect(header().string("Location", Matchers.containsString("42")));
}
@Test
@WithMockUser("duke")
public void shouldRejectDeletingReviewsWhenUserLacksAdminRole() throws Exception {
- this.mockMvc
- .perform(delete("/api/tasks/42"))
- .andExpect(status().isForbidden());
+ this.mockMvc.perform(delete("/api/tasks/42")).andExpect(status().isForbidden());
}
@Test
public void shouldAllowDeletingReviewsWhenUserIsAdmin() throws Exception {
this.mockMvc
- .perform(
- delete("/api/tasks/42")
- .with(SecurityMockMvcRequestPostProcessors.user("duke").roles("ADMIN", "SUPER_USER"))
- .with(csrf())
- )
- .andExpect(status().isOk());
+ .perform(
+ delete("/api/tasks/42")
+ .with(
+ SecurityMockMvcRequestPostProcessors.user("duke").roles("ADMIN", "SUPER_USER"))
+ .with(csrf()))
+ .andExpect(status().isOk());
verify(taskService).deleteTask(42L);
}
diff --git a/testing-spring-boot-applications-with-mockmvc/src/test/java/de/rieckpil/blog/user/UserControllerTest.java b/testing-spring-boot-applications-with-mockmvc/src/test/java/de/rieckpil/blog/user/UserControllerTest.java
index eeb5678a..4a91bd0d 100644
--- a/testing-spring-boot-applications-with-mockmvc/src/test/java/de/rieckpil/blog/user/UserControllerTest.java
+++ b/testing-spring-boot-applications-with-mockmvc/src/test/java/de/rieckpil/blog/user/UserControllerTest.java
@@ -1,70 +1,66 @@
package de.rieckpil.blog.user;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+import de.rieckpil.blog.SecurityConfig;
+import java.util.List;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.context.annotation.Import;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
-import java.util.List;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
-
+@Import(SecurityConfig.class)
@WebMvcTest(UserController.class)
class UserControllerTest {
- @Autowired
- private MockMvc mockMvc;
+ @Autowired private MockMvc mockMvc;
- @MockBean
- private UserService userService;
+ @MockBean private UserService userService;
@Test
public void shouldReturnAllUsersForUnauthenticatedUsers() throws Exception {
- when(userService.getAllUsers())
- .thenReturn(List.of(new User("duke", "duke@spring.io")));
+ when(userService.getAllUsers()).thenReturn(List.of(new User("duke", "duke@spring.io")));
this.mockMvc
- .perform(MockMvcRequestBuilders.get("/api/users"))
- .andExpect(MockMvcResultMatchers.status().isOk())
- .andExpect(MockMvcResultMatchers.jsonPath("$.size()").value(1))
- .andExpect(MockMvcResultMatchers.jsonPath("$[0].username").value("duke"))
- .andExpect(MockMvcResultMatchers.jsonPath("$[0].email").value("duke@spring.io"));
+ .perform(MockMvcRequestBuilders.get("/api/users"))
+ .andExpect(MockMvcResultMatchers.status().isOk())
+ .andExpect(MockMvcResultMatchers.jsonPath("$.size()").value(1))
+ .andExpect(MockMvcResultMatchers.jsonPath("$[0].username").value("duke"))
+ .andExpect(MockMvcResultMatchers.jsonPath("$[0].email").value("duke@spring.io"));
}
@Test
public void shouldReturn404WhenUserIsNotFound() throws Exception {
when(userService.getUserByUsername("duke"))
- .thenThrow(new UserNotFoundException("duke is not found"));
+ .thenThrow(new UserNotFoundException("duke is not found"));
- this.mockMvc
- .perform(get("/api/users/duke"))
- .andExpect(status().isNotFound());
+ this.mockMvc.perform(get("/api/users/duke")).andExpect(status().isNotFound());
}
@Test
public void shouldAllowCreationForUnauthenticatedUsers() throws Exception {
this.mockMvc
- .perform(
- post("/api/users")
- .contentType(MediaType.APPLICATION_JSON)
- .content("{\"username\": \"duke\", \"email\":\"duke@spring.io\"}")
- .with(csrf())
- )
- .andExpect(status().isCreated())
- .andExpect(header().exists("Location"))
- .andExpect(header().string("Location", Matchers.containsString("duke")));
+ .perform(
+ post("/api/users")
+ .contentType(MediaType.APPLICATION_JSON)
+ .content("{\"username\": \"duke\", \"email\":\"duke@spring.io\"}")
+ .with(csrf()))
+ .andExpect(status().isCreated())
+ .andExpect(header().exists("Location"))
+ .andExpect(header().string("Location", Matchers.containsString("duke")));
verify(userService).storeNewUser(any(User.class));
}
diff --git a/testing-spring-rest-template/pom.xml b/testing-spring-rest-template/pom.xml
index 63a1f67d..4617d3b2 100644
--- a/testing-spring-rest-template/pom.xml
+++ b/testing-spring-rest-template/pom.xml
@@ -2,23 +2,19 @@
4.0.0
+
- org.springframework.boot
- spring-boot-starter-parent
- 2.4.5
-
+ de.rieckpil.blog
+ blog-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
- de.rieckpil.blog
testing-spring-rest-template
0.0.1-SNAPSHOT
testing-spring-rest-template
Demo project for Spring Boot
-
- 16
-
-
org.springframework.boot
diff --git a/testing-spring-rest-template/src/main/java/de/rieckpil/blog/RestTemplateConfig.java b/testing-spring-rest-template/src/main/java/de/rieckpil/blog/RestTemplateConfig.java
index 44a171e6..cffe522b 100644
--- a/testing-spring-rest-template/src/main/java/de/rieckpil/blog/RestTemplateConfig.java
+++ b/testing-spring-rest-template/src/main/java/de/rieckpil/blog/RestTemplateConfig.java
@@ -1,20 +1,20 @@
package de.rieckpil.blog;
+import java.time.Duration;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
-import java.time.Duration;
-
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate reqresRestTemplate(RestTemplateBuilder restTemplateBuilder) {
- return restTemplateBuilder.rootUri("https://reqres.in/")
- .setConnectTimeout(Duration.ofSeconds(2))
- .setReadTimeout(Duration.ofSeconds(2))
- .build();
+ return restTemplateBuilder
+ .rootUri("https://reqres.in/")
+ .setConnectTimeout(Duration.ofSeconds(2))
+ .setReadTimeout(Duration.ofSeconds(2))
+ .build();
}
}
diff --git a/testing-spring-rest-template/src/main/java/de/rieckpil/blog/TestingSpringRestTemplateApplication.java b/testing-spring-rest-template/src/main/java/de/rieckpil/blog/TestingSpringRestTemplateApplication.java
index e0dab9b8..7ea961ff 100644
--- a/testing-spring-rest-template/src/main/java/de/rieckpil/blog/TestingSpringRestTemplateApplication.java
+++ b/testing-spring-rest-template/src/main/java/de/rieckpil/blog/TestingSpringRestTemplateApplication.java
@@ -4,10 +4,9 @@
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
-public class TestingSpringRestTemplateApplication{
+public class TestingSpringRestTemplateApplication {
public static void main(String[] args) {
SpringApplication.run(TestingSpringRestTemplateApplication.class, args);
}
-
}
diff --git a/testing-spring-rest-template/src/main/java/de/rieckpil/blog/User.java b/testing-spring-rest-template/src/main/java/de/rieckpil/blog/User.java
index 643a435f..cd409fc3 100644
--- a/testing-spring-rest-template/src/main/java/de/rieckpil/blog/User.java
+++ b/testing-spring-rest-template/src/main/java/de/rieckpil/blog/User.java
@@ -3,9 +3,7 @@
public class User {
private UserData data;
- public User() {
-
- }
+ public User() {}
public User(UserData data) {
this.data = data;
@@ -21,8 +19,6 @@ public void setData(UserData data) {
@Override
public String toString() {
- return "User{" +
- "data=" + data +
- '}';
+ return "User{" + "data=" + data + '}';
}
}
diff --git a/testing-spring-rest-template/src/main/java/de/rieckpil/blog/UserClient.java b/testing-spring-rest-template/src/main/java/de/rieckpil/blog/UserClient.java
index 3b8807e8..87ebd98b 100644
--- a/testing-spring-rest-template/src/main/java/de/rieckpil/blog/UserClient.java
+++ b/testing-spring-rest-template/src/main/java/de/rieckpil/blog/UserClient.java
@@ -24,8 +24,7 @@ public User getSingleUser(Long id) {
HttpEntity requestEntity = new HttpEntity<>(headers);
return this.restTemplate
- .exchange("/api/users/{id}", HttpMethod.GET, requestEntity, User.class, id)
- .getBody();
-
+ .exchange("/api/users/{id}", HttpMethod.GET, requestEntity, User.class, id)
+ .getBody();
}
}
diff --git a/testing-spring-rest-template/src/main/java/de/rieckpil/blog/UserData.java b/testing-spring-rest-template/src/main/java/de/rieckpil/blog/UserData.java
index bf01801d..99a934fe 100644
--- a/testing-spring-rest-template/src/main/java/de/rieckpil/blog/UserData.java
+++ b/testing-spring-rest-template/src/main/java/de/rieckpil/blog/UserData.java
@@ -68,12 +68,21 @@ public void setAvatar(String avatar) {
@Override
public String toString() {
- return "UserData{" +
- "id=" + id +
- ", email='" + email + '\'' +
- ", avatar='" + avatar + '\'' +
- ", firstName='" + firstName + '\'' +
- ", lastName='" + lastName + '\'' +
- '}';
+ return "UserData{"
+ + "id="
+ + id
+ + ", email='"
+ + email
+ + '\''
+ + ", avatar='"
+ + avatar
+ + '\''
+ + ", firstName='"
+ + firstName
+ + '\''
+ + ", lastName='"
+ + lastName
+ + '\''
+ + '}';
}
}
diff --git a/testing-spring-rest-template/src/test/java/de/rieckpil/blog/ResourceClientTest.java b/testing-spring-rest-template/src/test/java/de/rieckpil/blog/ResourceClientTest.java
index 08838eeb..aadb2583 100644
--- a/testing-spring-rest-template/src/test/java/de/rieckpil/blog/ResourceClientTest.java
+++ b/testing-spring-rest-template/src/test/java/de/rieckpil/blog/ResourceClientTest.java
@@ -1,5 +1,9 @@
package de.rieckpil.blog;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
+import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
+
import com.fasterxml.jackson.databind.JsonNode;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
@@ -10,28 +14,22 @@
import org.springframework.http.MediaType;
import org.springframework.test.web.client.MockRestServiceServer;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
-import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
-
@RestClientTest(ResourceClient.class)
@AutoConfigureWebClient(registerRestTemplate = true)
class ResourceClientTest {
- @Autowired
- private ResourceClient resourceClient;
+ @Autowired private ResourceClient resourceClient;
- @Autowired
- private MockRestServiceServer mockRestServiceServer;
+ @Autowired private MockRestServiceServer mockRestServiceServer;
@BeforeEach
- // @Before for JUnit 4
+ // @Before for JUnit 4
void setUp() {
this.mockRestServiceServer.reset();
}
@AfterEach
- // @After for JUnit 4
+ // @After for JUnit 4
void tearDown() {
this.mockRestServiceServer.verify();
}
@@ -46,8 +44,8 @@ void successfullyReturnData() {
""";
this.mockRestServiceServer
- .expect(requestTo("/api/unkown/1"))
- .andRespond(withSuccess(json, MediaType.APPLICATION_JSON));
+ .expect(requestTo("/api/unkown/1"))
+ .andRespond(withSuccess(json, MediaType.APPLICATION_JSON));
JsonNode result = resourceClient.getSingleResource(1L);
diff --git a/testing-spring-rest-template/src/test/java/de/rieckpil/blog/TestingSpringRestTemplateApplicationTests.java b/testing-spring-rest-template/src/test/java/de/rieckpil/blog/TestingSpringRestTemplateApplicationTests.java
index 2c4994f2..322063d0 100644
--- a/testing-spring-rest-template/src/test/java/de/rieckpil/blog/TestingSpringRestTemplateApplicationTests.java
+++ b/testing-spring-rest-template/src/test/java/de/rieckpil/blog/TestingSpringRestTemplateApplicationTests.java
@@ -6,8 +6,6 @@
@SpringBootTest
class TestingSpringRestTemplateApplicationTests {
- @Test
- void contextLoads() {
- }
-
+ @Test
+ void contextLoads() {}
}
diff --git a/testing-spring-rest-template/src/test/java/de/rieckpil/blog/UserClientTest.java b/testing-spring-rest-template/src/test/java/de/rieckpil/blog/UserClientTest.java
index 86f030de..94d722c8 100644
--- a/testing-spring-rest-template/src/test/java/de/rieckpil/blog/UserClientTest.java
+++ b/testing-spring-rest-template/src/test/java/de/rieckpil/blog/UserClientTest.java
@@ -1,5 +1,9 @@
package de.rieckpil.blog;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
+import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
+
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
@@ -10,26 +14,20 @@
import org.springframework.test.web.client.response.MockRestResponseCreators;
import org.springframework.web.client.HttpClientErrorException;
-import static org.junit.jupiter.api.Assertions.*;
-import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
-import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
-
@RestClientTest(UserClient.class)
class UserClientTest {
- @Autowired
- private UserClient userClient;
+ @Autowired private UserClient userClient;
- @Autowired
- private ObjectMapper objectMapper;
+ @Autowired private ObjectMapper objectMapper;
- @Autowired
- private MockRestServiceServer mockRestServiceServer;
+ @Autowired private MockRestServiceServer mockRestServiceServer;
@Test
void userClientSuccessfullyReturnsUser() {
- String json = """
+ String json =
+ """
{
"data": {
"id": 1,
@@ -42,8 +40,8 @@ void userClientSuccessfullyReturnsUser() {
""";
this.mockRestServiceServer
- .expect(requestTo("/api/users/1"))
- .andRespond(withSuccess(json, MediaType.APPLICATION_JSON));
+ .expect(requestTo("/api/users/1"))
+ .andRespond(withSuccess(json, MediaType.APPLICATION_JSON));
User result = userClient.getSingleUser(1L);
@@ -53,12 +51,13 @@ void userClientSuccessfullyReturnsUser() {
@Test
void userClientSuccessfullyReturnsUserDuke() throws Exception {
- String json = this.objectMapper
- .writeValueAsString(new User(new UserData(42L, "duke@java.org", "duke", "duke", "duke")));
+ String json =
+ this.objectMapper.writeValueAsString(
+ new User(new UserData(42L, "duke@java.org", "duke", "duke", "duke")));
this.mockRestServiceServer
- .expect(requestTo("/api/users/42"))
- .andRespond(withSuccess(json, MediaType.APPLICATION_JSON));
+ .expect(requestTo("/api/users/42"))
+ .andRespond(withSuccess(json, MediaType.APPLICATION_JSON));
User result = userClient.getSingleUser(42L);
@@ -71,10 +70,10 @@ void userClientSuccessfullyReturnsUserDuke() throws Exception {
@Test
void userClientThrowsExceptionWhenNoUserIsFound() {
- this.mockRestServiceServer.expect(requestTo("/api/users/1"))
- .andRespond(MockRestResponseCreators.withStatus(HttpStatus.NOT_FOUND));
+ this.mockRestServiceServer
+ .expect(requestTo("/api/users/1"))
+ .andRespond(MockRestResponseCreators.withStatus(HttpStatus.NOT_FOUND));
assertThrows(HttpClientErrorException.class, () -> userClient.getSingleUser(1L));
}
-
}
diff --git a/whats-new-in-spring-boot-2.1/pom.xml b/whats-new-in-spring-boot-2.1/pom.xml
index ed4b7e5e..95f88569 100644
--- a/whats-new-in-spring-boot-2.1/pom.xml
+++ b/whats-new-in-spring-boot-2.1/pom.xml
@@ -1,76 +1,71 @@
-
- 4.0.0
+
+ 4.0.0
- de.rieckpil.blog
- whats-new-in-spring-boot-2.1
- 0.0.1-SNAPSHOT
- jar
+
+ de.rieckpil.blog
+ blog-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
+
- whats-new-in-spring-boot-2.1
- Updates to Spring Boot 2.1
+ whats-new-in-spring-boot-2.1
+ 0.0.1-SNAPSHOT
+ jar
-
- org.springframework.boot
- spring-boot-starter-parent
- 2.1.0.RELEASE
-
-
+ whats-new-in-spring-boot-2.1
+ Updates to Spring Boot 2.1
-
- UTF-8
- UTF-8
- 11
-
+
+ UTF-8
+ UTF-8
+
-
-
- org.springframework.boot
- spring-boot-starter-data-jpa
-
-
- org.springframework.boot
- spring-boot-starter-web
-
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
-
- com.h2database
- h2
- runtime
-
-
- org.springframework.boot
- spring-boot-starter-test
- test
-
-
- junit
- junit
-
-
-
-
- org.junit.jupiter
- junit-jupiter-api
- test
-
-
- org.junit.jupiter
- junit-jupiter-engine
- test
-
-
-
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
-
-
+
+ com.h2database
+ h2
+ runtime
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ junit
+ junit
+
+
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ test
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
diff --git a/whats-new-in-spring-boot-2.1/src/main/java/de/rieckpil/learning/Application.java b/whats-new-in-spring-boot-2.1/src/main/java/de/rieckpil/learning/Application.java
index 46353304..55688540 100644
--- a/whats-new-in-spring-boot-2.1/src/main/java/de/rieckpil/learning/Application.java
+++ b/whats-new-in-spring-boot-2.1/src/main/java/de/rieckpil/learning/Application.java
@@ -6,7 +6,7 @@
@SpringBootApplication
public class Application {
- public static void main(String[] args) {
- SpringApplication.run(Application.class, args);
- }
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
}
diff --git a/whats-new-in-spring-boot-2.1/src/main/java/de/rieckpil/learning/User.java b/whats-new-in-spring-boot-2.1/src/main/java/de/rieckpil/learning/User.java
index 33a8c05c..e61f04f1 100644
--- a/whats-new-in-spring-boot-2.1/src/main/java/de/rieckpil/learning/User.java
+++ b/whats-new-in-spring-boot-2.1/src/main/java/de/rieckpil/learning/User.java
@@ -1,48 +1,50 @@
-package de.rieckpil.learning;
-
-import javax.persistence.Entity;
-import javax.persistence.GeneratedValue;
-import javax.persistence.Id;
-
-@Entity
-public class User {
-
- @Id
- @GeneratedValue
- private Long id;
- private String name;
- private String userId;
-
- public User() {
- }
-
- public User(String name, String userId) {
- this.name = name;
- this.userId = userId;
- }
-
- public Long getId() {
- return id;
- }
-
- public void setId(Long id) {
- this.id = id;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public String getUserId() {
- return userId;
- }
-
- public void setUserId(String userId) {
- this.userId = userId;
- }
-
-}
+package de.rieckpil.learning;
+
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+
+@Entity
+public class User {
+
+ @Id private Long id;
+
+ private String name;
+ private String userId;
+
+ public User() {}
+
+ public User(Long id, String name, String userId) {
+ this.id = id;
+ this.name = name;
+ this.userId = userId;
+ }
+
+ public User(String name, String userId) {
+ this.name = name;
+ this.userId = userId;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getUserId() {
+ return userId;
+ }
+
+ public void setUserId(String userId) {
+ this.userId = userId;
+ }
+}
diff --git a/whats-new-in-spring-boot-2.1/src/main/java/de/rieckpil/learning/UserPopulator.java b/whats-new-in-spring-boot-2.1/src/main/java/de/rieckpil/learning/UserPopulator.java
index 9bb4ed18..cd00c9e3 100644
--- a/whats-new-in-spring-boot-2.1/src/main/java/de/rieckpil/learning/UserPopulator.java
+++ b/whats-new-in-spring-boot-2.1/src/main/java/de/rieckpil/learning/UserPopulator.java
@@ -1,24 +1,27 @@
-package de.rieckpil.learning;
-
-import java.util.List;
-import java.util.UUID;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.CommandLineRunner;
-import org.springframework.stereotype.Service;
-
-@Service
-public class UserPopulator implements CommandLineRunner {
-
- @Autowired
- UserRepository userRepository;
-
- @Override
- public void run(String... args) throws Exception {
-
- List.of("Tom", "Mike", "John", "Andrew").stream()
- .forEach(n -> userRepository.save(new User(n, UUID.randomUUID().toString())));
-
- }
-
-}
+package de.rieckpil.learning;
+
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.ThreadLocalRandom;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.stereotype.Service;
+
+@Service
+public class UserPopulator implements CommandLineRunner {
+
+ @Autowired UserRepository userRepository;
+
+ @Override
+ public void run(String... args) throws Exception {
+
+ List.of("Tom", "Mike", "John", "Andrew").stream()
+ .forEach(
+ n ->
+ userRepository.save(
+ new User(
+ ThreadLocalRandom.current().nextLong(1, 99999),
+ n,
+ UUID.randomUUID().toString())));
+ }
+}
diff --git a/whats-new-in-spring-boot-2.1/src/main/java/de/rieckpil/learning/UserRepository.java b/whats-new-in-spring-boot-2.1/src/main/java/de/rieckpil/learning/UserRepository.java
index 5c7f4771..2369fad1 100644
--- a/whats-new-in-spring-boot-2.1/src/main/java/de/rieckpil/learning/UserRepository.java
+++ b/whats-new-in-spring-boot-2.1/src/main/java/de/rieckpil/learning/UserRepository.java
@@ -1,7 +1,5 @@
-package de.rieckpil.learning;
-
-import org.springframework.data.jpa.repository.JpaRepository;
-
-public interface UserRepository extends JpaRepository {
-
-}
+package de.rieckpil.learning;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface UserRepository extends JpaRepository {}
diff --git a/whats-new-in-spring-boot-2.1/src/test/java/de/rieckpil/learning/ApplicationTests.java b/whats-new-in-spring-boot-2.1/src/test/java/de/rieckpil/learning/ApplicationTests.java
index befa5bdc..a36eb946 100644
--- a/whats-new-in-spring-boot-2.1/src/test/java/de/rieckpil/learning/ApplicationTests.java
+++ b/whats-new-in-spring-boot-2.1/src/test/java/de/rieckpil/learning/ApplicationTests.java
@@ -1,16 +1,16 @@
package de.rieckpil.learning;
+import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
+@Disabled
@SpringBootTest
// no @ExtendWith(SpringExtension.class) needed
-public class ApplicationTests {
-
- @Test
- @DisplayName("Load the whole Spring context")
- public void contextLoads() {
- }
+class ApplicationTests {
+ @Test
+ @DisplayName("Load the whole Spring context")
+ void contextLoads() {}
}
diff --git a/whats-new-in-spring-boot-2.2/pom.xml b/whats-new-in-spring-boot-2.2/pom.xml
index 8a943833..2bcccdfd 100644
--- a/whats-new-in-spring-boot-2.2/pom.xml
+++ b/whats-new-in-spring-boot-2.2/pom.xml
@@ -3,22 +3,19 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0%20http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
-
- org.springframework.boot
- spring-boot-starter-parent
- 2.2.0.RELEASE
-
-
+
+
de.rieckpil.blog
+ blog-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
+
+
whats-new-in-spring-boot.2.2
0.0.1-SNAPSHOT
- whats-new-in-spring-boot.2.2
+ whats-new-in-spring-boot-2.2
What's new in Spring Boot 2.2
-
- 11
-
-
org.springframework.boot
diff --git a/whats-new-in-spring-boot-2.2/src/main/java/de/rieckpil/blog/Application.java b/whats-new-in-spring-boot-2.2/src/main/java/de/rieckpil/blog/Application.java
index 0d8a1e8f..4c8cfd9d 100644
--- a/whats-new-in-spring-boot-2.2/src/main/java/de/rieckpil/blog/Application.java
+++ b/whats-new-in-spring-boot-2.2/src/main/java/de/rieckpil/blog/Application.java
@@ -7,12 +7,10 @@
@SpringBootApplication
public class Application implements CommandLineRunner {
- public static void main(String[] args) {
- SpringApplication.run(Application.class, args);
- }
-
- @Override
- public void run(String... args) throws Exception {
- }
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+ @Override
+ public void run(String... args) throws Exception {}
}
diff --git a/whats-new-in-spring-boot-2.2/src/main/java/de/rieckpil/blog/CustomLivenessCheck.java b/whats-new-in-spring-boot-2.2/src/main/java/de/rieckpil/blog/CustomLivenessCheck.java
index bc056d9a..46fab7ca 100644
--- a/whats-new-in-spring-boot-2.2/src/main/java/de/rieckpil/blog/CustomLivenessCheck.java
+++ b/whats-new-in-spring-boot-2.2/src/main/java/de/rieckpil/blog/CustomLivenessCheck.java
@@ -1,24 +1,22 @@
package de.rieckpil.blog;
+import java.util.concurrent.ThreadLocalRandom;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;
-import java.util.concurrent.ThreadLocalRandom;
-
@Component("custom-liveness")
public class CustomLivenessCheck implements HealthIndicator {
- @Override
- public Health health() {
- if (checkLiveness()) {
- return Health.up().build();
- }
- return Health.down().withDetail("Error Code", 42).build();
- }
-
- private boolean checkLiveness() {
- return ThreadLocalRandom.current().nextBoolean();
+ @Override
+ public Health health() {
+ if (checkLiveness()) {
+ return Health.up().build();
}
+ return Health.down().withDetail("Error Code", 42).build();
+ }
-}
\ No newline at end of file
+ private boolean checkLiveness() {
+ return ThreadLocalRandom.current().nextBoolean();
+ }
+}
diff --git a/whats-new-in-spring-boot-2.2/src/main/java/de/rieckpil/blog/KubernetesDetector.java b/whats-new-in-spring-boot-2.2/src/main/java/de/rieckpil/blog/KubernetesDetector.java
index 5fbc28d8..16219caf 100644
--- a/whats-new-in-spring-boot-2.2/src/main/java/de/rieckpil/blog/KubernetesDetector.java
+++ b/whats-new-in-spring-boot-2.2/src/main/java/de/rieckpil/blog/KubernetesDetector.java
@@ -9,9 +9,8 @@
@ConditionalOnCloudPlatform(CloudPlatform.KUBERNETES)
public class KubernetesDetector implements CommandLineRunner {
- @Override
- public void run(String... args) throws Exception {
- System.out.println("--- You are running on KUBERNETES ;)");
- }
-
+ @Override
+ public void run(String... args) throws Exception {
+ System.out.println("--- You are running on KUBERNETES ;)");
+ }
}
diff --git a/whats-new-in-spring-boot-2.2/src/main/java/de/rieckpil/blog/SampleEndpoint.java b/whats-new-in-spring-boot-2.2/src/main/java/de/rieckpil/blog/SampleEndpoint.java
index 3b007320..f1ecc4dc 100644
--- a/whats-new-in-spring-boot-2.2/src/main/java/de/rieckpil/blog/SampleEndpoint.java
+++ b/whats-new-in-spring-boot-2.2/src/main/java/de/rieckpil/blog/SampleEndpoint.java
@@ -1,27 +1,26 @@
package de.rieckpil.blog;
+import jakarta.annotation.PostConstruct;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
-import javax.annotation.PostConstruct;
-
@RestController
public class SampleEndpoint {
- private SampleService sampleService;
+ private SampleService sampleService;
- private SampleEndpoint(SampleService sampleService) {
- this.sampleService = sampleService;
- }
+ private SampleEndpoint(SampleService sampleService) {
+ this.sampleService = sampleService;
+ }
- @PostConstruct
- public void init() {
- System.out.println("SampleEndpoint is now initialized");
- }
+ @PostConstruct
+ public void init() {
+ System.out.println("SampleEndpoint is now initialized");
+ }
- @GetMapping("/hello")
- public ResponseEntity sayHello() {
- return ResponseEntity.ok(sampleService.getMessage());
- }
+ @GetMapping("/hello")
+ public ResponseEntity sayHello() {
+ return ResponseEntity.ok(sampleService.getMessage());
+ }
}
diff --git a/whats-new-in-spring-boot-2.2/src/main/java/de/rieckpil/blog/SampleService.java b/whats-new-in-spring-boot-2.2/src/main/java/de/rieckpil/blog/SampleService.java
index 417c7589..0ccff0c3 100644
--- a/whats-new-in-spring-boot-2.2/src/main/java/de/rieckpil/blog/SampleService.java
+++ b/whats-new-in-spring-boot-2.2/src/main/java/de/rieckpil/blog/SampleService.java
@@ -1,20 +1,19 @@
package de.rieckpil.blog;
+import jakarta.annotation.PostConstruct;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
-import javax.annotation.PostConstruct;
-
@Service
@Lazy(false)
public class SampleService {
- @PostConstruct
- public void init() {
- System.out.println("SampleService is now initialized");
- }
+ @PostConstruct
+ public void init() {
+ System.out.println("SampleService is now initialized");
+ }
- public String getMessage() {
- return "Hello World";
- }
+ public String getMessage() {
+ return "Hello World";
+ }
}
diff --git a/whats-new-in-spring-boot-2.2/src/test/java/de/rieckpil/blog/ApplicationTests.java b/whats-new-in-spring-boot-2.2/src/test/java/de/rieckpil/blog/ApplicationTests.java
index f8704546..fa726c98 100644
--- a/whats-new-in-spring-boot-2.2/src/test/java/de/rieckpil/blog/ApplicationTests.java
+++ b/whats-new-in-spring-boot-2.2/src/test/java/de/rieckpil/blog/ApplicationTests.java
@@ -9,8 +9,6 @@
@SpringBootTest
public class ApplicationTests {
- @Test
- public void contextLoads() {
- }
-
+ @Test
+ public void contextLoads() {}
}
diff --git a/whats-new-in-spring-boot-2.2/src/test/java/de/rieckpil/blog/JUnit5Test.java b/whats-new-in-spring-boot-2.2/src/test/java/de/rieckpil/blog/JUnit5Test.java
index 1b390bfd..6634f60b 100644
--- a/whats-new-in-spring-boot-2.2/src/test/java/de/rieckpil/blog/JUnit5Test.java
+++ b/whats-new-in-spring-boot-2.2/src/test/java/de/rieckpil/blog/JUnit5Test.java
@@ -1,14 +1,14 @@
package de.rieckpil.blog;
-import org.junit.jupiter.api.Test;
-
import static org.junit.jupiter.api.Assertions.assertEquals;
+import org.junit.jupiter.api.Test;
+
public class JUnit5Test {
- @Test
- public void testMe() {
- var sum = 2 + 2;
- assertEquals(4, sum);
- }
+ @Test
+ public void testMe() {
+ var sum = 2 + 2;
+ assertEquals(4, sum);
+ }
}
diff --git a/whats-new-in-spring-boot-2.3/.java-version b/whats-new-in-spring-boot-2.3/.java-version
deleted file mode 100644
index ed9d00f9..00000000
--- a/whats-new-in-spring-boot-2.3/.java-version
+++ /dev/null
@@ -1 +0,0 @@
-14.0
diff --git a/whats-new-in-spring-boot-2.3/pom.xml b/whats-new-in-spring-boot-2.3/pom.xml
index 0633013d..e75afed9 100644
--- a/whats-new-in-spring-boot-2.3/pom.xml
+++ b/whats-new-in-spring-boot-2.3/pom.xml
@@ -4,22 +4,17 @@
4.0.0
- org.springframework.boot
- spring-boot-starter-parent
- 2.3.0.RELEASE
-
+ de.rieckpil.blog
+ blog-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
- de.rieckpil.blog
whats-new-in-spring-boot-2-3
0.0.1-SNAPSHOT
whats-new-in-spring-boot-2-3
Updates with Spring Boot 2.3
-
- 14
-
-
org.springframework.boot
@@ -56,7 +51,7 @@
spring-boot-maven-plugin
- --enable-preview
+ --enable-preview
true
@@ -64,7 +59,7 @@
myregistry.com/rieckpil/${project.artifactId}
- 14.0.1
+ ${java.version}
@@ -76,24 +71,6 @@
-
- org.apache.maven.plugins
- maven-compiler-plugin
-
-
- --enable-preview
-
-
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
-
-
- --enable-preview
-
-
-
diff --git a/whats-new-in-spring-boot-2.3/src/main/java/de/rieckpil/blog/SampleController.java b/whats-new-in-spring-boot-2.3/src/main/java/de/rieckpil/blog/SampleController.java
index dfd2cabb..316ef0e6 100644
--- a/whats-new-in-spring-boot-2.3/src/main/java/de/rieckpil/blog/SampleController.java
+++ b/whats-new-in-spring-boot-2.3/src/main/java/de/rieckpil/blog/SampleController.java
@@ -1,33 +1,31 @@
package de.rieckpil.blog;
+import jakarta.validation.constraints.Max;
+import jakarta.validation.constraints.Positive;
+import java.time.LocalDate;
+import java.util.List;
+import java.util.stream.Collectors;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
-import javax.validation.constraints.Max;
-import javax.validation.constraints.Positive;
-import java.time.LocalDate;
-import java.util.List;
-import java.util.stream.Collectors;
-
@Validated
@RestController
public class SampleController {
@GetMapping("/messages")
public List getMessages(@RequestParam("size") @Positive @Max(6) Integer size) {
- return List.of("Hello", "World", "Foo", "Bar", "Duke", "Spring")
- .stream()
- .limit(size)
- .collect(Collectors.toList());
-
+ return List.of("Hello", "World", "Foo", "Bar", "Duke", "Spring").stream()
+ .limit(size)
+ .collect(Collectors.toList());
}
@GetMapping("/users")
public List getUsers() {
- return List.of(new User("Duke", LocalDate.now(), true),
- new User("Duke", LocalDate.now().minusDays(1), false));
+ return List.of(
+ new User("Duke", LocalDate.now(), true),
+ new User("Duke", LocalDate.now().minusDays(1), false));
}
@GetMapping("/api/customers")
diff --git a/whats-new-in-spring-boot-2.3/src/main/java/de/rieckpil/blog/User.java b/whats-new-in-spring-boot-2.3/src/main/java/de/rieckpil/blog/User.java
index a1073375..d9876ee4 100644
--- a/whats-new-in-spring-boot-2.3/src/main/java/de/rieckpil/blog/User.java
+++ b/whats-new-in-spring-boot-2.3/src/main/java/de/rieckpil/blog/User.java
@@ -1,10 +1,7 @@
package de.rieckpil.blog;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
-
import java.time.LocalDate;
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
-public record User(String name, LocalDate dateOfBirth, boolean isRegistered) {
-}
-
+public record User(String name, LocalDate dateOfBirth, boolean isRegistered) {}
diff --git a/whats-new-in-spring-boot-2.3/src/main/java/de/rieckpil/blog/WhatsNewInSpringBoot23Application.java b/whats-new-in-spring-boot-2.3/src/main/java/de/rieckpil/blog/WhatsNewInSpringBoot23Application.java
index 9b60e3b9..512eb562 100644
--- a/whats-new-in-spring-boot-2.3/src/main/java/de/rieckpil/blog/WhatsNewInSpringBoot23Application.java
+++ b/whats-new-in-spring-boot-2.3/src/main/java/de/rieckpil/blog/WhatsNewInSpringBoot23Application.java
@@ -9,5 +9,4 @@ public class WhatsNewInSpringBoot23Application {
public static void main(String[] args) {
SpringApplication.run(WhatsNewInSpringBoot23Application.class, args);
}
-
}
diff --git a/whats-new-in-spring-boot-2.3/src/test/java/de/rieckpil/blog/WhatsNewInSpringBoot23ApplicationTests.java b/whats-new-in-spring-boot-2.3/src/test/java/de/rieckpil/blog/WhatsNewInSpringBoot23ApplicationTests.java
index ccab3ab2..13ff41e3 100644
--- a/whats-new-in-spring-boot-2.3/src/test/java/de/rieckpil/blog/WhatsNewInSpringBoot23ApplicationTests.java
+++ b/whats-new-in-spring-boot-2.3/src/test/java/de/rieckpil/blog/WhatsNewInSpringBoot23ApplicationTests.java
@@ -7,7 +7,5 @@
class WhatsNewInSpringBoot23ApplicationTests {
@Test
- void contextLoads() {
- }
-
+ void contextLoads() {}
}
diff --git a/write-concise-web-tests-with-selenide/pom.xml b/write-concise-web-tests-with-selenide/pom.xml
index bea7066b..7aabaeb1 100644
--- a/write-concise-web-tests-with-selenide/pom.xml
+++ b/write-concise-web-tests-with-selenide/pom.xml
@@ -2,23 +2,22 @@
4.0.0
+
- org.springframework.boot
- spring-boot-starter-parent
- 2.3.4.RELEASE
-
+ de.rieckpil.blog
+ blog-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
- de.rieckpil.blog
write-concise-web-tests-with-selenide
0.0.1-SNAPSHOT
write-concise-web-tests-with-selenide
Concise Web Tests with Selenide
- 11
- 5.15.0
- 1.15.1
+ 7.0.4
+ 4.16.1
@@ -35,12 +34,6 @@
org.springframework.boot
spring-boot-starter-test
test
-
-
- org.junit.vintage
- junit-vintage-engine
-
-
com.codeborne
@@ -63,21 +56,6 @@
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
-
- org.apache.maven.plugins
- maven-failsafe-plugin
- 3.0.0-M5
-
-
- **/*WT.java
-
-
-
-
+
diff --git a/write-concise-web-tests-with-selenide/src/main/java/de/rieckpil/blog/Application.java b/write-concise-web-tests-with-selenide/src/main/java/de/rieckpil/blog/Application.java
index bd5e4c56..6511f3c1 100644
--- a/write-concise-web-tests-with-selenide/src/main/java/de/rieckpil/blog/Application.java
+++ b/write-concise-web-tests-with-selenide/src/main/java/de/rieckpil/blog/Application.java
@@ -9,5 +9,4 @@ public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
-
}
diff --git a/write-concise-web-tests-with-selenide/src/main/java/de/rieckpil/blog/Book.java b/write-concise-web-tests-with-selenide/src/main/java/de/rieckpil/blog/Book.java
index 2f521a29..049caade 100644
--- a/write-concise-web-tests-with-selenide/src/main/java/de/rieckpil/blog/Book.java
+++ b/write-concise-web-tests-with-selenide/src/main/java/de/rieckpil/blog/Book.java
@@ -6,8 +6,7 @@ public class Book {
private String isbn;
private String title;
- public Book() {
- }
+ public Book() {}
public Book(Long id, String isbn, String title) {
this.id = id;
diff --git a/write-concise-web-tests-with-selenide/src/main/java/de/rieckpil/blog/BookController.java b/write-concise-web-tests-with-selenide/src/main/java/de/rieckpil/blog/BookController.java
index cbe79d27..73ad5ca0 100644
--- a/write-concise-web-tests-with-selenide/src/main/java/de/rieckpil/blog/BookController.java
+++ b/write-concise-web-tests-with-selenide/src/main/java/de/rieckpil/blog/BookController.java
@@ -1,11 +1,10 @@
package de.rieckpil.blog;
+import java.util.List;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
-import java.util.List;
-
@RestController
@RequestMapping("/api/books")
public class BookController {
diff --git a/write-concise-web-tests-with-selenide/src/test/java/de/rieckpil/blog/BookStoreTestcontainersWT.java b/write-concise-web-tests-with-selenide/src/test/java/de/rieckpil/blog/BookStoreTestcontainersWT.java
index c218e656..6fbeca80 100644
--- a/write-concise-web-tests-with-selenide/src/test/java/de/rieckpil/blog/BookStoreTestcontainersWT.java
+++ b/write-concise-web-tests-with-selenide/src/test/java/de/rieckpil/blog/BookStoreTestcontainersWT.java
@@ -1,48 +1,58 @@
package de.rieckpil.blog;
+import static com.codeborne.selenide.Selenide.$;
+import static com.codeborne.selenide.Selenide.open;
+import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+
import com.codeborne.selenide.Condition;
import com.codeborne.selenide.Configuration;
import com.codeborne.selenide.WebDriverRunner;
import com.codeborne.selenide.junit5.ScreenShooterExtension;
+import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.openqa.selenium.By;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.RemoteWebDriver;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.boot.web.server.LocalServerPort;
+import org.springframework.boot.test.web.server.LocalServerPort;
+import org.springframework.core.env.Environment;
+import org.testcontainers.Testcontainers;
import org.testcontainers.containers.BrowserWebDriverContainer;
-import org.testcontainers.junit.jupiter.Container;
-import org.testcontainers.junit.jupiter.Testcontainers;
+import org.testcontainers.utility.DockerImageName;
-import static com.codeborne.selenide.Selenide.$;
-import static com.codeborne.selenide.Selenide.open;
-import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
-
-@Testcontainers(disabledWithoutDocker = true)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
-public class BookStoreTestcontainersWT {
+class BookStoreTestcontainersWT {
- @Container
public static BrowserWebDriverContainer> webDriverContainer =
- new BrowserWebDriverContainer<>()
- .withCapabilities(new ChromeOptions()
- .addArguments("--no-sandbox")
- .addArguments("--disable-dev-shm-usage"));
+ new BrowserWebDriverContainer<>(
+ System.getProperty("os.arch").equals("aarch64")
+ ? DockerImageName.parse("seleniarm/standalone-chromium")
+ .asCompatibleSubstituteFor("selenium/standalone-chrome")
+ : DockerImageName.parse("selenium/standalone-chrome"))
+ .withCapabilities(
+ new ChromeOptions()
+ .addArguments("--no-sandbox")
+ .addArguments("--disable-dev-shm-usage"));
@RegisterExtension
- public static ScreenShooterExtension screenShooterExtension =
- new ScreenShooterExtension().to("target/selenide");
+ static ScreenShooterExtension screenShooterExtension =
+ new ScreenShooterExtension().to("target/selenide");
- @LocalServerPort
- private Integer port;
+ @LocalServerPort private Integer port;
- @Test
- public void shouldDisplayBook() {
+ @BeforeAll
+ static void beforeAll(@Autowired Environment environment) {
+ Testcontainers.exposeHostPorts(environment.getProperty("local.server.port", Integer.class));
+ webDriverContainer.start();
+ }
+ @Test
+ void shouldDisplayBook() {
Configuration.timeout = 2000;
- Configuration.baseUrl = "http://172.17.0.1/" + port;
+ Configuration.baseUrl = String.format("http://host.testcontainers.internal:%d", port);
RemoteWebDriver remoteWebDriver = webDriverContainer.getWebDriver();
WebDriverRunner.setWebDriver(remoteWebDriver);
diff --git a/write-concise-web-tests-with-selenide/src/test/java/de/rieckpil/blog/BookStoreWT.java b/write-concise-web-tests-with-selenide/src/test/java/de/rieckpil/blog/BookStoreWT.java
index be714149..7742124f 100644
--- a/write-concise-web-tests-with-selenide/src/test/java/de/rieckpil/blog/BookStoreWT.java
+++ b/write-concise-web-tests-with-selenide/src/test/java/de/rieckpil/blog/BookStoreWT.java
@@ -1,5 +1,9 @@
package de.rieckpil.blog;
+import static com.codeborne.selenide.Selenide.*;
+import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+
+import com.codeborne.selenide.CollectionCondition;
import com.codeborne.selenide.Condition;
import com.codeborne.selenide.Configuration;
import com.codeborne.selenide.junit5.ScreenShooterExtension;
@@ -10,24 +14,19 @@
import org.openqa.selenium.By;
import org.openqa.selenium.chrome.ChromeOptions;
import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.boot.web.server.LocalServerPort;
-
-import static com.codeborne.selenide.Selenide.*;
-import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.boot.test.web.server.LocalServerPort;
-@Disabled
+@Disabled("Failing on CI, to be fixed")
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
-public class BookStoreWT {
+class BookStoreWT {
- @LocalServerPort
- private Integer port;
+ @LocalServerPort private Integer port;
@RegisterExtension
- public static ScreenShooterExtension extension =
- new ScreenShooterExtension().to("target/selenide");
+ static ScreenShooterExtension extension = new ScreenShooterExtension().to("target/selenide");
@BeforeAll
- public static void configureChromeDriver() {
+ static void configureChromeDriver() {
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.addArguments("--no-sandbox", "--disable-dev-shm-usage");
@@ -35,11 +34,12 @@ public static void configureChromeDriver() {
}
@Test
- public void shouldDisplayBooks() {
+ void shouldDisplayBooks() {
Configuration.reportsFolder = "target/selenide";
+ Configuration.baseUrl = "http://localhost/" + port;
- open("http://localhost/" + port + "/book-store");
+ open("/book-store");
$(By.id("all-books")).shouldNot(Condition.exist);
@@ -47,6 +47,6 @@ public void shouldDisplayBooks() {
$(By.id("fetch-books")).click();
$(By.id("all-books")).shouldBe(Condition.visible);
- $$(By.tagName("h1")).shouldHaveSize(1);
+ $$(By.tagName("h1")).shouldHave(CollectionCondition.size(1));
}
}
diff --git a/write-concise-web-tests-with-selenide/src/test/java/de/rieckpil/blog/BookStoreYouTubeWT.java b/write-concise-web-tests-with-selenide/src/test/java/de/rieckpil/blog/BookStoreYouTubeWT.java
index b897b207..ffa8ab74 100644
--- a/write-concise-web-tests-with-selenide/src/test/java/de/rieckpil/blog/BookStoreYouTubeWT.java
+++ b/write-concise-web-tests-with-selenide/src/test/java/de/rieckpil/blog/BookStoreYouTubeWT.java
@@ -1,45 +1,58 @@
package de.rieckpil.blog;
+import static com.codeborne.selenide.Selenide.*;
+import static org.testcontainers.Testcontainers.exposeHostPorts;
+
import com.codeborne.selenide.Condition;
import com.codeborne.selenide.Configuration;
import com.codeborne.selenide.WebDriverRunner;
import com.codeborne.selenide.junit5.ScreenShooterExtension;
+import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.openqa.selenium.By;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.RemoteWebDriver;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.boot.web.server.LocalServerPort;
+import org.springframework.boot.test.web.server.LocalServerPort;
+import org.springframework.core.env.Environment;
import org.testcontainers.containers.BrowserWebDriverContainer;
-import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
-
-import static com.codeborne.selenide.Selenide.*;
+import org.testcontainers.utility.DockerImageName;
@Testcontainers(disabledWithoutDocker = true)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
-public class BookStoreYouTubeWT {
+class BookStoreYouTubeWT {
- @LocalServerPort
- private Integer port;
+ @LocalServerPort private Integer port;
- @Container
public static BrowserWebDriverContainer> webDriverContainer =
- new BrowserWebDriverContainer<>()
- .withCapabilities(new ChromeOptions()
- .addArguments("--no-sandbox")
- .addArguments("--disable-dev-shm-usage"));
+ new BrowserWebDriverContainer<>(
+ System.getProperty("os.arch").equals("aarch64")
+ ? DockerImageName.parse("seleniarm/standalone-chromium")
+ .asCompatibleSubstituteFor("selenium/standalone-chrome")
+ : DockerImageName.parse("selenium/standalone-chrome"))
+ .withCapabilities(
+ new ChromeOptions()
+ .addArguments("--no-sandbox")
+ .addArguments("--disable-dev-shm-usage"));
@RegisterExtension
- public static ScreenShooterExtension screenShooterExtension =
- new ScreenShooterExtension().to("target/selenide");
+ static ScreenShooterExtension screenShooterExtension =
+ new ScreenShooterExtension().to("target/selenide");
+
+ @BeforeAll
+ static void beforeAll(@Autowired Environment environment) {
+ exposeHostPorts(environment.getProperty("local.server.port", Integer.class));
+ webDriverContainer.start();
+ }
@Test
- public void shouldDisplayBook() {
+ void shouldDisplayBook() {
Configuration.timeout = 2000;
- Configuration.baseUrl = "http://172.17.0.1/" + port;
+ Configuration.baseUrl = String.format("http://host.testcontainers.internal:%d", port);
RemoteWebDriver remoteWebDriver = webDriverContainer.getWebDriver();
WebDriverRunner.setWebDriver(remoteWebDriver);