diff --git a/config-server/.gitignore b/config-server/.gitignore
new file mode 100644
index 0000000..549e00a
--- /dev/null
+++ b/config-server/.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/config-server/.mvn/wrapper/maven-wrapper.jar b/config-server/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..c1dd12f
Binary files /dev/null and b/config-server/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/config-server/.mvn/wrapper/maven-wrapper.properties b/config-server/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..b7cb93e
--- /dev/null
+++ b/config-server/.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/config-server/mvnw b/config-server/mvnw
new file mode 100644
index 0000000..8a8fb22
--- /dev/null
+++ b/config-server/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/config-server/mvnw.cmd b/config-server/mvnw.cmd
new file mode 100644
index 0000000..1d8ab01
--- /dev/null
+++ b/config-server/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/config-server/pom.xml b/config-server/pom.xml
new file mode 100644
index 0000000..e958ac7
--- /dev/null
+++ b/config-server/pom.xml
@@ -0,0 +1,53 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.6.6
+
+
+ com.example
+ config-server
+ 0.0.1-SNAPSHOT
+ config-server
+ Demo project for Spring Boot
+
+ 17
+ 2021.0.1
+
+
+
+ org.springframework.cloud
+ spring-cloud-config-server
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/config-server/src/main/java/com/example/configserver/ConfigServerApplication.java b/config-server/src/main/java/com/example/configserver/ConfigServerApplication.java
new file mode 100644
index 0000000..b37b844
--- /dev/null
+++ b/config-server/src/main/java/com/example/configserver/ConfigServerApplication.java
@@ -0,0 +1,15 @@
+package com.example.configserver;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.config.server.EnableConfigServer;
+
+@SpringBootApplication
+@EnableConfigServer
+public class ConfigServerApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(ConfigServerApplication.class, args);
+ }
+
+}
\ No newline at end of file
diff --git a/config-server/src/main/resources/application.properties b/config-server/src/main/resources/application.properties
new file mode 100644
index 0000000..259a027
--- /dev/null
+++ b/config-server/src/main/resources/application.properties
@@ -0,0 +1,3 @@
+server.port= 8888
+spring.application.name=config-server
+spring.cloud.config.server.git.uri= https://github.com/NeacsuAlex/PCJ.git
diff --git a/config-server/src/test/java/com/example/configserver/ConfigServerApplicationTests.java b/config-server/src/test/java/com/example/configserver/ConfigServerApplicationTests.java
new file mode 100644
index 0000000..cdf8337
--- /dev/null
+++ b/config-server/src/test/java/com/example/configserver/ConfigServerApplicationTests.java
@@ -0,0 +1,13 @@
+package com.example.configserver;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class ConfigServerApplicationTests {
+
+ @Test
+ void contextLoads() {
+ }
+
+}
diff --git a/eureka/.gitignore b/eureka/.gitignore
new file mode 100644
index 0000000..549e00a
--- /dev/null
+++ b/eureka/.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/eureka/discovery-server/.gitignore b/eureka/discovery-server/.gitignore
new file mode 100644
index 0000000..549e00a
--- /dev/null
+++ b/eureka/discovery-server/.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/eureka/discovery-server/pom.xml b/eureka/discovery-server/pom.xml
new file mode 100644
index 0000000..fd67994
--- /dev/null
+++ b/eureka/discovery-server/pom.xml
@@ -0,0 +1,53 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.6.4
+
+
+ com.example
+ discovery-server
+ 0.0.1-SNAPSHOT
+ discovery-server
+ discovery-server
+
+ 11
+ 2021.0.1
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-netflix-eureka-server
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/eureka/discovery-server/src/main/java/com/example/discovery/DiscoveryServer.java b/eureka/discovery-server/src/main/java/com/example/discovery/DiscoveryServer.java
new file mode 100644
index 0000000..9e6e7d0
--- /dev/null
+++ b/eureka/discovery-server/src/main/java/com/example/discovery/DiscoveryServer.java
@@ -0,0 +1,27 @@
+package com.example.discovery;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
+
+import java.io.IOException;
+
+@EnableEurekaServer
+@SpringBootApplication
+public class DiscoveryServer {
+
+ private static Logger logger = LoggerFactory.getLogger(DiscoveryServer.class);
+
+ public static void main(String... args) throws IOException {
+ // Look for configuration in discovery-server.properties or discovery-server.yml
+ System.setProperty("spring.config.name", "discovery-server");
+
+ var ctx = SpringApplication.run(DiscoveryServer.class, args);
+ assert (ctx != null);
+ logger.info("Started ...");
+ System.in.read();
+ ctx.close();
+ }
+}
diff --git a/eureka/discovery-server/src/main/resources/discovery-server.yml b/eureka/discovery-server/src/main/resources/discovery-server.yml
new file mode 100644
index 0000000..5e64aab
--- /dev/null
+++ b/eureka/discovery-server/src/main/resources/discovery-server.yml
@@ -0,0 +1,23 @@
+spring:
+ application:
+ name: discovery-service
+# Configure this Discovery Server
+#TODO here you add configurations for server
+
+logging:
+ pattern:
+ console: "%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"
+ level:
+ root: INFO
+ org.springframework: DEBUG
+ com.apress.cems: DEBUG
+ com.netflix.eureka: OFF
+ com.netflix.discovery: OFF
+
+server:
+ port: 3000
+
+eureka:
+ client:
+ register-with-eureka: false
+ fetch-registry: false
diff --git a/eureka/discovery-server/src/test/java/com/example/discoveryserver/DiscoveryServerApplicationTests.java b/eureka/discovery-server/src/test/java/com/example/discoveryserver/DiscoveryServerApplicationTests.java
new file mode 100644
index 0000000..f102053
--- /dev/null
+++ b/eureka/discovery-server/src/test/java/com/example/discoveryserver/DiscoveryServerApplicationTests.java
@@ -0,0 +1,13 @@
+package com.example.discoveryserver;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class DiscoveryServerApplicationTests {
+
+ @Test
+ void contextLoads() {
+ }
+
+}
diff --git a/eureka/persons-server/.gitignore b/eureka/persons-server/.gitignore
new file mode 100644
index 0000000..549e00a
--- /dev/null
+++ b/eureka/persons-server/.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/eureka/persons-server/pom.xml b/eureka/persons-server/pom.xml
new file mode 100644
index 0000000..b342d8e
--- /dev/null
+++ b/eureka/persons-server/pom.xml
@@ -0,0 +1,96 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.6.4
+
+
+ com.example
+ persons-server
+ 0.0.1-SNAPSHOT
+ persons-server
+ persons-server
+
+ 11
+ 2021.0.1
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.cloud
+ spring-cloud-starter-netflix-eureka-client
+
+
+ org.springframework.cloud
+ spring-cloud-starter-netflix-eureka-server
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ com.h2database
+ h2
+ 2.1.210
+ runtime
+
+
+ com.sun.jersey.contribs
+ jersey-apache-client4
+ 1.19.4
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ 2.13.1
+
+
+ com.fasterxml.jackson.core
+ jackson-core
+ 2.13.1
+
+
+ javax.validation
+ validation-api
+ 2.0.1.Final
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/eureka/persons-server/src/main/java/com/eureka/persons/PersonRepo.java b/eureka/persons-server/src/main/java/com/eureka/persons/PersonRepo.java
new file mode 100644
index 0000000..5e7b169
--- /dev/null
+++ b/eureka/persons-server/src/main/java/com/eureka/persons/PersonRepo.java
@@ -0,0 +1,36 @@
+package com.eureka.persons;
+
+import com.eureka.persons.person.Person;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Optional;
+
+@Repository
+public interface PersonRepo extends JpaRepository {
+
+ @Query("select p from Person p where p.username like %?1%")
+ Optional findByUsername(String username);
+
+ @Query("select p from Person p where p.username like %?1%")
+ List findByUsernameLike(String username);
+
+ @Query("select p from Person p where p.firstName=:fn")
+ List findByFirstName(@Param("fn") String firstName);
+
+ @Query("select p from Person p where p.firstName like %?1%")
+ List findByFirstNameLike(String firstName);
+
+ @Query("select p from Person p where p.lastName=:ln")
+ List findByLastName(@Param("ln") String lastName);
+
+ @Query("select p from Person p where p.lastName like %?1%")
+ List findByLastNameLike(String lastName);
+
+ @Query("select p from Person p where p.hiringDate=:hd")
+ List findByHiringDate(@Param("hd") LocalDateTime date);
+}
diff --git a/eureka/persons-server/src/main/java/com/eureka/persons/PersonsController.java b/eureka/persons-server/src/main/java/com/eureka/persons/PersonsController.java
new file mode 100644
index 0000000..97985a9
--- /dev/null
+++ b/eureka/persons-server/src/main/java/com/eureka/persons/PersonsController.java
@@ -0,0 +1,92 @@
+package com.eureka.persons;
+
+import com.eureka.persons.ex.NotFoundException;
+import com.eureka.persons.person.Person;
+import com.eureka.persons.services.PersonService;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.validation.BindingResult;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RestController
+@RequestMapping("/persons")
+public class PersonsController {
+ private PersonService personService;
+
+ public PersonsController(PersonService personService) {
+ this.personService = personService;
+ }
+
+ /**
+ * Handles requests to list all persons.
+ */
+ //TODO find all persons using the functions already implemented and sort them by id
+ @ResponseStatus(HttpStatus.OK)
+ @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
+ public List list() {
+
+ return personService.findAll();
+ }
+
+ /**
+ * Handles requests to create a person.
+ */
+ //TODO save a person to the db or throw PersonsException
+ @ResponseStatus(HttpStatus.CREATED)
+ @PostMapping
+ public void create(@RequestBody Person person, BindingResult result) {
+ if(result.hasErrors())
+ throw new PersonsException(HttpStatus.BAD_REQUEST, "Persons Exception");
+ personService.save(person);
+ }
+
+ /**
+ * Returns the {@code Person} instance with id {@code id}
+ *
+ * @param id
+ * @return
+ */
+ //TODO find a person by id or throw NotFoundException
+ @ResponseStatus(HttpStatus.OK)
+ @GetMapping(value = "/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
+ public Person show(@PathVariable Long id) {
+
+ return personService.findById(id).orElseThrow(()->new NotFoundException(Person.class,id));
+ }
+
+ /**
+ * Updates the {@code Person} instance with id {@code id}
+ *
+ * @param updatedPerson
+ * @param id
+ * @return
+ */
+ //TODO update an existing person if found else throw NotFoundException
+ @ResponseStatus(HttpStatus.NO_CONTENT)
+ @PutMapping("/{id}")
+ public void update(@RequestBody Person updatedPerson, @PathVariable Long id) {
+ Person result = personService.findById(id).orElseThrow(()->new NotFoundException(Person.class,id));
+ result.setFirstName(updatedPerson.getFirstName());
+ result.setLastName(updatedPerson.getLastName());
+ result.setPassword(updatedPerson.getPassword());
+ result.setHiringDate(updatedPerson.getHiringDate());
+ result.setNewPassword(updatedPerson.getNewPassword());
+ result.setUsername(updatedPerson.getUsername());
+ personService.save(result);
+ }
+
+ /**
+ * Delete the {@code Person} instance with id {@code id}
+ *
+ * @param id
+ */
+ //TODO delete a person
+ @ResponseStatus(HttpStatus.NO_CONTENT)
+ @DeleteMapping("/{id}")
+ public void delete(@PathVariable Long id) {
+ personService.delete(personService.findById(id).orElseThrow(()->new NotFoundException(Person.class,id)));
+ }
+}
\ No newline at end of file
diff --git a/eureka/persons-server/src/main/java/com/eureka/persons/PersonsException.java b/eureka/persons-server/src/main/java/com/eureka/persons/PersonsException.java
new file mode 100644
index 0000000..781c4f6
--- /dev/null
+++ b/eureka/persons-server/src/main/java/com/eureka/persons/PersonsException.java
@@ -0,0 +1,17 @@
+package com.eureka.persons;
+
+import org.springframework.http.HttpStatus;
+
+public class PersonsException extends RuntimeException{
+ private HttpStatus status;
+
+ public PersonsException(HttpStatus status, String message) {
+ super(message);
+ this.status = status;
+ }
+
+ public PersonsException(HttpStatus status, Throwable cause) {
+ super(cause);
+ this.status = status;
+ }
+}
diff --git a/eureka/persons-server/src/main/java/com/eureka/persons/PersonsServer.java b/eureka/persons-server/src/main/java/com/eureka/persons/PersonsServer.java
new file mode 100644
index 0000000..ba17aa9
--- /dev/null
+++ b/eureka/persons-server/src/main/java/com/eureka/persons/PersonsServer.java
@@ -0,0 +1,30 @@
+package com.eureka.persons;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.domain.EntityScan;
+import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
+import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
+
+import java.io.IOException;
+
+@EnableEurekaClient
+@EntityScan(basePackages = "com.eureka.persons")
+@SpringBootApplication
+public class PersonsServer {
+
+ private static Logger logger = LoggerFactory.getLogger(PersonsServer.class);
+
+ public static void main(String... args) throws IOException {
+ // Look for configuration in persons-server.properties or persons-server.yml
+ System.setProperty("spring.config.name", "persons-server");
+
+ var ctx = SpringApplication.run(PersonsServer.class, args);
+ assert (ctx != null);
+ logger.info("Started ...");
+ System.in.read();
+ ctx.close();
+ }
+}
diff --git a/eureka/persons-server/src/main/java/com/eureka/persons/base/AbstractEntity.java b/eureka/persons-server/src/main/java/com/eureka/persons/base/AbstractEntity.java
new file mode 100644
index 0000000..199103b
--- /dev/null
+++ b/eureka/persons-server/src/main/java/com/eureka/persons/base/AbstractEntity.java
@@ -0,0 +1,70 @@
+package com.eureka.persons.base;
+
+import com.eureka.persons.util.DateProcessor;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import javax.persistence.*;
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import java.util.Comparator;
+import java.util.Objects;
+
+@MappedSuperclass
+@Getter
+@Setter
+public abstract class AbstractEntity implements Serializable {
+
+ public static Comparator COMPARATOR_BY_ID = Comparator.comparing(AbstractEntity::getId);
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ @Column(updatable = false)
+ protected Long id;
+
+ @Version
+ protected int version;
+
+ @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = DateProcessor.DATE_FORMAT)
+ @Column(name = "created_at", nullable = false)
+ @DateTimeFormat(pattern = DateProcessor.DATE_FORMAT)
+ protected LocalDateTime createdAt;
+
+
+ @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = DateProcessor.DATE_FORMAT)
+ @Column(name = "modified_at", nullable = false)
+ @DateTimeFormat(pattern = DateProcessor.DATE_FORMAT)
+ protected LocalDateTime modifiedAt;
+
+ /**
+ * This constructor is required by JPA. All subclasses of this class will inherit this constructor.
+ */
+ protected AbstractEntity() {
+ createdAt = LocalDateTime.now();
+ modifiedAt = LocalDateTime.now();
+ }
+
+ // IDE generated methods
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ var that = (AbstractEntity) o;
+ if (!Objects.equals(id, that.id)) return false;
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return id != null ? id.hashCode() : 0;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("AbstractEntity[id='%d%n', createdAt='%s', modifiedAt='%s', version='%d%n']",
+ id, DateProcessor.toString(createdAt), DateProcessor.toString(modifiedAt), version);
+ }
+}
diff --git a/eureka/persons-server/src/main/java/com/eureka/persons/ex/NotFoundException.java b/eureka/persons-server/src/main/java/com/eureka/persons/ex/NotFoundException.java
new file mode 100644
index 0000000..094ecec
--- /dev/null
+++ b/eureka/persons-server/src/main/java/com/eureka/persons/ex/NotFoundException.java
@@ -0,0 +1,7 @@
+package com.eureka.persons.ex;
+
+public class NotFoundException extends RuntimeException {
+ public NotFoundException(Class cls, Long id) {
+ super(cls.getSimpleName() + " with id: " + id + " does not exist!");
+ }
+}
diff --git a/eureka/persons-server/src/main/java/com/eureka/persons/person/Person.java b/eureka/persons-server/src/main/java/com/eureka/persons/person/Person.java
new file mode 100644
index 0000000..9064df8
--- /dev/null
+++ b/eureka/persons-server/src/main/java/com/eureka/persons/person/Person.java
@@ -0,0 +1,82 @@
+package com.eureka.persons.person;
+
+import com.eureka.persons.base.AbstractEntity;
+import com.eureka.persons.util.DateProcessor;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Transient;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import java.time.LocalDateTime;
+import java.util.Objects;
+
+@Entity
+@Getter
+@Setter
+@NoArgsConstructor
+public class Person extends AbstractEntity {
+ interface BasicValidation{}
+
+ @NotNull(groups = BasicValidation.class)
+ @Size(min = 3, max = 30, groups = BasicValidation.class)
+ @Column(nullable = false, unique = true)
+ private String username;
+
+ @NotNull(groups = BasicValidation.class)
+ @Size(min = 3, max = 30, groups = BasicValidation.class)
+ @Column(nullable = false)
+ private String firstName;
+
+ @NotNull(groups = BasicValidation.class)
+ @Size(min = 3, max = 30, groups = BasicValidation.class)
+ @Column(nullable = false)
+ private String lastName;
+
+ @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
+ @NotNull
+ @Size(min = 4, max = 50)
+ @Column(nullable = false)
+ private String password;
+
+ @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = DateProcessor.DATE_FORMAT)
+ @NotNull(groups = BasicValidation.class)
+ @Column(nullable = false)
+ @DateTimeFormat(pattern = DateProcessor.DATE_FORMAT)
+ private LocalDateTime hiringDate;
+
+ @JsonIgnore
+ @Transient
+ private String newPassword;
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ var person = (Person) o;
+ if (!Objects.equals(id, person.id)) return false;
+ return Objects.equals(firstName, person.firstName) &&
+ Objects.equals(lastName, person.lastName) &&
+ Objects.equals(hiringDate.toLocalDate(), person.hiringDate.toLocalDate());
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(super.hashCode(), firstName, lastName, hiringDate.toLocalDate());
+ }
+
+ @Override
+ public String toString() {
+ return String.format("Person[username='%s', firstName='%s', lastName='%s', hiringDate='%s']\n",
+ username, firstName, lastName, hiringDate.toString());
+
+ }
+
+}
diff --git a/eureka/persons-server/src/main/java/com/eureka/persons/services/Initializer.java b/eureka/persons-server/src/main/java/com/eureka/persons/services/Initializer.java
new file mode 100644
index 0000000..22024a4
--- /dev/null
+++ b/eureka/persons-server/src/main/java/com/eureka/persons/services/Initializer.java
@@ -0,0 +1,65 @@
+package com.eureka.persons.services;
+
+import com.eureka.persons.person.Person;
+import com.eureka.persons.util.DateProcessor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.PostConstruct;
+
+@Service
+@Transactional
+public class Initializer {
+ private Logger logger = LoggerFactory.getLogger(Initializer.class);
+
+ private PersonService personService;
+
+ public Initializer(PersonService personService) {
+ this.personService = personService;
+ }
+
+ @PostConstruct
+ public void init() {
+ logger.info(" -->> Starting database initialization...");
+ if (personService.findAll().isEmpty()) {
+ createPersons();
+ }
+ logger.info(" -->> Database initialization finished.");
+ }
+
+ private void createPersons() {
+ Person person = new Person();
+ person.setUsername("sherlock.holmes");
+ person.setFirstName("Sherlock");
+ person.setLastName("Holmes");
+ person.setPassword("dudu");
+ person.setHiringDate(DateProcessor.toDate("1983-08-15 00:23"));
+ personService.save(person);
+
+ person = new Person();
+ person.setUsername("jackson.brodie");
+ person.setFirstName("Jackson");
+ person.setLastName("Brodie");
+ person.setPassword("bagy");
+ person.setHiringDate(DateProcessor.toDate("1983-06-22 00:23"));
+ personService.save(person);
+
+ person = new Person();
+ person.setUsername("nancy.drew");
+ person.setFirstName("Nancy");
+ person.setLastName("Drew");
+ person.setPassword("dada45");
+ person.setHiringDate(DateProcessor.toDate("1990-05-21 00:23"));
+ personService.save(person);
+
+ person = new Person();
+ person.setUsername("irene.adler");
+ person.setFirstName("Irene");
+ person.setLastName("Adler");
+ person.setPassword("xxxyy");
+ person.setHiringDate(DateProcessor.toDate("1987-03-11 00:23"));
+ personService.save(person);
+ }
+}
\ No newline at end of file
diff --git a/eureka/persons-server/src/main/java/com/eureka/persons/services/PersonService.java b/eureka/persons-server/src/main/java/com/eureka/persons/services/PersonService.java
new file mode 100644
index 0000000..0f86a73
--- /dev/null
+++ b/eureka/persons-server/src/main/java/com/eureka/persons/services/PersonService.java
@@ -0,0 +1,16 @@
+package com.eureka.persons.services;
+
+import com.eureka.persons.person.Person;
+
+import java.util.List;
+import java.util.Optional;
+
+public interface PersonService {
+ List findAll();
+
+ Optional findById(Long id);
+
+ Person save(Person person);
+
+ void delete(Person person);
+}
\ No newline at end of file
diff --git a/eureka/persons-server/src/main/java/com/eureka/persons/services/PersonServiceImpl.java b/eureka/persons-server/src/main/java/com/eureka/persons/services/PersonServiceImpl.java
new file mode 100644
index 0000000..f1c2fec
--- /dev/null
+++ b/eureka/persons-server/src/main/java/com/eureka/persons/services/PersonServiceImpl.java
@@ -0,0 +1,42 @@
+package com.eureka.persons.services;
+
+import com.eureka.persons.PersonRepo;
+import com.eureka.persons.person.Person;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+import java.util.Optional;
+
+@Service
+@Transactional
+public class PersonServiceImpl implements PersonService {
+ private PersonRepo personRepo;
+
+ public PersonServiceImpl(PersonRepo personRepo) {
+ this.personRepo = personRepo;
+ }
+
+ @Override
+ public List findAll() {
+ return personRepo.findAll();
+ }
+
+ @Override
+ public Optional findById(Long id) {
+ return personRepo.findById(id);
+ }
+
+
+ @Override
+ public Person save(Person person) {
+ personRepo.save(person);
+ return person;
+ }
+
+ @Override
+ public void delete(Person person) {
+ personRepo.delete(person);
+ }
+}
+
diff --git a/eureka/persons-server/src/main/java/com/eureka/persons/util/DateProcessor.java b/eureka/persons-server/src/main/java/com/eureka/persons/util/DateProcessor.java
new file mode 100644
index 0000000..0d2f624
--- /dev/null
+++ b/eureka/persons-server/src/main/java/com/eureka/persons/util/DateProcessor.java
@@ -0,0 +1,17 @@
+package com.eureka.persons.util;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+
+public class DateProcessor {
+ public static final String DATE_FORMAT= "yyyy-MM-dd HH:mm";
+ private static DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_FORMAT);
+
+ public static LocalDateTime toDate(final String date) {
+ return LocalDateTime.parse(date, formatter);
+ }
+
+ public static String toString(final LocalDateTime date){
+ return date.format(formatter);
+ }
+}
diff --git a/eureka/persons-server/src/main/java/com/eureka/persons/util/NumberGenerator.java b/eureka/persons-server/src/main/java/com/eureka/persons/util/NumberGenerator.java
new file mode 100644
index 0000000..92b1c40
--- /dev/null
+++ b/eureka/persons-server/src/main/java/com/eureka/persons/util/NumberGenerator.java
@@ -0,0 +1,18 @@
+package com.eureka.persons.util;
+
+import java.util.Random;
+
+public final class NumberGenerator {
+ private static final Random RAND = new Random();
+ private static final String UPPER = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ private static final String DIGITS = "0123456789";
+
+ private static Character randomCharacter() {
+ final var all = UPPER.concat(UPPER.toLowerCase()).concat(DIGITS);
+ return all.charAt(RAND.nextInt(all.length() - 1));
+ }
+
+ private NumberGenerator() {
+ // prevent initialization fo this class
+ }
+}
diff --git a/eureka/persons-server/src/main/resources/banner.txt b/eureka/persons-server/src/main/resources/banner.txt
new file mode 100644
index 0000000..be21922
--- /dev/null
+++ b/eureka/persons-server/src/main/resources/banner.txt
@@ -0,0 +1,7 @@
+__________ _________ .__
+\______ \ ___________ __________ ____ ______ / _____/ ______________ _|__| ____ ____
+ | ___// __ \_ __ \/ ___/ _ \ / \ / ___/ \_____ \_/ __ \_ __ \ \/ / |/ ___\/ __ \
+ | | \ ___/| | \/\___ ( <_> ) | \\___ \ / \ ___/| | \/\ /| \ \__\ ___/
+ |____| \___ >__| /____ >____/|___| /____ > /_______ /\___ >__| \_/ |__|\___ >___ >
+ \/ \/ \/ \/ \/ \/ \/ \/
+ :: Spring Boot :: (v2.2.4.RELEASE)
diff --git a/eureka/persons-server/src/main/resources/persons-server.yml b/eureka/persons-server/src/main/resources/persons-server.yml
new file mode 100644
index 0000000..2740f01
--- /dev/null
+++ b/eureka/persons-server/src/main/resources/persons-server.yml
@@ -0,0 +1,47 @@
+spring:
+ application:
+ name: persons-service # Service registers under this name
+ datasource:
+ driver-class-name: org.h2.Driver
+ jdbc-url: jdbc:h2:mem:personsdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
+ username: sa
+ password: password
+ maximum-pool-size: 5
+ connection-test-query: "SELECT 1"
+ pool-name: cemsPool
+ connection-timeout: 60000
+ jpa:
+ generate-ddl: true
+ hibernate:
+ ddl-auto: create-drop
+ database-platform: org.hibernate.dialect.H2Dialect
+ h2:
+ console:
+ enabled: true
+# HTTP Server
+server:
+ port: 4001 # HTTP (Tomcat) port
+ address: 0.0.0.0
+
+# Discovery Server Access
+#TODO here you add configurations for eureka client
+
+info:
+ app:
+ name: persons-server
+ description: Spring Cloud Application Managing Person Instances
+ version: 1.0-SNAPSHOT
+
+logging:
+ pattern:
+ console: "%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"
+ level:
+ root: INFO
+ org.springframework: DEBUG
+ com.apress.cems: DEBUG
+
+
+eureka:
+ client:
+ serviceUrl:
+ defaultZone: http://localhost:3000/eureka/
\ No newline at end of file
diff --git a/eureka/persons-server/src/test/java/com/example/personsserver/PersonsServerApplicationTests.java b/eureka/persons-server/src/test/java/com/example/personsserver/PersonsServerApplicationTests.java
new file mode 100644
index 0000000..2fd298e
--- /dev/null
+++ b/eureka/persons-server/src/test/java/com/example/personsserver/PersonsServerApplicationTests.java
@@ -0,0 +1,17 @@
+package com.example.personsserver;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class PersonsServerApplicationTests {
+
+ //TODO configure discovery-server to be the Eureka's server (on port 3000) and persons-server to be the client server (on port 4001)
+ // hint1: you need to add some configurations in resources -> .yml files
+ // After you start your server and your client you need to create the endpoints from PersonsController, you have more details there
+ // Use postman to test the endpoints. Create a new collection and add all 5 endpoints inside of it.
+ @Test
+ void contextLoads() {
+ }
+
+}
diff --git a/eureka/pom.xml b/eureka/pom.xml
new file mode 100644
index 0000000..1049986
--- /dev/null
+++ b/eureka/pom.xml
@@ -0,0 +1,66 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.6.4
+
+
+ com.example
+ eureka
+ 0.0.1-SNAPSHOT
+ eureka
+ eureka
+ pom
+
+ 11
+ 2021.0.1
+
+
+ discovery-server
+ persons-server
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.cloud
+ spring-cloud-starter-netflix-eureka-client
+
+
+ org.springframework.cloud
+ spring-cloud-starter-netflix-eureka-server
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/eureka/src/main/java/com/example/eureka/EurekaApplication.java b/eureka/src/main/java/com/example/eureka/EurekaApplication.java
new file mode 100644
index 0000000..20c67a9
--- /dev/null
+++ b/eureka/src/main/java/com/example/eureka/EurekaApplication.java
@@ -0,0 +1,13 @@
+package com.example.eureka;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class EurekaApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(EurekaApplication.class, args);
+ }
+
+}
diff --git a/eureka/src/main/resources/application.properties b/eureka/src/main/resources/application.properties
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/eureka/src/main/resources/application.properties
@@ -0,0 +1 @@
+
diff --git a/eureka/src/test/java/com/example/eureka/EurekaApplicationTests.java b/eureka/src/test/java/com/example/eureka/EurekaApplicationTests.java
new file mode 100644
index 0000000..1415105
--- /dev/null
+++ b/eureka/src/test/java/com/example/eureka/EurekaApplicationTests.java
@@ -0,0 +1,13 @@
+package com.example.eureka;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class EurekaApplicationTests {
+
+ @Test
+ void contextLoads() {
+ }
+
+}
diff --git a/java8/src/main/java/com/unitbv/datasource/UserDataSource.java b/java8/src/main/java/com/unitbv/datasource/UserDataSource.java
index 94d8095..134f03c 100644
--- a/java8/src/main/java/com/unitbv/datasource/UserDataSource.java
+++ b/java8/src/main/java/com/unitbv/datasource/UserDataSource.java
@@ -3,6 +3,7 @@
import com.unitbv.model.User;
import java.util.*;
+import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -11,7 +12,7 @@ public class UserDataSource {
private List users = new ArrayList<>();
- public UserDataSource(){
+ public UserDataSource() {
users.add(new User(1, "John", "Wick", 35, "actor"));
users.add(new User(2, "Jayce", "Lucas", 35, "driver"));
users.add(new User(3, "Jack", "Spades", 18, "gamer"));
@@ -21,20 +22,20 @@ public UserDataSource(){
users.add(new User(7, "Mark", "John", 17, "student"));
}
- public UserDataSource(List users){
+ public UserDataSource(List users) {
this.users = users;
}
- public List getAll(){
+ public List getAll() {
return users;
}
- public Optional findById(int id){
+ public Optional findById(int id) {
Optional user = users.stream().filter(u -> u.getId() == id).findFirst();
return user;
}
- public String getUsersNamesWithAgeGreaterThanThirty(){
+ public String getUsersNamesWithAgeGreaterThanThirty() {
String text = users.stream()
.filter(u -> u.getAge() > 30)
.map(User::getFirstName)
@@ -42,27 +43,27 @@ public String getUsersNamesWithAgeGreaterThanThirty(){
return text;
}
- public int sumUpUserAgesWhereFirstNameStartsWithJ(){
+ public int sumUpUserAgesWhereFirstNameStartsWithJ() {
return users.stream()
.filter(u -> u.getFirstName().startsWith("J"))
.mapToInt(User::getAge)
.reduce(0, Integer::sum);
}
- public User getUserWithHighestAge(){
+ public User getUserWithHighestAge() {
return users.stream()
.sorted((u1, u2) -> Integer.compare(u2.getAge(), u1.getAge()))
.findFirst()
.orElse(new User());
}
- public User getUserWithHighestAge_V2(){
+ public User getUserWithHighestAge_V2() {
return users.stream()
.max(Comparator.comparingInt(User::getAge))
.orElse(new User());
}
- public List mergeUserLists(List l1, List l2){
+ public List mergeUserLists(List l1, List l2) {
return Stream.of(l1, l2)
.flatMap(Collection::stream)
.collect(Collectors.toList());
@@ -71,78 +72,89 @@ public List mergeUserLists(List l1, List l2){
// <---------- TO DO ---------->
// Get the full names for all users
- public List getFullNames(){
+ public List getFullNames() {
// your code here
- return new ArrayList<>();
+ return users.stream().map(u -> u.getFirstName() + " " + u.getLastName()).collect(Collectors.toList());
}
// Get the job of the oldest user
- public String getJobOfTheOldestUser(){
+ public String getJobOfTheOldestUser() {
// your code here
- return "";
+ return users.stream().max(Comparator.comparingInt(User::getAge)).get().getJob();
}
// Get user (distinct) jobs sorted alphabetically
- public Set getAllUserJobsSorted(){
+ public Set getAllUserJobsSorted() {
// your code here
- return new HashSet<>();
+ return users.stream().map(User::getJob).collect(Collectors.toSet());
}
// Find user by first name - throw RuntimeException if not found
- public User findByFirstName(String firstName){
+ public User findByFirstName(String firstName) {
// your code here
- return new User();
+ return users.stream().filter(user -> user.getFirstName().equals(firstName)).findFirst().orElseThrow(RuntimeException::new);
}
// Check if all users are older than the specified age
- public boolean areAllUsersOlderThan(int age){
+ public boolean areAllUsersOlderThan(int age) {
// your code here - please try with allMatch/noneMatch
- return false;
+ return users.stream().allMatch(user -> user.getAge() > age);
}
// Add a new user - if there is a user with the same id, don't add and throw a RuntimeException
- public void addUser(User user){
+ public void addUser(User user) {
// your code here - HINT: use ifPresent() method from Optional
+ users.stream().filter(user1 -> user1.getId() == user.getId()).findFirst().ifPresentOrElse(
+ user1 -> {
+ throw new RuntimeException();
+ },
+ () -> users.add(user)
+ );
+
}
// For all students (user.job = "student"), change the job to "graduate" and add 5 years to their age
- public void changeAllStudentsJobsAndAges(){
+ public void changeAllStudentsJobsAndAges() {
// your code here
+ users.stream().filter(user -> user.getJob().equals("student")).forEach(user -> {
+ user.setAge(user.getAge() + 5);
+ user.setJob("graduate");
+ });
}
// Count users that have the given Job
- public long countUsersHavingTheSpecifiedJob(String job){
+ public long countUsersHavingTheSpecifiedJob(String job) {
// your code here
- return 0;
+ return users.stream().filter(user -> user.getJob().equals(job)).count();
}
// Get a map where the key is the user id and the value is the User object itself
- public Map getMapOfUsers(){
+ public Map getMapOfUsers() {
// your code here
- return new HashMap<>();
+ return users.stream().collect(Collectors.toMap(User::getId, Function.identity()));
}
// Get a predicate for filtering by the given name - applies to both firstName and lastName
- public Predicate getPredicateForFilteringByName(String name){
+ public Predicate getPredicateForFilteringByName(String name) {
// your code here
- return null;
+ return p -> p.getFirstName().equals(name) || p.getLastName().equals(name);
}
// Get a comparator for User type - compare by age ascending, then by job alphabetically
- public Comparator getUserComparator(){
+ public Comparator getUserComparator() {
// your code here
- return null;
+ return Comparator.comparingInt(User::getAge).thenComparing(User::getJob);
}
// Filter users using the given Predicate
- public List filterUsers(Predicate super User> predicate){
+ public List filterUsers(Predicate super User> predicate) {
return users.stream()
.filter(predicate)
.collect(Collectors.toList());
}
// Sort users using the given Comparator
- public List sortUsers(Comparator super User> comparator){
+ public List sortUsers(Comparator super User> comparator) {
return users.stream()
.sorted(comparator)
.collect(Collectors.toList());
diff --git a/java8/src/main/java/com/unitbv/util/DateTimeUtils.java b/java8/src/main/java/com/unitbv/util/DateTimeUtils.java
index f0134c9..9eeb856 100644
--- a/java8/src/main/java/com/unitbv/util/DateTimeUtils.java
+++ b/java8/src/main/java/com/unitbv/util/DateTimeUtils.java
@@ -2,18 +2,20 @@
import java.time.LocalDate;
import java.time.Month;
+import java.time.temporal.ChronoField;
+import java.time.temporal.ChronoUnit;
public class DateTimeUtils {
// Get the number of years until the given date
- public static int getNumberOfYearsUntil(LocalDate date){
+ public static int getNumberOfYearsUntil(LocalDate date) {
// your code here
- return 0;
+ return (int) ChronoUnit.YEARS.between(LocalDate.now(), date);
}
// Check if the given date occurs on Friday the 13th
- public static boolean isDateOccurringOnFriday13th(LocalDate date){
+ public static boolean isDateOccurringOnFriday13th(LocalDate date) {
// your code here - HINT: use ChronoField enum constants for day of month and day of week
- return false;
+ return date.get(ChronoField.DAY_OF_WEEK) == 5 && date.get(ChronoField.DAY_OF_MONTH) == 13;
}
}
diff --git a/lab6-gateway/.gitignore b/lab6-gateway/.gitignore
new file mode 100644
index 0000000..549e00a
--- /dev/null
+++ b/lab6-gateway/.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/lab6-gateway/api-gateway-project/.gitignore b/lab6-gateway/api-gateway-project/.gitignore
new file mode 100644
index 0000000..549e00a
--- /dev/null
+++ b/lab6-gateway/api-gateway-project/.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/lab6-gateway/api-gateway-project/pom.xml b/lab6-gateway/api-gateway-project/pom.xml
new file mode 100644
index 0000000..82291ce
--- /dev/null
+++ b/lab6-gateway/api-gateway-project/pom.xml
@@ -0,0 +1,77 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.6.5
+
+
+ com.example
+ api-gateway-project
+ 0.0.1-SNAPSHOT
+ api-gateway-project
+ api-gateway-project
+
+ 11
+ 2021.0.1
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+ org.springframework.boot
+ spring-boot-starter-webflux
+
+
+ org.springframework.cloud
+ spring-cloud-starter-gateway
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ io.projectreactor
+ reactor-test
+ test
+
+
+ org.springframework.cloud
+ spring-cloud-netflix-eureka-server
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ test
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/lab6-gateway/api-gateway-project/src/main/java/com/example/apigatewayproject/ApiGatewayProjectApplication.java b/lab6-gateway/api-gateway-project/src/main/java/com/example/apigatewayproject/ApiGatewayProjectApplication.java
new file mode 100644
index 0000000..708791f
--- /dev/null
+++ b/lab6-gateway/api-gateway-project/src/main/java/com/example/apigatewayproject/ApiGatewayProjectApplication.java
@@ -0,0 +1,16 @@
+package com.example.apigatewayproject;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
+import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
+
+@SpringBootApplication
+@EnableEurekaClient
+public class ApiGatewayProjectApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(ApiGatewayProjectApplication.class, args);
+ }
+
+}
diff --git a/lab6-gateway/api-gateway-project/src/main/resources/application.yml b/lab6-gateway/api-gateway-project/src/main/resources/application.yml
new file mode 100644
index 0000000..ec9318c
--- /dev/null
+++ b/lab6-gateway/api-gateway-project/src/main/resources/application.yml
@@ -0,0 +1,30 @@
+server:
+ port: 8080
+ address: 0.0.0.0
+eureka:
+ client:
+ serviceUrl:
+ defaultZone: http://localhost:3000/eureka/
+ register-with-eureka: true
+ fetch-registry: true
+spring:
+ application:
+ name: gateway
+ main:
+ web-application-type: reactive
+ cloud:
+ gateway:
+ routes:
+ - id: service1
+ uri: http://localhost:8081
+ predicates:
+ - Path=/api/greeting/**
+ - id: service2
+ uri: http://localhost:8082
+ predicates:
+ - Path=/product/**
+
+#TODO use eureka to discover the URL for the service1 and service2
+#TODO configure spring cloud gateway to route the request to downstream services (service1 and service2) based on the paths(/api/greeting, /product)
+#TODO for greeting endpoint add a route to accept requests to /greeting but before calling service1 it must append api before the greeting path (HINT: rewrite path filter)
+#and method types (GET,POST)
\ No newline at end of file
diff --git a/lab6-gateway/api-gateway-project/src/test/java/com/example/apigatewayproject/ApiGatewayProjectApplicationTests.java b/lab6-gateway/api-gateway-project/src/test/java/com/example/apigatewayproject/ApiGatewayProjectApplicationTests.java
new file mode 100644
index 0000000..6c58423
--- /dev/null
+++ b/lab6-gateway/api-gateway-project/src/test/java/com/example/apigatewayproject/ApiGatewayProjectApplicationTests.java
@@ -0,0 +1,13 @@
+package com.example.apigatewayproject;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class ApiGatewayProjectApplicationTests {
+
+ @Test
+ void contextLoads() {
+ }
+
+}
diff --git a/lab6-gateway/pom.xml b/lab6-gateway/pom.xml
new file mode 100644
index 0000000..aa491ab
--- /dev/null
+++ b/lab6-gateway/pom.xml
@@ -0,0 +1,47 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.6.5
+
+
+ com.example
+ lab-6-api-gateway
+ 0.0.1-SNAPSHOT
+ lab-6-api-gateway
+ lab-6-api-gateway
+
+ 11
+
+ pom
+
+ api-gateway-project
+ service1
+ service2
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/lab6-gateway/service1/.gitignore b/lab6-gateway/service1/.gitignore
new file mode 100644
index 0000000..549e00a
--- /dev/null
+++ b/lab6-gateway/service1/.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/lab6-gateway/service1/pom.xml b/lab6-gateway/service1/pom.xml
new file mode 100644
index 0000000..500ef19
--- /dev/null
+++ b/lab6-gateway/service1/pom.xml
@@ -0,0 +1,65 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.6.5
+
+
+ com.example
+ service1
+ 0.0.1-SNAPSHOT
+ service1
+ service1
+
+ 11
+ 2021.0.1
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-netflix-eureka-client
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.springframework.cloud
+ spring-cloud-netflix-eureka-client
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/lab6-gateway/service1/src/main/java/com/example/service1/Controller.java b/lab6-gateway/service1/src/main/java/com/example/service1/Controller.java
new file mode 100644
index 0000000..a297e15
--- /dev/null
+++ b/lab6-gateway/service1/src/main/java/com/example/service1/Controller.java
@@ -0,0 +1,17 @@
+package com.example.service1;
+
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/api")
+public class Controller {
+
+ @GetMapping("/greeting/{name}")
+ public String greeting(@PathVariable String name) {
+ System.out.println(name);
+ return "Hello "+name;
+ }
+}
diff --git a/lab6-gateway/service1/src/main/java/com/example/service1/Service1Application.java b/lab6-gateway/service1/src/main/java/com/example/service1/Service1Application.java
new file mode 100644
index 0000000..50112c0
--- /dev/null
+++ b/lab6-gateway/service1/src/main/java/com/example/service1/Service1Application.java
@@ -0,0 +1,24 @@
+package com.example.service1;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
+
+@SpringBootApplication
+@EnableEurekaClient
+public class Service1Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Service1Application.class, args);
+ }
+
+
+
+ // TODO
+ // 1. define a GET endpoint /api/greeting which should accept a query parameter "name"
+ // 2. return should be a string returning a greeting: Hello Brasov
+ // 3. print request headers
+ // 4. register the service in eureka
+
+
+}
diff --git a/lab6-gateway/service1/src/main/java/com/example/service1/Service1Controller.java b/lab6-gateway/service1/src/main/java/com/example/service1/Service1Controller.java
new file mode 100644
index 0000000..196c64a
--- /dev/null
+++ b/lab6-gateway/service1/src/main/java/com/example/service1/Service1Controller.java
@@ -0,0 +1,20 @@
+package com.example.service1;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.Console;
+import java.util.Map;
+
+@RestController
+@RequestMapping("/api")
+public class Service1Controller {
+
+ @ResponseStatus(HttpStatus.OK)
+ @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
+ public String list(@RequestHeader Map headers) {
+ System.out.println("Headers {" + headers + "}");
+ return "Hello Brasov";
+ }
+}
diff --git a/lab6-gateway/service1/src/main/resources/application.yml b/lab6-gateway/service1/src/main/resources/application.yml
new file mode 100644
index 0000000..c96fc6d
--- /dev/null
+++ b/lab6-gateway/service1/src/main/resources/application.yml
@@ -0,0 +1,15 @@
+server:
+ port: 8081
+ address: 0.0.0.0
+
+spring:
+ application:
+ name: service1
+
+eureka:
+ client:
+ serviceUrl:
+ defaultZone: http://localhost:3000/eureka/
+ register-with-eureka: true
+ fetch-registry: true
+
diff --git a/lab6-gateway/service1/src/test/java/com/example/service1/Service1ApplicationTests.java b/lab6-gateway/service1/src/test/java/com/example/service1/Service1ApplicationTests.java
new file mode 100644
index 0000000..539fcde
--- /dev/null
+++ b/lab6-gateway/service1/src/test/java/com/example/service1/Service1ApplicationTests.java
@@ -0,0 +1,13 @@
+package com.example.service1;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class Service1ApplicationTests {
+
+ @Test
+ void contextLoads() {
+ }
+
+}
diff --git a/lab6-gateway/service2/.gitignore b/lab6-gateway/service2/.gitignore
new file mode 100644
index 0000000..549e00a
--- /dev/null
+++ b/lab6-gateway/service2/.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/lab6-gateway/service2/pom.xml b/lab6-gateway/service2/pom.xml
new file mode 100644
index 0000000..a3e7960
--- /dev/null
+++ b/lab6-gateway/service2/pom.xml
@@ -0,0 +1,77 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.6.5
+
+
+ com.example
+ service2
+ 0.0.1-SNAPSHOT
+ service2
+ service2
+
+ 11
+ 2021.0.1
+
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.cloud
+ spring-cloud-starter-netflix-eureka-client
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.springframework.cloud
+ spring-cloud-netflix-eureka-client
+
+
+ org.hibernate
+ hibernate-core
+
+
+ org.projectlombok
+ lombok
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/lab6-gateway/service2/src/main/java/com/example/service2/Controller.java b/lab6-gateway/service2/src/main/java/com/example/service2/Controller.java
new file mode 100644
index 0000000..c45aa76
--- /dev/null
+++ b/lab6-gateway/service2/src/main/java/com/example/service2/Controller.java
@@ -0,0 +1,28 @@
+package com.example.service2;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.validation.BindingResult;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RestController
+@RequestMapping("/product")
+public class Controller {
+
+ private List products = new ArrayList();
+
+ @ResponseStatus(HttpStatus.CREATED)
+ @PostMapping()
+ public void greeting(@RequestBody Product product, BindingResult result) {
+ if(result.hasErrors())
+ throw new RuntimeException("Product Exception");
+ products.add(product);
+ }
+
+ @GetMapping()
+ public List greeting() {
+ return products;
+ }
+}
\ No newline at end of file
diff --git a/lab6-gateway/service2/src/main/java/com/example/service2/Product.java b/lab6-gateway/service2/src/main/java/com/example/service2/Product.java
new file mode 100644
index 0000000..a7436a4
--- /dev/null
+++ b/lab6-gateway/service2/src/main/java/com/example/service2/Product.java
@@ -0,0 +1,24 @@
+package com.example.service2;
+
+import com.sun.istack.NotNull;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+
+@Entity
+@Getter
+@Setter
+@NoArgsConstructor
+public class Product {
+
+ @NotNull
+ @Column(nullable = false, unique = true)
+ private String name;
+
+ @NotNull
+ @Column(nullable = false, unique = true)
+ private int quantity;
+}
diff --git a/lab6-gateway/service2/src/main/java/com/example/service2/Service2Application.java b/lab6-gateway/service2/src/main/java/com/example/service2/Service2Application.java
new file mode 100644
index 0000000..383d462
--- /dev/null
+++ b/lab6-gateway/service2/src/main/java/com/example/service2/Service2Application.java
@@ -0,0 +1,21 @@
+package com.example.service2;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
+
+@SpringBootApplication
+@EnableEurekaClient
+public class Service2Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Service2Application.class, args);
+ }
+ // TODO
+ // 1. define a POST endpoint /product which should accept a request body containing two properties -product name and quantity
+ //2. save the request body in memory
+ // 3. return 200 if OK
+ // 4. print request headers
+ // 5. register the service in eureka
+ // 6. define a GET endpoint /product to return the saved data using the POST endpoint - return type is List
+}
diff --git a/lab6-gateway/service2/src/main/java/com/example/service2/Service2Controller.java b/lab6-gateway/service2/src/main/java/com/example/service2/Service2Controller.java
new file mode 100644
index 0000000..388a131
--- /dev/null
+++ b/lab6-gateway/service2/src/main/java/com/example/service2/Service2Controller.java
@@ -0,0 +1,29 @@
+package com.example.service2;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+@RestController
+public class Service2Controller {
+
+ private static ArrayList products = new ArrayList<>();
+
+ @ResponseStatus(HttpStatus.OK)
+ @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
+ public List getList() {
+ return products;
+ }
+
+ @ResponseStatus(HttpStatus.OK)
+ @PostMapping(produces = MediaType.APPLICATION_JSON_VALUE)
+ public String list(@RequestHeader Map headers, @RequestBody Product product) {
+ products.add(product);
+ System.out.println("Headers {" + headers + "}");
+ return "Hello Brasov";
+ }
+}
diff --git a/lab6-gateway/service2/src/main/java/com/example/service2/base/AbstractEntity.java b/lab6-gateway/service2/src/main/java/com/example/service2/base/AbstractEntity.java
new file mode 100644
index 0000000..12c37f7
--- /dev/null
+++ b/lab6-gateway/service2/src/main/java/com/example/service2/base/AbstractEntity.java
@@ -0,0 +1,70 @@
+package com.example.service2.base;
+
+import com.example.service2.util.DateProcessor;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import javax.persistence.*;
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import java.util.Comparator;
+import java.util.Objects;
+
+@MappedSuperclass
+@Getter
+@Setter
+public abstract class AbstractEntity implements Serializable {
+
+ public static Comparator COMPARATOR_BY_ID = Comparator.comparing(AbstractEntity::getId);
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ @Column(updatable = false)
+ protected Long id;
+
+ @Version
+ protected int version;
+
+ @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = DateProcessor.DATE_FORMAT)
+ @Column(name = "created_at", nullable = false)
+ @DateTimeFormat(pattern = DateProcessor.DATE_FORMAT)
+ protected LocalDateTime createdAt;
+
+
+ @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = DateProcessor.DATE_FORMAT)
+ @Column(name = "modified_at", nullable = false)
+ @DateTimeFormat(pattern = DateProcessor.DATE_FORMAT)
+ protected LocalDateTime modifiedAt;
+
+ /**
+ * This constructor is required by JPA. All subclasses of this class will inherit this constructor.
+ */
+ protected AbstractEntity() {
+ createdAt = LocalDateTime.now();
+ modifiedAt = LocalDateTime.now();
+ }
+
+ // IDE generated methods
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ var that = (AbstractEntity) o;
+ if (!Objects.equals(id, that.id)) return false;
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return id != null ? id.hashCode() : 0;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("AbstractEntity[id='%d%n', createdAt='%s', modifiedAt='%s', version='%d%n']",
+ id, DateProcessor.toString(createdAt), DateProcessor.toString(modifiedAt), version);
+ }
+}
diff --git a/lab6-gateway/service2/src/main/java/com/example/service2/util/DateProcessor.java b/lab6-gateway/service2/src/main/java/com/example/service2/util/DateProcessor.java
new file mode 100644
index 0000000..259d9c5
--- /dev/null
+++ b/lab6-gateway/service2/src/main/java/com/example/service2/util/DateProcessor.java
@@ -0,0 +1,17 @@
+package com.example.service2.util;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+
+public class DateProcessor {
+ public static final String DATE_FORMAT= "yyyy-MM-dd HH:mm";
+ private static DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_FORMAT);
+
+ public static LocalDateTime toDate(final String date) {
+ return LocalDateTime.parse(date, formatter);
+ }
+
+ public static String toString(final LocalDateTime date){
+ return date.format(formatter);
+ }
+}
diff --git a/lab6-gateway/service2/src/main/resources/application.yml b/lab6-gateway/service2/src/main/resources/application.yml
new file mode 100644
index 0000000..6e5b917
--- /dev/null
+++ b/lab6-gateway/service2/src/main/resources/application.yml
@@ -0,0 +1,14 @@
+server:
+ port: 8082
+ address: 0.0.0.0
+
+spring:
+ application:
+ name: service2
+
+eureka:
+ client:
+ serviceUrl:
+ defaultZone: http://localhost:3000/eureka/
+ register-with-eureka: true
+ fetch-registry: true
\ No newline at end of file
diff --git a/lab6-gateway/service2/src/test/java/com/example/service2/Service2ApplicationTests.java b/lab6-gateway/service2/src/test/java/com/example/service2/Service2ApplicationTests.java
new file mode 100644
index 0000000..3da138b
--- /dev/null
+++ b/lab6-gateway/service2/src/test/java/com/example/service2/Service2ApplicationTests.java
@@ -0,0 +1,13 @@
+package com.example.service2;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class Service2ApplicationTests {
+
+ @Test
+ void contextLoads() {
+ }
+
+}
diff --git a/lab6-gateway/src/main/java/com/example/lab6apigateway/Lab6ApiGatewayApplication.java b/lab6-gateway/src/main/java/com/example/lab6apigateway/Lab6ApiGatewayApplication.java
new file mode 100644
index 0000000..eb83cff
--- /dev/null
+++ b/lab6-gateway/src/main/java/com/example/lab6apigateway/Lab6ApiGatewayApplication.java
@@ -0,0 +1,13 @@
+package com.example.lab6apigateway;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Lab6ApiGatewayApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Lab6ApiGatewayApplication.class, args);
+ }
+
+}
diff --git a/lab6-gateway/src/main/resources/application.properties b/lab6-gateway/src/main/resources/application.properties
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/lab6-gateway/src/main/resources/application.properties
@@ -0,0 +1 @@
+
diff --git a/lab6-gateway/src/test/java/com/example/lab6apigateway/Lab6ApiGatewayApplicationTests.java b/lab6-gateway/src/test/java/com/example/lab6apigateway/Lab6ApiGatewayApplicationTests.java
new file mode 100644
index 0000000..af4ce01
--- /dev/null
+++ b/lab6-gateway/src/test/java/com/example/lab6apigateway/Lab6ApiGatewayApplicationTests.java
@@ -0,0 +1,13 @@
+package com.example.lab6apigateway;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class Lab6ApiGatewayApplicationTests {
+
+ @Test
+ void contextLoads() {
+ }
+
+}
diff --git a/pom.xml b/pom.xml
index 487bfbd..4500e55 100644
--- a/pom.xml
+++ b/pom.xml
@@ -21,9 +21,17 @@
java8rest-service
+ spring1
+ spring2
+ eureka
+
+ org.springframework
+ spring-context
+ 5.3.15
+ org.junit.jupiterjunit-jupiter-engine
diff --git a/recipe-rest-service/.gitignore b/recipe-rest-service/.gitignore
new file mode 100644
index 0000000..549e00a
--- /dev/null
+++ b/recipe-rest-service/.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/recipe-rest-service/.mvn/wrapper/maven-wrapper.jar b/recipe-rest-service/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..c1dd12f
Binary files /dev/null and b/recipe-rest-service/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/recipe-rest-service/.mvn/wrapper/maven-wrapper.properties b/recipe-rest-service/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..b7cb93e
--- /dev/null
+++ b/recipe-rest-service/.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/recipe-rest-service/mvnw b/recipe-rest-service/mvnw
new file mode 100644
index 0000000..8a8fb22
--- /dev/null
+++ b/recipe-rest-service/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/recipe-rest-service/mvnw.cmd b/recipe-rest-service/mvnw.cmd
new file mode 100644
index 0000000..1d8ab01
--- /dev/null
+++ b/recipe-rest-service/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/recipe-rest-service/pom.xml b/recipe-rest-service/pom.xml
new file mode 100644
index 0000000..99ffaaf
--- /dev/null
+++ b/recipe-rest-service/pom.xml
@@ -0,0 +1,48 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.6.4
+
+
+ com.example
+ recipes
+ 0.0.1-SNAPSHOT
+ recipes
+ Demo project for Spring Boot
+
+ 17
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+ org.projectlombok
+ lombok
+ 1.18.22
+ provided
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/recipe-rest-service/src/main/java/com/example/recipes/RecipesApplication.java b/recipe-rest-service/src/main/java/com/example/recipes/RecipesApplication.java
new file mode 100644
index 0000000..fd1b96c
--- /dev/null
+++ b/recipe-rest-service/src/main/java/com/example/recipes/RecipesApplication.java
@@ -0,0 +1,13 @@
+package com.example.recipes;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class RecipesApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(RecipesApplication.class, args);
+ }
+
+}
diff --git a/recipe-rest-service/src/main/java/com/example/recipes/config/AppConfig.java b/recipe-rest-service/src/main/java/com/example/recipes/config/AppConfig.java
new file mode 100644
index 0000000..e6da9a4
--- /dev/null
+++ b/recipe-rest-service/src/main/java/com/example/recipes/config/AppConfig.java
@@ -0,0 +1,14 @@
+package com.example.recipes.config;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class AppConfig {
+ @Bean
+ public ObjectMapper objectMapper() {
+ return new ObjectMapper();
+ }
+
+}
diff --git a/recipe-rest-service/src/main/java/com/example/recipes/controller/RecipeController.java b/recipe-rest-service/src/main/java/com/example/recipes/controller/RecipeController.java
new file mode 100644
index 0000000..cb1bb0f
--- /dev/null
+++ b/recipe-rest-service/src/main/java/com/example/recipes/controller/RecipeController.java
@@ -0,0 +1,42 @@
+package com.example.recipes.controller;
+
+import com.example.recipes.model.Recipe;
+import com.example.recipes.service.RecipeService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/api/recipe")
+public class RecipeController {
+ private final RecipeService recipeService;
+
+ @Autowired
+ public RecipeController(RecipeService recipeService) {
+ this.recipeService = recipeService;
+ }
+
+ @GetMapping()
+ public ResponseEntity> getAllRecipes() {
+ return ResponseEntity.ok(recipeService.getAllRecipes());
+ }
+
+ @PostMapping
+ public ResponseEntity> saveRecipe(@RequestBody Recipe recipe) {
+ try {
+ return ResponseEntity.ok(recipeService.saveRecipe(recipe));
+ } catch (RuntimeException exception) {
+ switch (exception.getMessage()) {
+ case "Recipe name can not be null!", "Ingredient name can not be null!" -> {
+ return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(exception.getMessage());
+ }
+ default -> {
+ return ResponseEntity.status(HttpStatus.CONFLICT).body(exception.getMessage());
+ }
+ }
+ }
+ }
+}
diff --git a/recipe-rest-service/src/main/java/com/example/recipes/datasource/MyRecipe.java b/recipe-rest-service/src/main/java/com/example/recipes/datasource/MyRecipe.java
new file mode 100644
index 0000000..ec96b72
--- /dev/null
+++ b/recipe-rest-service/src/main/java/com/example/recipes/datasource/MyRecipe.java
@@ -0,0 +1,59 @@
+package com.example.recipes.datasource;
+
+import com.example.recipes.model.Ingredient;
+import com.example.recipes.model.Recipe;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+@Component
+public class MyRecipe {
+ private List recipes;
+
+ public MyRecipe() {
+ recipes = new ArrayList<>();
+// recipes = Stream.of(
+// new Recipe("Classic omelette", new ArrayList(Arrays.asList(
+// new Ingredient("Milk", 500, "ml"),
+// new Ingredient("Eggs", 5, "pieces"),
+// new Ingredient("Sugar", 200, "g")))),
+// new Recipe("cake2", new ArrayList(Arrays.asList(
+// new Ingredient("Milk2", 500, "ml"),
+// new Ingredient("Eggs2", 5, "pieces"),
+// new Ingredient("Sugar2", 200, "g"))))
+// ).collect(Collectors.toList());
+ }
+
+ public List getAllRecipes() {
+ return recipes;
+ }
+
+ public Optional findRecipeByName(String name) {
+ return recipes.stream().filter(i -> i.getName().equals(name)).findFirst();
+ }
+
+ public Recipe saveRecipe(Recipe recipe) {
+ findRecipeByName(recipe.getName()).ifPresent(i -> {
+ throw new RuntimeException("Recipe with name " + i.getName() + " already exists!");
+ });
+
+ if (recipe.getName() == null || recipe.getName().isEmpty()) {
+ throw new RuntimeException("Recipe name can not be null!");
+ }
+
+ for (Ingredient ingredient : recipe.getIngredients()) {
+ if (ingredient.getName() == null || ingredient.getName().isEmpty()) {
+ throw new RuntimeException("Ingredient name can not be null!");
+ }
+ }
+
+ this.recipes.add(recipe);
+
+ return recipe;
+ }
+}
diff --git a/recipe-rest-service/src/main/java/com/example/recipes/model/Ingredient.java b/recipe-rest-service/src/main/java/com/example/recipes/model/Ingredient.java
new file mode 100644
index 0000000..484a084
--- /dev/null
+++ b/recipe-rest-service/src/main/java/com/example/recipes/model/Ingredient.java
@@ -0,0 +1,16 @@
+package com.example.recipes.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.ToString;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@ToString
+public class Ingredient {
+ private String name;
+ private double quantity;
+ private String unitOfMeasurement;
+}
diff --git a/recipe-rest-service/src/main/java/com/example/recipes/model/Recipe.java b/recipe-rest-service/src/main/java/com/example/recipes/model/Recipe.java
new file mode 100644
index 0000000..4bdc93f
--- /dev/null
+++ b/recipe-rest-service/src/main/java/com/example/recipes/model/Recipe.java
@@ -0,0 +1,17 @@
+package com.example.recipes.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.ToString;
+
+import java.util.List;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@ToString
+public class Recipe {
+ private String name;
+ private List ingredients;
+}
diff --git a/recipe-rest-service/src/main/java/com/example/recipes/service/RecipeService.java b/recipe-rest-service/src/main/java/com/example/recipes/service/RecipeService.java
new file mode 100644
index 0000000..5e0e6dc
--- /dev/null
+++ b/recipe-rest-service/src/main/java/com/example/recipes/service/RecipeService.java
@@ -0,0 +1,11 @@
+package com.example.recipes.service;
+
+import com.example.recipes.model.Recipe;
+
+import java.util.List;
+
+public interface RecipeService {
+ List getAllRecipes();
+
+ Recipe saveRecipe(Recipe recipe);
+}
diff --git a/recipe-rest-service/src/main/java/com/example/recipes/service/RecipeServiceImpl.java b/recipe-rest-service/src/main/java/com/example/recipes/service/RecipeServiceImpl.java
new file mode 100644
index 0000000..12f03ce
--- /dev/null
+++ b/recipe-rest-service/src/main/java/com/example/recipes/service/RecipeServiceImpl.java
@@ -0,0 +1,29 @@
+package com.example.recipes.service;
+
+import com.example.recipes.datasource.MyRecipe;
+import com.example.recipes.model.Recipe;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class RecipeServiceImpl implements RecipeService{
+
+ private final MyRecipe myRecipe;
+
+ @Autowired
+ public RecipeServiceImpl(MyRecipe myRecipe) {
+ this.myRecipe = myRecipe;
+ }
+
+ @Override
+ public List getAllRecipes() {
+ return myRecipe.getAllRecipes();
+ }
+
+ @Override
+ public Recipe saveRecipe(Recipe recipe) {
+ return myRecipe.saveRecipe(recipe);
+ }
+}
diff --git a/recipe-rest-service/src/main/resources/application.properties b/recipe-rest-service/src/main/resources/application.properties
new file mode 100644
index 0000000..4d360de
--- /dev/null
+++ b/recipe-rest-service/src/main/resources/application.properties
@@ -0,0 +1 @@
+server.port=8081
diff --git a/recipe-rest-service/src/test/java/com/example/recipes/RecipesApplicationTests.java b/recipe-rest-service/src/test/java/com/example/recipes/RecipesApplicationTests.java
new file mode 100644
index 0000000..96bdced
--- /dev/null
+++ b/recipe-rest-service/src/test/java/com/example/recipes/RecipesApplicationTests.java
@@ -0,0 +1,13 @@
+package com.example.recipes;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class RecipesApplicationTests {
+
+ @Test
+ void contextLoads() {
+ }
+
+}
diff --git a/rest-service/src/main/java/com/unitbv/config/AppConfig.java b/rest-service/src/main/java/com/unitbv/config/AppConfig.java
index 5f6539e..aad8365 100644
--- a/rest-service/src/main/java/com/unitbv/config/AppConfig.java
+++ b/rest-service/src/main/java/com/unitbv/config/AppConfig.java
@@ -3,6 +3,7 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.web.client.RestTemplate;
@Configuration
public class AppConfig {
@@ -11,4 +12,9 @@ public class AppConfig {
public ObjectMapper objectMapper(){
return new ObjectMapper();
}
+
+ @Bean
+ public RestTemplate restTemplate() {
+ return new RestTemplate();
+ }
}
diff --git a/rest-service/src/main/java/com/unitbv/controller/PantryController.java b/rest-service/src/main/java/com/unitbv/controller/PantryController.java
index 323e656..06049be 100644
--- a/rest-service/src/main/java/com/unitbv/controller/PantryController.java
+++ b/rest-service/src/main/java/com/unitbv/controller/PantryController.java
@@ -3,6 +3,7 @@
import com.unitbv.model.Ingredient;
import com.unitbv.service.PantryService;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@@ -15,12 +16,39 @@ public class PantryController {
private final PantryService pantryService;
@Autowired
- public PantryController(PantryService pantryService){
+ public PantryController(PantryService pantryService) {
this.pantryService = pantryService;
}
@GetMapping
- public ResponseEntity> getAllIngredients(){
+ public ResponseEntity> getAllIngredients() {
return ResponseEntity.ok(pantryService.getAllIngredients());
}
+
+ @PostMapping
+ public ResponseEntity> saveIngredient(@RequestBody Ingredient ingredient) {
+ try {
+ return ResponseEntity.ok(pantryService.saveIngredient(ingredient));
+ } catch (RuntimeException exception) {
+ return ResponseEntity.status(HttpStatus.CONFLICT).body(exception.getMessage());
+ }
+ }
+
+ @PutMapping("/ingredient")
+ public ResponseEntity> updateIngredient(@RequestBody Ingredient ingredient) {
+ try {
+ return ResponseEntity.ok(pantryService.updateIngredient(ingredient));
+ } catch (RuntimeException exception) {
+ return ResponseEntity.status(HttpStatus.NOT_FOUND).body(exception.getMessage());
+ }
+ }
+
+ @DeleteMapping("/ingredient/{ingredientName}")
+ public ResponseEntity> deleteIngredient(@PathVariable String ingredientName) {
+ try {
+ return ResponseEntity.ok(pantryService.deleteIngredient(ingredientName));
+ } catch (RuntimeException exception) {
+ return ResponseEntity.status(HttpStatus.NOT_FOUND).body(exception.getMessage());
+ }
+ }
}
diff --git a/rest-service/src/main/java/com/unitbv/controller/RecipeController.java b/rest-service/src/main/java/com/unitbv/controller/RecipeController.java
new file mode 100644
index 0000000..fb02330
--- /dev/null
+++ b/rest-service/src/main/java/com/unitbv/controller/RecipeController.java
@@ -0,0 +1,36 @@
+package com.unitbv.controller;
+
+import com.unitbv.model.Ingredient;
+import com.unitbv.request.CreateRecipeRequest;
+import com.unitbv.service.RecipeService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/api/recipe")
+public class RecipeController {
+ private final RecipeService recipeService;
+
+ @Autowired
+ public RecipeController(RecipeService recipeService) {
+ this.recipeService = recipeService;
+ }
+
+ @GetMapping("/all")
+ public ResponseEntity> getAllRecipes() {
+ return ResponseEntity.ok(recipeService.getAllRecipes());
+ }
+
+ @PostMapping("/new")
+ public ResponseEntity> saveNewRecipe(@RequestBody CreateRecipeRequest recipe) {
+ try {
+ return ResponseEntity.ok(recipeService.saveRecipe(recipe));
+ } catch (RuntimeException exception) {
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(exception.getMessage());
+ }
+ }
+}
diff --git a/rest-service/src/main/java/com/unitbv/service/PantryService.java b/rest-service/src/main/java/com/unitbv/service/PantryService.java
index af3b315..74f2461 100644
--- a/rest-service/src/main/java/com/unitbv/service/PantryService.java
+++ b/rest-service/src/main/java/com/unitbv/service/PantryService.java
@@ -6,4 +6,12 @@
public interface PantryService {
List getAllIngredients();
+
+ Ingredient saveIngredient(Ingredient ingredient);
+
+ List saveAllIngredients(List ingredientsToAdd);
+
+ Ingredient updateIngredient(Ingredient ingredient);
+
+ boolean deleteIngredient(String name);
}
diff --git a/rest-service/src/main/java/com/unitbv/service/PantryServiceImpl.java b/rest-service/src/main/java/com/unitbv/service/PantryServiceImpl.java
index 8e1ead8..19f1381 100644
--- a/rest-service/src/main/java/com/unitbv/service/PantryServiceImpl.java
+++ b/rest-service/src/main/java/com/unitbv/service/PantryServiceImpl.java
@@ -8,17 +8,37 @@
import java.util.List;
@Service
-public class PantryServiceImpl implements PantryService{
+public class PantryServiceImpl implements PantryService {
private final MyPantry pantry;
@Autowired
- public PantryServiceImpl(MyPantry pantry){
+ public PantryServiceImpl(MyPantry pantry) {
this.pantry = pantry;
}
@Override
- public List getAllIngredients(){
+ public List getAllIngredients() {
return pantry.getAllIngredients();
}
+
+ @Override
+ public Ingredient saveIngredient(Ingredient ingredient) {
+ return pantry.saveIngredient(ingredient);
+ }
+
+ @Override
+ public List saveAllIngredients(List ingredientsToAdd) {
+ return pantry.saveAllIngredients(ingredientsToAdd);
+ }
+
+ @Override
+ public Ingredient updateIngredient(Ingredient ingredient) {
+ return pantry.updateIngredient(ingredient);
+ }
+
+ @Override
+ public boolean deleteIngredient(String name) {
+ return pantry.deleteIngredient(name);
+ }
}
diff --git a/rest-service/src/main/java/com/unitbv/service/RecipeService.java b/rest-service/src/main/java/com/unitbv/service/RecipeService.java
new file mode 100644
index 0000000..6552b2b
--- /dev/null
+++ b/rest-service/src/main/java/com/unitbv/service/RecipeService.java
@@ -0,0 +1,12 @@
+package com.unitbv.service;
+
+import com.unitbv.request.CreateRecipeRequest;
+
+import java.util.List;
+
+public interface RecipeService {
+
+ List getAllRecipes();
+
+ CreateRecipeRequest saveRecipe(CreateRecipeRequest recipe);
+}
diff --git a/rest-service/src/main/java/com/unitbv/service/RecipeServiceImpl.java b/rest-service/src/main/java/com/unitbv/service/RecipeServiceImpl.java
new file mode 100644
index 0000000..feedb9e
--- /dev/null
+++ b/rest-service/src/main/java/com/unitbv/service/RecipeServiceImpl.java
@@ -0,0 +1,44 @@
+package com.unitbv.service;
+
+import com.unitbv.datasource.MyPantry;
+import com.unitbv.request.CreateRecipeRequest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.*;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.Arrays;
+import java.util.List;
+
+@Service
+public class RecipeServiceImpl implements RecipeService {
+
+ private final RestTemplate restTemplate;
+ private final MyPantry pantry;
+
+ @Autowired
+ public RecipeServiceImpl(RestTemplate restTemplate, MyPantry pantry) {
+ this.restTemplate = restTemplate;
+ this.pantry = pantry;
+ }
+
+ @Override
+ public List getAllRecipes() {
+ ResponseEntity response =
+ restTemplate.getForEntity(
+ "http://localhost:8081/api/recipe",
+ CreateRecipeRequest[].class);
+ return Arrays.asList(response.getBody());
+ }
+
+ @Override
+ public CreateRecipeRequest saveRecipe(CreateRecipeRequest recipe) {
+ ResponseEntity response =
+ restTemplate.postForEntity(
+ "http://localhost:8081/api/recipe",
+ recipe,
+ CreateRecipeRequest.class);
+ pantry.saveAllIngredients(recipe.getIngredients());
+ return response.getBody();
+ }
+}
diff --git a/rest-service/src/test/java/com/unitbv/ControllerTests.java b/rest-service/src/test/java/com/unitbv/ControllerTests.java
index 8f049e9..2a5c996 100644
--- a/rest-service/src/test/java/com/unitbv/ControllerTests.java
+++ b/rest-service/src/test/java/com/unitbv/ControllerTests.java
@@ -113,11 +113,11 @@ public void shouldReturn404NotFoundWhenIngredientIsNotFound() throws Exception {
* Create another Spring Boot application (you can use https://start.spring.io/). Name it whatever you want.
* Make sure that the project type is Maven, the language is Java and the packaging is jar.
* Add the Spring Web dependency. After generated, set its port to 8081.
- *
+ *
* What should it do?
* 1. It should be able to return the list of existing recipes
* 2. It should be able to create a new recipe based on a given name and a list of ingredients
- *
+ *
* What you need to do?
* 1. Create 2 model classes, for recipe and ingredient (a recipe has a name and contains a list of ingredients)
* 2. Create a datasource class (similar to MyPantry) where you will store the recipes
@@ -125,24 +125,23 @@ public void shouldReturn404NotFoundWhenIngredientIsNotFound() throws Exception {
* and delete are not necessary
* 4. Create a service class (similar to PantryService) where you will interact with the datasource class
* 5. Finally, create a controller and declare 2 endpoints:
- * 1. GET /recipe - returns the list of existing recipes
- * 2. POST /recipe - creates a new recipe based on the given name and list of ingredients (name
- * and list given in the request body) - if any ingredient is missing the name or the recipe name
- * is missing, respond with 400 BAD REQUEST
- *
+ * 1. GET /recipe - returns the list of existing recipes
+ * 2. POST /recipe - creates a new recipe based on the given name and list of ingredients (name
+ * and list given in the request body) - if any ingredient is missing the name or the recipe name
+ * is missing, respond with 400 BAD REQUEST
+ *
* Here, create a new controller and a new service for interacting with the Recipes Service. The controller should
* have 2 endpoints:
- * 1. GET /api/recipe/all - gets all existing recipes from the Recipes Service
- * 2. POST /api/recipe/new - receives a list of ingredients and a name for the recipe
- * - sends a request to the Recipes Service, passing the name and the list
- * - saves all ingredients locally - in MyPantry - only if the recipe was
- * saved successfully
+ * 1. GET /api/recipe/all - gets all existing recipes from the Recipes Service
+ * 2. POST /api/recipe/new - receives a list of ingredients and a name for the recipe
+ * - sends a request to the Recipes Service, passing the name and the list
+ * - saves all ingredients locally - in MyPantry - only if the recipe was
+ * saved successfully
* Use RestTemplate for sending requests to the Recipes Service endpoints.
* NOTE: In case there are errors when communicating with Recipes Service, 500 INTERNAL SERVER ERROR should be
* returned.
- *
+ *
* The below tests should pass.
- *
*/
// External service call - SUCCESS
@@ -159,7 +158,7 @@ public void shouldSaveAndReturnRecipeIfSuccessful() throws Exception {
this.mockMvc.perform(post("/api/recipe/new").contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(request)))
.andExpect(status().isOk())
- .andExpect(jsonPath("$[*].name").value(recipeName));
+ .andExpect(jsonPath("$.name").value(recipeName));
this.mockMvc.perform(get("/api/recipe/all"))
.andExpect(status().isOk())
diff --git a/service-application/.gitignore b/service-application/.gitignore
new file mode 100644
index 0000000..549e00a
--- /dev/null
+++ b/service-application/.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/service-application/.mvn/wrapper/maven-wrapper.jar b/service-application/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..c1dd12f
Binary files /dev/null and b/service-application/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/service-application/.mvn/wrapper/maven-wrapper.properties b/service-application/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..b7cb93e
--- /dev/null
+++ b/service-application/.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/service-application/mvnw b/service-application/mvnw
new file mode 100644
index 0000000..8a8fb22
--- /dev/null
+++ b/service-application/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/service-application/mvnw.cmd b/service-application/mvnw.cmd
new file mode 100644
index 0000000..1d8ab01
--- /dev/null
+++ b/service-application/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/service-application/pom.xml b/service-application/pom.xml
new file mode 100644
index 0000000..0e3b544
--- /dev/null
+++ b/service-application/pom.xml
@@ -0,0 +1,58 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.6.6
+
+
+ com.example
+ service-application
+ 0.0.1-SNAPSHOT
+ service-application
+ Demo project for Spring Boot
+
+ 17
+ 2021.0.1
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-config
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/service-application/src/main/java/com/example/serviceapplication/ServiceApplication.java b/service-application/src/main/java/com/example/serviceapplication/ServiceApplication.java
new file mode 100644
index 0000000..a19bc3d
--- /dev/null
+++ b/service-application/src/main/java/com/example/serviceapplication/ServiceApplication.java
@@ -0,0 +1,27 @@
+package com.example.serviceapplication;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RestController;
+
+@SpringBootApplication
+@RestController
+public class ServiceApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(ServiceApplication.class, args);
+ }
+
+ @Value("${message:default message}")
+ private String message;
+
+ @GetMapping(value = "/message")
+ public String getMessage() {
+ return message;
+ }
+
+
+}
diff --git a/service-application/src/main/resources/application.properties b/service-application/src/main/resources/application.properties
new file mode 100644
index 0000000..5373463
--- /dev/null
+++ b/service-application/src/main/resources/application.properties
@@ -0,0 +1,4 @@
+spring.application.name=app
+spring.profiles.active=local
+spring.config.import=optional:configserver:http://localhost:8888
+server.port=4001
diff --git a/service-application/src/test/java/com/example/serviceapplication/ServiceApplicationTests.java b/service-application/src/test/java/com/example/serviceapplication/ServiceApplicationTests.java
new file mode 100644
index 0000000..5be5b5f
--- /dev/null
+++ b/service-application/src/test/java/com/example/serviceapplication/ServiceApplicationTests.java
@@ -0,0 +1,13 @@
+package com.example.serviceapplication;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class ServiceApplicationTests {
+
+ @Test
+ void contextLoads() {
+ }
+
+}
diff --git a/spring1/.gitignore b/spring1/.gitignore
new file mode 100644
index 0000000..549e00a
--- /dev/null
+++ b/spring1/.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/spring1/pom.xml b/spring1/pom.xml
new file mode 100644
index 0000000..55666da
--- /dev/null
+++ b/spring1/pom.xml
@@ -0,0 +1,53 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.6.3
+
+
+ com.example
+ spring1
+ 0.0.1-SNAPSHOT
+ spring1
+ spring1
+
+ 1.8
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.springframework.data
+ spring-data-jpa
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 10
+ 10
+
+
+
+
+
+
diff --git a/spring1/src/main/java/com/unitbv/Spring1Application.java b/spring1/src/main/java/com/unitbv/Spring1Application.java
new file mode 100644
index 0000000..2d9a6da
--- /dev/null
+++ b/spring1/src/main/java/com/unitbv/Spring1Application.java
@@ -0,0 +1,13 @@
+package com.unitbv;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Spring1Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Spring1Application.class, args);
+ }
+
+}
diff --git a/spring1/src/main/java/com/unitbv/autowiring/AutowiredCfg.java b/spring1/src/main/java/com/unitbv/autowiring/AutowiredCfg.java
new file mode 100644
index 0000000..db8f32e
--- /dev/null
+++ b/spring1/src/main/java/com/unitbv/autowiring/AutowiredCfg.java
@@ -0,0 +1,9 @@
+package com.unitbv.autowiring;
+
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@ComponentScan(basePackages = {"com.unitbv.autowiring"})
+public class AutowiredCfg {
+}
diff --git a/spring1/src/main/java/com/unitbv/autowiring/service/FormatServiceConstructorInjection.java b/spring1/src/main/java/com/unitbv/autowiring/service/FormatServiceConstructorInjection.java
new file mode 100644
index 0000000..7551a55
--- /dev/null
+++ b/spring1/src/main/java/com/unitbv/autowiring/service/FormatServiceConstructorInjection.java
@@ -0,0 +1,18 @@
+package com.unitbv.autowiring.service;
+
+import com.unitbv.autowiring.util.FormatUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class FormatServiceConstructorInjection {
+ private final FormatUtil formatUtil;
+
+ public FormatServiceConstructorInjection(FormatUtil formatUtil) {
+ this.formatUtil = formatUtil;
+ }
+
+ public void checkFormatted() {
+ System.out.println(this.formatUtil.formatted(true));
+ }
+}
diff --git a/spring1/src/main/java/com/unitbv/autowiring/service/FormatServiceFieldInjection.java b/spring1/src/main/java/com/unitbv/autowiring/service/FormatServiceFieldInjection.java
new file mode 100644
index 0000000..39cc99d
--- /dev/null
+++ b/spring1/src/main/java/com/unitbv/autowiring/service/FormatServiceFieldInjection.java
@@ -0,0 +1,15 @@
+package com.unitbv.autowiring.service;
+
+import com.unitbv.autowiring.util.FormatUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class FormatServiceFieldInjection {
+ @Autowired
+ public FormatUtil formatUtil;
+
+ public void checkFormatted() {
+ System.out.println(this.formatUtil.formatted(true));
+ }
+}
diff --git a/spring1/src/main/java/com/unitbv/autowiring/service/FormatServiceSetterInjection.java b/spring1/src/main/java/com/unitbv/autowiring/service/FormatServiceSetterInjection.java
new file mode 100644
index 0000000..831f0c5
--- /dev/null
+++ b/spring1/src/main/java/com/unitbv/autowiring/service/FormatServiceSetterInjection.java
@@ -0,0 +1,19 @@
+package com.unitbv.autowiring.service;
+
+import com.unitbv.autowiring.util.FormatUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class FormatServiceSetterInjection {
+ private FormatUtil formatUtil;
+
+ public void checkFormatted() {
+ System.out.println(this.formatUtil.formatted(true));
+ }
+
+ @Autowired
+ public void setFormatUtil(FormatUtil formatUtil) {
+ this.formatUtil=formatUtil;
+ }
+}
diff --git a/spring1/src/main/java/com/unitbv/autowiring/util/FormatUtil.java b/spring1/src/main/java/com/unitbv/autowiring/util/FormatUtil.java
new file mode 100644
index 0000000..39025aa
--- /dev/null
+++ b/spring1/src/main/java/com/unitbv/autowiring/util/FormatUtil.java
@@ -0,0 +1,13 @@
+package com.unitbv.autowiring.util;
+
+import org.springframework.stereotype.Component;
+
+@Component
+public class FormatUtil {
+ public String formatted(boolean isFormatted) {
+ if (isFormatted) {
+ return "Everything was formatted.";
+ }
+ return "Couldn't format";
+ }
+}
diff --git a/spring1/src/main/java/com/unitbv/beans/Book.java b/spring1/src/main/java/com/unitbv/beans/Book.java
new file mode 100644
index 0000000..41d280a
--- /dev/null
+++ b/spring1/src/main/java/com/unitbv/beans/Book.java
@@ -0,0 +1,20 @@
+package com.unitbv.beans;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+@Component
+public class Book implements Item {
+ private String title;
+
+ @Autowired
+ public Book(@Value("${application.properties.book.title") String title) {
+ this.title = title;
+ }
+
+ @Override
+ public String getTitle() {
+ return title;
+ }
+}
diff --git a/spring1/src/main/java/com/unitbv/beans/Human.java b/spring1/src/main/java/com/unitbv/beans/Human.java
new file mode 100644
index 0000000..5bbd304
--- /dev/null
+++ b/spring1/src/main/java/com/unitbv/beans/Human.java
@@ -0,0 +1,6 @@
+package com.unitbv.beans;
+
+public interface Human {
+
+ Item getItem();
+}
diff --git a/spring1/src/main/java/com/unitbv/beans/HumanAppCfg.java b/spring1/src/main/java/com/unitbv/beans/HumanAppCfg.java
new file mode 100644
index 0000000..a38cf2b
--- /dev/null
+++ b/spring1/src/main/java/com/unitbv/beans/HumanAppCfg.java
@@ -0,0 +1,9 @@
+package com.unitbv.beans;
+
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@ComponentScan(basePackages = {"com.unitbv.beans"} )
+public class HumanAppCfg {
+}
diff --git a/spring1/src/main/java/com/unitbv/beans/Item.java b/spring1/src/main/java/com/unitbv/beans/Item.java
new file mode 100644
index 0000000..a06892b
--- /dev/null
+++ b/spring1/src/main/java/com/unitbv/beans/Item.java
@@ -0,0 +1,5 @@
+package com.unitbv.beans;
+
+public interface Item {
+ String getTitle();
+}
diff --git a/spring1/src/main/java/com/unitbv/beans/Person.java b/spring1/src/main/java/com/unitbv/beans/Person.java
new file mode 100644
index 0000000..987caf0
--- /dev/null
+++ b/spring1/src/main/java/com/unitbv/beans/Person.java
@@ -0,0 +1,23 @@
+package com.unitbv.beans;
+
+import com.unitbv.autowiring.util.FormatUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.stereotype.Component;
+
+@Component
+public class Person implements Human {
+
+ @Autowired
+ private Item item;
+
+ @Autowired
+ public Person(Item item) {
+ this.item = item;
+ }
+
+ @Override
+ public Item getItem() {
+ return item;
+ }
+}
diff --git a/spring1/src/main/java/com/unitbv/beansnaming/DependantBean.java b/spring1/src/main/java/com/unitbv/beansnaming/DependantBean.java
new file mode 100644
index 0000000..4d3cf32
--- /dev/null
+++ b/spring1/src/main/java/com/unitbv/beansnaming/DependantBean.java
@@ -0,0 +1,4 @@
+package com.unitbv.beansnaming;
+
+public interface DependantBean {
+}
\ No newline at end of file
diff --git a/spring1/src/main/java/com/unitbv/beansnaming/DependantBeanImpl.java b/spring1/src/main/java/com/unitbv/beansnaming/DependantBeanImpl.java
new file mode 100644
index 0000000..5de2fa6
--- /dev/null
+++ b/spring1/src/main/java/com/unitbv/beansnaming/DependantBeanImpl.java
@@ -0,0 +1,10 @@
+package com.unitbv.beansnaming;
+
+
+public class DependantBeanImpl implements DependantBean {
+ private SimpleBean simpleBean;
+
+ public DependantBeanImpl(SimpleBean simpleBean) {
+ this.simpleBean = simpleBean;
+ }
+}
\ No newline at end of file
diff --git a/spring1/src/main/java/com/unitbv/beansnaming/SimpleBean.java b/spring1/src/main/java/com/unitbv/beansnaming/SimpleBean.java
new file mode 100644
index 0000000..3bb5316
--- /dev/null
+++ b/spring1/src/main/java/com/unitbv/beansnaming/SimpleBean.java
@@ -0,0 +1,4 @@
+package com.unitbv.beansnaming;
+
+public interface SimpleBean {
+}
\ No newline at end of file
diff --git a/spring1/src/main/java/com/unitbv/beansnaming/SimpleBeanImpl.java b/spring1/src/main/java/com/unitbv/beansnaming/SimpleBeanImpl.java
new file mode 100644
index 0000000..9d85a46
--- /dev/null
+++ b/spring1/src/main/java/com/unitbv/beansnaming/SimpleBeanImpl.java
@@ -0,0 +1,19 @@
+package com.unitbv.beansnaming;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+//TODO test what will happen when you add a stereotype annotation
+public class SimpleBeanImpl implements SimpleBean {
+
+ public SimpleBeanImpl() {
+ Logger logger = LoggerFactory.getLogger(SimpleBeanImpl.class);
+ logger.info("[SimpleBeanImpl instantiation]");
+ }
+
+ @Override
+ public String toString() {
+ return "SimpleBeanImpl{ code: " + hashCode() + "}";
+ }
+
+}
\ No newline at end of file
diff --git a/spring1/src/main/java/com/unitbv/beansnaming/SimpleDependantCfg.java b/spring1/src/main/java/com/unitbv/beansnaming/SimpleDependantCfg.java
new file mode 100644
index 0000000..470f45f
--- /dev/null
+++ b/spring1/src/main/java/com/unitbv/beansnaming/SimpleDependantCfg.java
@@ -0,0 +1,28 @@
+package com.unitbv.beansnaming;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@ComponentScan(basePackages = {"com.unitbv.beansnaming"})
+public class SimpleDependantCfg {
+
+ private final Logger logger = LoggerFactory.getLogger(SimpleDependantCfg.class);
+
+ //@Bean
+ //@Bean("customSimpleBean")
+ @Bean({"customSimpleBean1", "customSimpleBean2"})
+ SimpleBean simpleBean() {
+ return new SimpleBeanImpl();
+ }
+
+ //@Bean
+ //@Bean("customDependantBean")
+ @Bean({"customDependantBean1", "customDependantBean2"})
+ DependantBean dependantBean() {
+ return new DependantBeanImpl(simpleBean());
+ }
+}
\ No newline at end of file
diff --git a/spring1/src/main/java/com/unitbv/lifecycle/DepBean.java b/spring1/src/main/java/com/unitbv/lifecycle/DepBean.java
new file mode 100644
index 0000000..808134f
--- /dev/null
+++ b/spring1/src/main/java/com/unitbv/lifecycle/DepBean.java
@@ -0,0 +1,7 @@
+package com.unitbv.lifecycle;
+
+import org.springframework.stereotype.Component;
+
+@Component
+public class DepBean {
+}
diff --git a/spring1/src/main/java/com/unitbv/lifecycle/FunBean.java b/spring1/src/main/java/com/unitbv/lifecycle/FunBean.java
new file mode 100644
index 0000000..72a9179
--- /dev/null
+++ b/spring1/src/main/java/com/unitbv/lifecycle/FunBean.java
@@ -0,0 +1,68 @@
+package com.unitbv.lifecycle;
+
+import com.unitbv.beans.Item;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+
+@Component
+public class FunBean implements InitializingBean, DisposableBean, ApplicationContextAware {
+
+ private Logger logger = LoggerFactory.getLogger(FunBean.class);
+
+ @Autowired
+ private DepBean depBean;
+
+ @Autowired
+ public FunBean() {
+
+ }
+
+ @Autowired
+ void setDepBean(DepBean depBean) {
+ this.depBean = depBean;
+ logger.debug("[Setter]");
+ }
+
+ @Override
+ public void destroy() throws Exception {
+ logger.debug("[DestroyOverride]");
+ }
+
+ @Override
+ public void afterPropertiesSet() throws Exception {
+ logger.debug("[afterPropertiesSet]");
+ }
+
+ public void initializeMethod() {
+ logger.debug("[Initialize]");
+ }
+
+ public void destroyMethod() {
+ logger.debug("[Destroy]");
+ }
+
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+ logger.debug("[setApplicationContext]");
+ }
+
+ @PostConstruct
+ public void postConstruct() {
+ logger.debug("[PostConstruct]");
+ }
+
+ @PreDestroy
+ public void preDestroy() {
+ logger.debug("[PreDestroy]");
+ }
+}
\ No newline at end of file
diff --git a/spring1/src/main/java/com/unitbv/lifecycle/FunBeanCfg.java b/spring1/src/main/java/com/unitbv/lifecycle/FunBeanCfg.java
new file mode 100644
index 0000000..a5a3901
--- /dev/null
+++ b/spring1/src/main/java/com/unitbv/lifecycle/FunBeanCfg.java
@@ -0,0 +1,16 @@
+package com.unitbv.lifecycle;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+
+
+@Configuration
+@ComponentScan(basePackages = {"com.unitbv.lifecycle"})
+public class FunBeanCfg {
+
+ @Bean(initMethod="afterPropertiesSet", destroyMethod="destroy")
+ FunBean funBean() {
+ return new FunBean();
+ }
+}
\ No newline at end of file
diff --git a/spring1/src/main/java/com/unitbv/stereotype/StereotypeCfg.java b/spring1/src/main/java/com/unitbv/stereotype/StereotypeCfg.java
new file mode 100644
index 0000000..cb4586e
--- /dev/null
+++ b/spring1/src/main/java/com/unitbv/stereotype/StereotypeCfg.java
@@ -0,0 +1,9 @@
+package com.unitbv.stereotype;
+
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@ComponentScan(basePackages = "com.unitbv")
+public class StereotypeCfg {
+}
diff --git a/spring1/src/main/java/com/unitbv/stereotype/controller/UserController.java b/spring1/src/main/java/com/unitbv/stereotype/controller/UserController.java
new file mode 100644
index 0000000..c303298
--- /dev/null
+++ b/spring1/src/main/java/com/unitbv/stereotype/controller/UserController.java
@@ -0,0 +1,7 @@
+package com.unitbv.stereotype.controller;
+
+import org.springframework.stereotype.Controller;
+
+@Controller
+public class UserController {
+}
diff --git a/spring1/src/main/java/com/unitbv/stereotype/model/User.java b/spring1/src/main/java/com/unitbv/stereotype/model/User.java
new file mode 100644
index 0000000..77f84a0
--- /dev/null
+++ b/spring1/src/main/java/com/unitbv/stereotype/model/User.java
@@ -0,0 +1,9 @@
+package com.unitbv.stereotype.model;
+
+import org.springframework.stereotype.Component;
+
+@Component
+public class User {
+ private Integer id;
+ private String name;
+}
diff --git a/spring1/src/main/java/com/unitbv/stereotype/repository/UserRepository.java b/spring1/src/main/java/com/unitbv/stereotype/repository/UserRepository.java
new file mode 100644
index 0000000..01ea991
--- /dev/null
+++ b/spring1/src/main/java/com/unitbv/stereotype/repository/UserRepository.java
@@ -0,0 +1,7 @@
+package com.unitbv.stereotype.repository;
+
+import com.unitbv.stereotype.model.User;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface UserRepository extends JpaRepository {
+}
diff --git a/spring1/src/main/java/com/unitbv/stereotype/repository/impl/UserRepositoryImpl.java b/spring1/src/main/java/com/unitbv/stereotype/repository/impl/UserRepositoryImpl.java
new file mode 100644
index 0000000..b7aed1f
--- /dev/null
+++ b/spring1/src/main/java/com/unitbv/stereotype/repository/impl/UserRepositoryImpl.java
@@ -0,0 +1,162 @@
+package com.unitbv.stereotype.repository.impl;
+
+import com.unitbv.stereotype.model.User;
+import com.unitbv.stereotype.repository.UserRepository;
+import org.springframework.data.domain.Example;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.repository.query.FluentQuery;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Function;
+
+@Repository
+public class UserRepositoryImpl implements UserRepository {
+ @Override
+ public List findAll() {
+ return null;
+ }
+
+ @Override
+ public List findAll(Sort sort) {
+ return null;
+ }
+
+ @Override
+ public Page findAll(Pageable pageable) {
+ return null;
+ }
+
+ @Override
+ public List findAllById(Iterable users) {
+ return null;
+ }
+
+ @Override
+ public long count() {
+ return 0;
+ }
+
+ @Override
+ public void deleteById(User user) {
+
+ }
+
+ @Override
+ public void delete(Integer entity) {
+
+ }
+
+ @Override
+ public void deleteAllById(Iterable extends User> users) {
+
+ }
+
+ @Override
+ public void deleteAll(Iterable extends Integer> entities) {
+
+ }
+
+ @Override
+ public void deleteAll() {
+
+ }
+
+ @Override
+ public S save(S entity) {
+ return null;
+ }
+
+ @Override
+ public List saveAll(Iterable entities) {
+ return null;
+ }
+
+ @Override
+ public Optional findById(User user) {
+ return Optional.empty();
+ }
+
+ @Override
+ public boolean existsById(User user) {
+ return false;
+ }
+
+ @Override
+ public void flush() {
+
+ }
+
+ @Override
+ public S saveAndFlush(S entity) {
+ return null;
+ }
+
+ @Override
+ public List saveAllAndFlush(Iterable entities) {
+ return null;
+ }
+
+ @Override
+ public void deleteAllInBatch(Iterable entities) {
+
+ }
+
+ @Override
+ public void deleteAllByIdInBatch(Iterable users) {
+
+ }
+
+ @Override
+ public void deleteAllInBatch() {
+
+ }
+
+ @Override
+ public Integer getOne(User user) {
+ return null;
+ }
+
+ @Override
+ public Integer getById(User user) {
+ return null;
+ }
+
+ @Override
+ public Optional findOne(Example example) {
+ return Optional.empty();
+ }
+
+ @Override
+ public List findAll(Example example) {
+ return null;
+ }
+
+ @Override
+ public List findAll(Example example, Sort sort) {
+ return null;
+ }
+
+ @Override
+ public Page findAll(Example example, Pageable pageable) {
+ return null;
+ }
+
+ @Override
+ public long count(Example example) {
+ return 0;
+ }
+
+ @Override
+ public boolean exists(Example example) {
+ return false;
+ }
+
+ @Override
+ public R findBy(Example example, Function, R> queryFunction) {
+ return null;
+ }
+}
diff --git a/spring1/src/main/java/com/unitbv/stereotype/service/UserService.java b/spring1/src/main/java/com/unitbv/stereotype/service/UserService.java
new file mode 100644
index 0000000..3b9ad34
--- /dev/null
+++ b/spring1/src/main/java/com/unitbv/stereotype/service/UserService.java
@@ -0,0 +1,4 @@
+package com.unitbv.stereotype.service;
+
+public interface UserService {
+}
diff --git a/spring1/src/main/java/com/unitbv/stereotype/service/impl/UserServiceImpl.java b/spring1/src/main/java/com/unitbv/stereotype/service/impl/UserServiceImpl.java
new file mode 100644
index 0000000..bc9695a
--- /dev/null
+++ b/spring1/src/main/java/com/unitbv/stereotype/service/impl/UserServiceImpl.java
@@ -0,0 +1,8 @@
+package com.unitbv.stereotype.service.impl;
+
+import com.unitbv.stereotype.service.UserService;
+import org.springframework.stereotype.Service;
+
+@Service
+public class UserServiceImpl implements UserService {
+}
diff --git a/spring1/src/main/java/com/unitbv/stereotype/util/UserUtil.java b/spring1/src/main/java/com/unitbv/stereotype/util/UserUtil.java
new file mode 100644
index 0000000..0ca3835
--- /dev/null
+++ b/spring1/src/main/java/com/unitbv/stereotype/util/UserUtil.java
@@ -0,0 +1,7 @@
+package com.unitbv.stereotype.util;
+
+import org.springframework.stereotype.Component;
+
+@Component
+public class UserUtil {
+}
diff --git a/spring1/src/main/resources/application.properties b/spring1/src/main/resources/application.properties
new file mode 100644
index 0000000..b2ff11b
--- /dev/null
+++ b/spring1/src/main/resources/application.properties
@@ -0,0 +1 @@
+book.title="Dummy title"
\ No newline at end of file
diff --git a/spring1/src/test/java/com/unitbv/Spring1ApplicationTests.java b/spring1/src/test/java/com/unitbv/Spring1ApplicationTests.java
new file mode 100644
index 0000000..8307489
--- /dev/null
+++ b/spring1/src/test/java/com/unitbv/Spring1ApplicationTests.java
@@ -0,0 +1,13 @@
+package com.unitbv;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class Spring1ApplicationTests {
+
+ @Test
+ void contextLoads() {
+ }
+
+}
diff --git a/spring1/src/test/java/com/unitbv/autowiring/AutowiredCfgTest.java b/spring1/src/test/java/com/unitbv/autowiring/AutowiredCfgTest.java
new file mode 100644
index 0000000..7e2b6d0
--- /dev/null
+++ b/spring1/src/test/java/com/unitbv/autowiring/AutowiredCfgTest.java
@@ -0,0 +1,39 @@
+package com.unitbv.autowiring;
+
+import com.unitbv.autowiring.service.FormatServiceConstructorInjection;
+import com.unitbv.autowiring.service.FormatServiceFieldInjection;
+import com.unitbv.autowiring.service.FormatServiceSetterInjection;
+import com.unitbv.autowiring.util.FormatUtil;
+import org.junit.jupiter.api.Test;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+public class AutowiredCfgTest {
+ //TODO use constructor injection, setter injection and field injection to add dependency in FormatServices classes
+
+ @Test
+ void checkFormattedTestAutowireConstructorInjection() {
+ FormatUtil formatUtil = new FormatUtil();
+ FormatServiceConstructorInjection formatServiceConstructorInjection = new FormatServiceConstructorInjection(formatUtil);
+ formatServiceConstructorInjection.checkFormatted();
+ }
+
+ @Test
+ void checkFormattedTestAutowireSetterInjection() {
+ FormatUtil formatUtil = new FormatUtil();
+ FormatServiceSetterInjection formatServiceSetterInjection = new FormatServiceSetterInjection();
+ formatServiceSetterInjection.setFormatUtil(formatUtil);
+ formatServiceSetterInjection.checkFormatted();
+ }
+
+ @Test
+ void checkFormattedTestAutowireFieldInjection() {
+ ConfigurableApplicationContext ctx =
+ new AnnotationConfigApplicationContext(AutowiredCfg.class);
+ FormatServiceFieldInjection formatServiceFieldInjection = ctx.getBean(FormatServiceFieldInjection.class);
+ assertNotNull(formatServiceFieldInjection);
+ formatServiceFieldInjection.checkFormatted();
+ }
+}
diff --git a/spring1/src/test/java/com/unitbv/beans/HumanAppCfgTest.java b/spring1/src/test/java/com/unitbv/beans/HumanAppCfgTest.java
new file mode 100644
index 0000000..45d1a77
--- /dev/null
+++ b/spring1/src/test/java/com/unitbv/beans/HumanAppCfgTest.java
@@ -0,0 +1,53 @@
+/*
+Freeware License, some rights reserved
+
+Copyright (c) 2019 Iuliana Cosmina
+
+Permission is hereby granted, free of charge, to anyone obtaining a copy
+of this software and associated documentation files (the "Software"),
+to work with the Software within the limits of freeware distribution and fair use.
+This includes the rights to use, copy, and modify the Software for personal use.
+Users are also allowed and encouraged to submit corrections and modifications
+to the Software for the benefit of other users.
+
+It is not allowed to reuse, modify, or redistribute the Software for
+commercial use in any way, or for a user's educational materials such as books
+or blog articles without prior permission from the copyright holder.
+
+The above copyright notice and this permission notice need to be included
+in all copies or substantial portions of the software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS OR APRESS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+package com.unitbv.beans;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+class HumanAppCfgTest {
+
+ //TODO make Book.class and Person.class to be recognized as beans by Spring and inject their values
+ // through constructors in order to make them compile
+ //title from Book class should be populated with a value that comes from application.properties file
+ @Test
+ void testHumanAndItem() {
+ ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(HumanAppCfg.class);
+
+ Human humanBean = ctx.getBean(Human.class);
+
+ assertNotNull(humanBean);
+ assertNotNull(humanBean.getItem());
+ assertNotNull(humanBean.getItem().getTitle());
+
+ ctx.close();
+ }
+}
diff --git a/spring1/src/test/java/com/unitbv/beansnaming/SimpleDependantCfgTest.java b/spring1/src/test/java/com/unitbv/beansnaming/SimpleDependantCfgTest.java
new file mode 100644
index 0000000..74fe6b5
--- /dev/null
+++ b/spring1/src/test/java/com/unitbv/beansnaming/SimpleDependantCfgTest.java
@@ -0,0 +1,65 @@
+package com.unitbv.beansnaming;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+public class SimpleDependantCfgTest {
+
+ @Test
+ void testBeanNamingDefaultName() {
+ //TODO create definitions for SimpleBean and DependantBean and log some messages
+ ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(SimpleDependantCfg.class);
+
+ SimpleBean simpleBean = ctx.getBean("simpleBean", SimpleBean.class);
+ DependantBean dependantBean = ctx.getBean("dependantBean", DependantBean.class);
+
+ assertNotNull(simpleBean);
+ assertNotNull(dependantBean);
+
+ ctx.close();
+ }
+
+ @Test
+ void testBeanNamingSingleCustomName() {
+ //TODO define a name for your beans
+ ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(SimpleDependantCfg.class);
+
+ SimpleBean customSimpleBean = ctx.getBean("customSimpleBean", SimpleBean.class);
+ DependantBean customDependantBean = ctx.getBean("customDependantBean", DependantBean.class);
+
+ assertNotNull(customSimpleBean);
+ assertNotNull(customDependantBean);
+
+ // no bean named 'simpleBean' and 'dependantBean'
+ assertThrows(NoSuchBeanDefinitionException.class, () -> ctx.getBean("simpleBean", SimpleBean.class));
+ assertThrows(NoSuchBeanDefinitionException.class, () -> ctx.getBean("dependantBean", DependantBean.class));
+
+ ctx.close();
+ }
+
+ @Test
+ void testBeanNamingMultipleCustomName() {
+ //TODO define multiple names for the same bean
+ ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(SimpleDependantCfg.class);
+
+ SimpleBean customSimpleBean1 = ctx.getBean("customSimpleBean1", SimpleBean.class);
+ SimpleBean customSimpleBean2 = ctx.getBean("customSimpleBean2", SimpleBean.class);
+
+ DependantBean customDependantBean1 = ctx.getBean("customDependantBean1", DependantBean.class);
+ DependantBean customDependantBean2 = ctx.getBean("customDependantBean2", DependantBean.class);
+
+ assertNotNull(customSimpleBean1);
+ assertNotNull(customSimpleBean2);
+ assertEquals(customDependantBean1, customDependantBean2);
+
+ assertNotNull(customDependantBean1);
+ assertNotNull(customDependantBean2);
+ assertEquals(customDependantBean1, customDependantBean2);
+
+ ctx.close();
+ }
+}
diff --git a/spring1/src/test/java/com/unitbv/lifecycle/FunBeanCfgTest.java b/spring1/src/test/java/com/unitbv/lifecycle/FunBeanCfgTest.java
new file mode 100644
index 0000000..b84d821
--- /dev/null
+++ b/spring1/src/test/java/com/unitbv/lifecycle/FunBeanCfgTest.java
@@ -0,0 +1,23 @@
+package com.unitbv.lifecycle;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+public class FunBeanCfgTest {
+
+ @Test
+ void testBeanLifecycle() {
+ //TODO configure all lifecycle methods for FunBean and log messages just to be clear in each order are the methods called.
+ // hint 1: Use setter to inject a value for DepBean
+ // hint 2: @Bean has 2 values called initMethod and destroyMethod
+ // hint 3: you need to implement InitializingBean, DisposableBean
+ // hint 4: there should be 8 logged messages
+ var ctx = new AnnotationConfigApplicationContext(FunBeanCfg.class);
+ ctx.registerShutdownHook();
+
+ FunBean funBean = ctx.getBean(FunBean.class);
+ assertNotNull(funBean);
+ }
+}
diff --git a/spring1/src/test/java/com/unitbv/stereotype/StereotypeCfgTest.java b/spring1/src/test/java/com/unitbv/stereotype/StereotypeCfgTest.java
new file mode 100644
index 0000000..df519f3
--- /dev/null
+++ b/spring1/src/test/java/com/unitbv/stereotype/StereotypeCfgTest.java
@@ -0,0 +1,35 @@
+package com.unitbv.stereotype;
+
+import com.unitbv.stereotype.controller.UserController;
+import com.unitbv.stereotype.repository.UserRepository;
+import com.unitbv.stereotype.repository.impl.UserRepositoryImpl;
+import com.unitbv.stereotype.service.UserService;
+import com.unitbv.stereotype.service.impl.UserServiceImpl;
+import com.unitbv.stereotype.util.UserUtil;
+import org.junit.jupiter.api.Test;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+public class StereotypeCfgTest {
+
+ //TODO add stereotype annotations in order to instantiate the beans. Use more specific annotations where you can
+ // Hint 1: there are 4 stereotype annotations
+ // Hint 2: pay attention to the configuration of StereotypeCfg.class
+ @Test
+ void testStereotypeAnnotations() {
+ var ctx = new AnnotationConfigApplicationContext(StereotypeCfg.class);
+ ctx.registerShutdownHook();
+
+ UserController userControllerBean = ctx.getBean(UserController.class);
+ UserService userServiceBean = ctx.getBean(UserServiceImpl.class);
+ UserRepository userRepositoryBean = ctx.getBean(UserRepositoryImpl.class);
+ UserUtil userUtilBean = ctx.getBean(UserUtil.class);
+
+ assertNotNull(userControllerBean);
+ assertNotNull(userServiceBean);
+ assertNotNull(userRepositoryBean);
+ assertNotNull(userUtilBean);
+
+ }
+}
diff --git a/spring2/pom.xml b/spring2/pom.xml
new file mode 100644
index 0000000..bae1643
--- /dev/null
+++ b/spring2/pom.xml
@@ -0,0 +1,84 @@
+
+
+ 4.0.0
+
+ programare-cloud-java
+ com.unitbv
+ 1.0-SNAPSHOT
+
+
+ com.unitbv
+ spring2
+ 1.0-SNAPSHOT
+
+ spring2
+
+ http://www.example.com
+
+
+ UTF-8
+ 1.8
+ 1.8
+
+
+
+
+ junit
+ junit
+ 4.12
+ test
+
+
+ org.springframework
+ spring-test
+ 5.3.16
+ test
+
+
+
+
+
+
+
+
+ maven-clean-plugin
+ 3.1.0
+
+
+
+ maven-resources-plugin
+ 3.0.2
+
+
+ maven-compiler-plugin
+ 3.8.0
+
+
+ maven-surefire-plugin
+ 2.22.1
+
+
+ maven-jar-plugin
+ 3.0.2
+
+
+ maven-install-plugin
+ 2.5.2
+
+
+ maven-deploy-plugin
+ 2.8.2
+
+
+
+ maven-site-plugin
+ 3.7.1
+
+
+ maven-project-info-reports-plugin
+ 3.0.0
+
+
+
+
+
diff --git a/spring2/src/main/java/com/unitbv/dependsOn/AppConfig.java b/spring2/src/main/java/com/unitbv/dependsOn/AppConfig.java
new file mode 100644
index 0000000..bc11fa4
--- /dev/null
+++ b/spring2/src/main/java/com/unitbv/dependsOn/AppConfig.java
@@ -0,0 +1,26 @@
+package com.unitbv.dependsOn;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.DependsOn;
+
+@Configuration
+public class AppConfig {
+
+ @Bean
+ @DependsOn("beanB")
+ public BeanA beanA() {
+ return new BeanA();
+ }
+
+ @Bean
+ @DependsOn("beanC")
+ public BeanB beanB() {
+ return new BeanB();
+ }
+
+ @Bean
+ public BeanC beanC() {
+ return new BeanC();
+ }
+}
diff --git a/spring2/src/main/java/com/unitbv/dependsOn/BeanA.java b/spring2/src/main/java/com/unitbv/dependsOn/BeanA.java
new file mode 100644
index 0000000..0a8c06e
--- /dev/null
+++ b/spring2/src/main/java/com/unitbv/dependsOn/BeanA.java
@@ -0,0 +1,7 @@
+package com.unitbv.dependsOn;
+
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class BeanA {
+}
diff --git a/spring2/src/main/java/com/unitbv/dependsOn/BeanB.java b/spring2/src/main/java/com/unitbv/dependsOn/BeanB.java
new file mode 100644
index 0000000..d089690
--- /dev/null
+++ b/spring2/src/main/java/com/unitbv/dependsOn/BeanB.java
@@ -0,0 +1,8 @@
+package com.unitbv.dependsOn;
+
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class BeanB {
+
+}
diff --git a/spring2/src/main/java/com/unitbv/dependsOn/BeanC.java b/spring2/src/main/java/com/unitbv/dependsOn/BeanC.java
new file mode 100644
index 0000000..5e15fd6
--- /dev/null
+++ b/spring2/src/main/java/com/unitbv/dependsOn/BeanC.java
@@ -0,0 +1,7 @@
+package com.unitbv.dependsOn;
+
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class BeanC {
+}
diff --git a/spring2/src/main/java/com/unitbv/events/configuration/AppConfig.java b/spring2/src/main/java/com/unitbv/events/configuration/AppConfig.java
new file mode 100644
index 0000000..ef86295
--- /dev/null
+++ b/spring2/src/main/java/com/unitbv/events/configuration/AppConfig.java
@@ -0,0 +1,26 @@
+package com.unitbv.events.configuration;
+
+import com.unitbv.events.event.CarForRentEvent;
+import com.unitbv.events.service.CarService;
+import com.unitbv.events.service.PersonService;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class AppConfig {
+ @Bean
+ public CarService carService() {
+ return new CarService();
+ }
+
+ @Bean
+ public PersonService personService() {
+ return new PersonService(new ApplicationEventPublisher() {
+ @Override
+ public void publishEvent(Object event) {
+ carService().addCarForRent((CarForRentEvent) event);
+ }
+ });
+ }
+}
diff --git a/spring2/src/main/java/com/unitbv/events/event/CarForRentEvent.java b/spring2/src/main/java/com/unitbv/events/event/CarForRentEvent.java
new file mode 100644
index 0000000..3095e86
--- /dev/null
+++ b/spring2/src/main/java/com/unitbv/events/event/CarForRentEvent.java
@@ -0,0 +1,13 @@
+package com.unitbv.events.event;
+
+import org.springframework.context.ApplicationEvent;
+
+public class CarForRentEvent extends ApplicationEvent {
+ public CarForRentEvent(Object source) {
+ super(source);
+ }
+
+ public Object getCar() {
+ return source;
+ }
+}
diff --git a/spring2/src/main/java/com/unitbv/events/model/Car.java b/spring2/src/main/java/com/unitbv/events/model/Car.java
new file mode 100644
index 0000000..142056e
--- /dev/null
+++ b/spring2/src/main/java/com/unitbv/events/model/Car.java
@@ -0,0 +1,9 @@
+package com.unitbv.events.model;
+
+public class Car {
+ private final String model;
+
+ public Car(String model) {
+ this.model = model;
+ }
+}
diff --git a/spring2/src/main/java/com/unitbv/events/service/CarService.java b/spring2/src/main/java/com/unitbv/events/service/CarService.java
new file mode 100644
index 0000000..6083f54
--- /dev/null
+++ b/spring2/src/main/java/com/unitbv/events/service/CarService.java
@@ -0,0 +1,23 @@
+package com.unitbv.events.service;
+
+import com.unitbv.events.event.CarForRentEvent;
+import com.unitbv.events.model.Car;
+import lombok.Getter;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Service
+@Getter
+public class CarService {
+ private final List availableCars;
+
+ public CarService() {
+ this.availableCars = new ArrayList<>();
+ }
+
+ public void addCarForRent(CarForRentEvent carForRentEvent) {
+ this.availableCars.add((Car) carForRentEvent.getCar());
+ }
+}
diff --git a/spring2/src/main/java/com/unitbv/events/service/PersonService.java b/spring2/src/main/java/com/unitbv/events/service/PersonService.java
new file mode 100644
index 0000000..0182243
--- /dev/null
+++ b/spring2/src/main/java/com/unitbv/events/service/PersonService.java
@@ -0,0 +1,22 @@
+package com.unitbv.events.service;
+
+import com.unitbv.events.event.CarForRentEvent;
+import com.unitbv.events.model.Car;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.stereotype.Service;
+
+@Service
+public class PersonService {
+
+ private final ApplicationEventPublisher eventPublisher;
+
+ public PersonService(ApplicationEventPublisher eventPublisher) {
+ this.eventPublisher = eventPublisher;
+ }
+
+ public void rentCar(String model) {
+ final Car car = new Car(model);
+ CarForRentEvent carEvent = new CarForRentEvent(car);
+ eventPublisher.publishEvent(carEvent);
+ }
+}
diff --git a/spring2/src/main/java/com/unitbv/multipleConfigs/BeanA.java b/spring2/src/main/java/com/unitbv/multipleConfigs/BeanA.java
new file mode 100644
index 0000000..3c2a8b5
--- /dev/null
+++ b/spring2/src/main/java/com/unitbv/multipleConfigs/BeanA.java
@@ -0,0 +1,8 @@
+package com.unitbv.multipleConfigs;
+
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class BeanA {
+
+}
diff --git a/spring2/src/main/java/com/unitbv/multipleConfigs/BeanB.java b/spring2/src/main/java/com/unitbv/multipleConfigs/BeanB.java
new file mode 100644
index 0000000..c7477ce
--- /dev/null
+++ b/spring2/src/main/java/com/unitbv/multipleConfigs/BeanB.java
@@ -0,0 +1,8 @@
+package com.unitbv.multipleConfigs;
+
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class BeanB {
+
+}
diff --git a/spring2/src/main/java/com/unitbv/multipleConfigs/ConfigA.java b/spring2/src/main/java/com/unitbv/multipleConfigs/ConfigA.java
new file mode 100644
index 0000000..91d14e7
--- /dev/null
+++ b/spring2/src/main/java/com/unitbv/multipleConfigs/ConfigA.java
@@ -0,0 +1,10 @@
+package com.unitbv.multipleConfigs;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class ConfigA {
+ @Bean
+ public BeanA beanA(){return new BeanA();}
+}
diff --git a/spring2/src/main/java/com/unitbv/multipleConfigs/ConfigB.java b/spring2/src/main/java/com/unitbv/multipleConfigs/ConfigB.java
new file mode 100644
index 0000000..d9317f8
--- /dev/null
+++ b/spring2/src/main/java/com/unitbv/multipleConfigs/ConfigB.java
@@ -0,0 +1,13 @@
+package com.unitbv.multipleConfigs;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class ConfigB {
+
+ @Bean
+ BeanB beanB() {
+ return new BeanB();
+ }
+}
diff --git a/spring2/src/main/java/com/unitbv/multipleConfigs/appConfig/AppConfig.java b/spring2/src/main/java/com/unitbv/multipleConfigs/appConfig/AppConfig.java
new file mode 100644
index 0000000..fc1be07
--- /dev/null
+++ b/spring2/src/main/java/com/unitbv/multipleConfigs/appConfig/AppConfig.java
@@ -0,0 +1,14 @@
+package com.unitbv.multipleConfigs.appConfig;
+
+import com.unitbv.multipleConfigs.ConfigA;
+import com.unitbv.multipleConfigs.ConfigB;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+
+@Configuration
+@Import({ConfigA.class, ConfigB.class})
+@ComponentScan(basePackages = "com.unitbv.multipleConfigs.appConfig")
+public class AppConfig {
+
+}
diff --git a/spring2/src/main/java/com/unitbv/profiles/automatically/AppConfig.java b/spring2/src/main/java/com/unitbv/profiles/automatically/AppConfig.java
new file mode 100644
index 0000000..dc8a476
--- /dev/null
+++ b/spring2/src/main/java/com/unitbv/profiles/automatically/AppConfig.java
@@ -0,0 +1,16 @@
+package com.unitbv.profiles.automatically;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.*;
+
+@Configuration
+@ComponentScan("com.unitbv.profiles.automatically")
+@PropertySource("classpath:profiles.properties")
+public class AppConfig {
+
+ @Bean
+ @Profile("dev")
+ DevDataSourceConfig dataSourceConfig() {
+ return new DevDataSourceConfig();
+ }
+}
diff --git a/spring2/src/main/java/com/unitbv/profiles/automatically/DataSourceConfig.java b/spring2/src/main/java/com/unitbv/profiles/automatically/DataSourceConfig.java
new file mode 100644
index 0000000..5fc4502
--- /dev/null
+++ b/spring2/src/main/java/com/unitbv/profiles/automatically/DataSourceConfig.java
@@ -0,0 +1,5 @@
+package com.unitbv.profiles.automatically;
+
+public interface DataSourceConfig {
+ void setup();
+}
diff --git a/spring2/src/main/java/com/unitbv/profiles/automatically/DevDataSourceConfig.java b/spring2/src/main/java/com/unitbv/profiles/automatically/DevDataSourceConfig.java
new file mode 100644
index 0000000..a456519
--- /dev/null
+++ b/spring2/src/main/java/com/unitbv/profiles/automatically/DevDataSourceConfig.java
@@ -0,0 +1,11 @@
+package com.unitbv.profiles.automatically;
+
+import org.springframework.stereotype.Component;
+
+@Component
+public class DevDataSourceConfig implements DataSourceConfig {
+ @Override
+ public void setup() {
+ System.out.println("Setting up datasource for DEV environment. ");
+ }
+}
diff --git a/spring2/src/main/java/com/unitbv/profiles/automatically/ProdDataSourceConfig.java b/spring2/src/main/java/com/unitbv/profiles/automatically/ProdDataSourceConfig.java
new file mode 100644
index 0000000..f2d415b
--- /dev/null
+++ b/spring2/src/main/java/com/unitbv/profiles/automatically/ProdDataSourceConfig.java
@@ -0,0 +1,13 @@
+package com.unitbv.profiles.automatically;
+
+import org.springframework.context.annotation.Profile;
+import org.springframework.stereotype.Component;
+
+@Component
+@Profile("prod")
+public class ProdDataSourceConfig implements DataSourceConfig {
+ @Override
+ public void setup() {
+ System.out.println("Setting up datasource for PROD environment. ");
+ }
+}
diff --git a/spring2/src/main/java/com/unitbv/profiles/programatically/AppConfig.java b/spring2/src/main/java/com/unitbv/profiles/programatically/AppConfig.java
new file mode 100644
index 0000000..5d8f0f6
--- /dev/null
+++ b/spring2/src/main/java/com/unitbv/profiles/programatically/AppConfig.java
@@ -0,0 +1,26 @@
+package com.unitbv.profiles.programatically;
+
+import org.springframework.context.annotation.*;
+
+@Configuration
+@ComponentScan("com.unitbv.profiles.programatically")
+@PropertySource("classpath:profiles.properties")
+public class AppConfig {
+ @Bean
+ @Profile("dev")
+ DevDataSourceConfig devDataSourceConfig() {
+ return new DevDataSourceConfig();
+ }
+
+ @Bean
+ @Profile("prod")
+ ProdDataSourceConfig prodDataSourceConfig() {
+ return new ProdDataSourceConfig();
+ }
+
+ @Bean
+ @Profile("default")
+ DevDataSourceConfig dataSourceConfig() {
+ return new DevDataSourceConfig();
+ }
+}
diff --git a/spring2/src/main/java/com/unitbv/profiles/programatically/DataSourceConfig.java b/spring2/src/main/java/com/unitbv/profiles/programatically/DataSourceConfig.java
new file mode 100644
index 0000000..898f677
--- /dev/null
+++ b/spring2/src/main/java/com/unitbv/profiles/programatically/DataSourceConfig.java
@@ -0,0 +1,5 @@
+package com.unitbv.profiles.programatically;
+
+public interface DataSourceConfig {
+ public void setup();
+}
diff --git a/spring2/src/main/java/com/unitbv/profiles/programatically/DevDataSourceConfig.java b/spring2/src/main/java/com/unitbv/profiles/programatically/DevDataSourceConfig.java
new file mode 100644
index 0000000..40afff0
--- /dev/null
+++ b/spring2/src/main/java/com/unitbv/profiles/programatically/DevDataSourceConfig.java
@@ -0,0 +1,13 @@
+package com.unitbv.profiles.programatically;
+
+import org.springframework.context.annotation.Profile;
+import org.springframework.stereotype.Component;
+
+@Profile("dev")
+@Component
+public class DevDataSourceConfig implements DataSourceConfig {
+ @Override
+ public void setup() {
+
+ }
+}
diff --git a/spring2/src/main/java/com/unitbv/profiles/programatically/ProdDataSourceConfig.java b/spring2/src/main/java/com/unitbv/profiles/programatically/ProdDataSourceConfig.java
new file mode 100644
index 0000000..16097e7
--- /dev/null
+++ b/spring2/src/main/java/com/unitbv/profiles/programatically/ProdDataSourceConfig.java
@@ -0,0 +1,13 @@
+package com.unitbv.profiles.programatically;
+
+import org.springframework.context.annotation.Profile;
+import org.springframework.stereotype.Component;
+
+@Profile("prod")
+@Component
+public class ProdDataSourceConfig implements DataSourceConfig {
+ @Override
+ public void setup() {
+
+ }
+}
diff --git a/spring2/src/main/java/com/unitbv/profiles/stereotype/AppConfig.java b/spring2/src/main/java/com/unitbv/profiles/stereotype/AppConfig.java
new file mode 100644
index 0000000..6b8d868
--- /dev/null
+++ b/spring2/src/main/java/com/unitbv/profiles/stereotype/AppConfig.java
@@ -0,0 +1,20 @@
+package com.unitbv.profiles.stereotype;
+
+import org.springframework.context.annotation.*;
+
+@Configuration
+@ComponentScan("com.unitbv.profiles.stereotype")
+@PropertySource("classpath:profiles.properties")
+public class AppConfig {
+ @Bean
+ @Profile({"dev", "default"})
+ DevDataSourceConfig devDataSourceConfig() {
+ return new DevDataSourceConfig();
+ }
+
+ @Bean
+ @Profile("prod")
+ ProdDataSourceConfig prodDataSourceConfig() {
+ return new ProdDataSourceConfig();
+ }
+}
diff --git a/spring2/src/main/java/com/unitbv/profiles/stereotype/DataSourceConfig.java b/spring2/src/main/java/com/unitbv/profiles/stereotype/DataSourceConfig.java
new file mode 100644
index 0000000..c620bf5
--- /dev/null
+++ b/spring2/src/main/java/com/unitbv/profiles/stereotype/DataSourceConfig.java
@@ -0,0 +1,5 @@
+package com.unitbv.profiles.stereotype;
+
+public interface DataSourceConfig {
+ public void setup();
+}
diff --git a/spring2/src/main/java/com/unitbv/profiles/stereotype/DevDataSourceConfig.java b/spring2/src/main/java/com/unitbv/profiles/stereotype/DevDataSourceConfig.java
new file mode 100644
index 0000000..bc28c29
--- /dev/null
+++ b/spring2/src/main/java/com/unitbv/profiles/stereotype/DevDataSourceConfig.java
@@ -0,0 +1,8 @@
+package com.unitbv.profiles.stereotype;
+
+public class DevDataSourceConfig implements DataSourceConfig {
+ @Override
+ public void setup() {
+
+ }
+}
diff --git a/spring2/src/main/java/com/unitbv/profiles/stereotype/ProdDataSourceConfig.java b/spring2/src/main/java/com/unitbv/profiles/stereotype/ProdDataSourceConfig.java
new file mode 100644
index 0000000..0ceec4b
--- /dev/null
+++ b/spring2/src/main/java/com/unitbv/profiles/stereotype/ProdDataSourceConfig.java
@@ -0,0 +1,8 @@
+package com.unitbv.profiles.stereotype;
+
+public class ProdDataSourceConfig implements DataSourceConfig {
+ @Override
+ public void setup() {
+
+ }
+}
diff --git a/spring2/src/main/java/com/unitbv/properties/config/AppConfig.java b/spring2/src/main/java/com/unitbv/properties/config/AppConfig.java
new file mode 100644
index 0000000..9325921
--- /dev/null
+++ b/spring2/src/main/java/com/unitbv/properties/config/AppConfig.java
@@ -0,0 +1,22 @@
+package com.unitbv.properties.config;
+
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.PropertySource;
+
+@Configuration
+@PropertySource("classpath:application.properties")
+@RequiredArgsConstructor
+
+public class AppConfig {
+ @Value("${model}")
+ private String model;
+
+ @Bean
+ Car car() {
+ return new Car(model);
+ }
+
+}
diff --git a/spring2/src/main/java/com/unitbv/properties/config/Car.java b/spring2/src/main/java/com/unitbv/properties/config/Car.java
new file mode 100644
index 0000000..a03a82b
--- /dev/null
+++ b/spring2/src/main/java/com/unitbv/properties/config/Car.java
@@ -0,0 +1,11 @@
+package com.unitbv.properties.config;
+
+import lombok.Getter;
+@Getter
+public class Car {
+ private String model;
+
+ public Car(String model) {
+ this.model = model;
+ }
+}
diff --git a/spring2/src/main/java/com/unitbv/properties/programatically/AppConfig.java b/spring2/src/main/java/com/unitbv/properties/programatically/AppConfig.java
new file mode 100644
index 0000000..3c0718d
--- /dev/null
+++ b/spring2/src/main/java/com/unitbv/properties/programatically/AppConfig.java
@@ -0,0 +1,32 @@
+package com.unitbv.properties.programatically;
+
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+
+@Configuration
+@RequiredArgsConstructor
+
+public class AppConfig {
+ @Value("${model}")
+ private String model;
+
+ @Bean
+ Car car() {
+ return new Car(model);
+ }
+
+ @Bean
+ public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
+ PropertySourcesPlaceholderConfigurer pspc = new PropertySourcesPlaceholderConfigurer();
+ Resource[] resources = new ClassPathResource[]
+ {new ClassPathResource("application.properties")};
+ pspc.setLocations(resources);
+ pspc.setIgnoreUnresolvablePlaceholders(true);
+ return pspc;
+ }
+}
\ No newline at end of file
diff --git a/spring2/src/main/java/com/unitbv/properties/programatically/Car.java b/spring2/src/main/java/com/unitbv/properties/programatically/Car.java
new file mode 100644
index 0000000..0a11aad
--- /dev/null
+++ b/spring2/src/main/java/com/unitbv/properties/programatically/Car.java
@@ -0,0 +1,10 @@
+package com.unitbv.properties.programatically;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+@Getter
+@RequiredArgsConstructor
+public class Car {
+ private final String model;
+}
diff --git a/spring2/src/main/java/com/unitbv/properties/stereotype/AppConfig.java b/spring2/src/main/java/com/unitbv/properties/stereotype/AppConfig.java
new file mode 100644
index 0000000..dade386
--- /dev/null
+++ b/spring2/src/main/java/com/unitbv/properties/stereotype/AppConfig.java
@@ -0,0 +1,19 @@
+package com.unitbv.properties.stereotype;
+
+import lombok.RequiredArgsConstructor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.PropertySource;
+
+@Configuration
+@RequiredArgsConstructor
+@ComponentScan
+@PropertySource("classpath:application.properties")
+public class AppConfig {
+
+ @Bean
+ Car car() {
+ return new Car();
+ }
+}
diff --git a/spring2/src/main/java/com/unitbv/properties/stereotype/Car.java b/spring2/src/main/java/com/unitbv/properties/stereotype/Car.java
new file mode 100644
index 0000000..a0fcc57
--- /dev/null
+++ b/spring2/src/main/java/com/unitbv/properties/stereotype/Car.java
@@ -0,0 +1,11 @@
+package com.unitbv.properties.stereotype;
+
+import lombok.Getter;
+import org.springframework.beans.factory.annotation.Value;
+
+@Getter
+public class Car {
+ @Value("${model}")
+ private String model;
+
+}
\ No newline at end of file
diff --git a/spring2/src/main/resources/application.properties b/spring2/src/main/resources/application.properties
new file mode 100644
index 0000000..425902a
--- /dev/null
+++ b/spring2/src/main/resources/application.properties
@@ -0,0 +1 @@
+model=Audi
\ No newline at end of file
diff --git a/spring2/src/main/resources/profiles.properties b/spring2/src/main/resources/profiles.properties
new file mode 100644
index 0000000..ddd90bb
--- /dev/null
+++ b/spring2/src/main/resources/profiles.properties
@@ -0,0 +1 @@
+spring.profile.active=dev
\ No newline at end of file
diff --git a/spring2/src/test/java/com/unitbv/dependsOn/DependsOnTest.java b/spring2/src/test/java/com/unitbv/dependsOn/DependsOnTest.java
new file mode 100644
index 0000000..eddf941
--- /dev/null
+++ b/spring2/src/test/java/com/unitbv/dependsOn/DependsOnTest.java
@@ -0,0 +1,27 @@
+package com.unitbv.dependsOn;
+
+
+import org.junit.Test;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+public class DependsOnTest {
+ // TODO: create 3 beans: BeanA, BeanB and BeanC and make them depending on each other like:
+ // BeanA depends on BeanB and BeanB depends on BeanC
+ // use configuration class to declare beans
+ @Test
+ public void test() {
+ AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
+
+ BeanA beanA = context.getBean("beanA", BeanA.class);
+ BeanB beanB = context.getBean("beanB", BeanB.class);
+ BeanC beanC = context.getBean("beanC", BeanC.class);
+
+ assertNotNull(beanA);
+ assertNotNull(beanB);
+ assertNotNull(beanC);
+ context.close();
+
+ }
+}
diff --git a/spring2/src/test/java/com/unitbv/events/SpringEventsTest.java b/spring2/src/test/java/com/unitbv/events/SpringEventsTest.java
new file mode 100644
index 0000000..0bdff53
--- /dev/null
+++ b/spring2/src/test/java/com/unitbv/events/SpringEventsTest.java
@@ -0,0 +1,25 @@
+package com.unitbv.events;
+
+import com.unitbv.events.configuration.AppConfig;
+import com.unitbv.events.service.CarService;
+import com.unitbv.events.service.PersonService;
+import org.junit.Test;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class SpringEventsTest {
+
+ // Publish an event on PersonService that will be consumed in CarService
+ @Test
+ public void test() {
+ AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
+
+ final PersonService personService = context.getBean(PersonService.class);
+ personService.rentCar("Audi");
+
+ final CarService carService = context.getBean(CarService.class);
+
+ assertEquals(carService.getAvailableCars().size(), 1);
+
+ }
+}
diff --git a/spring2/src/test/java/com/unitbv/multipleConfigs/MultipleConfigsTest.java b/spring2/src/test/java/com/unitbv/multipleConfigs/MultipleConfigsTest.java
new file mode 100644
index 0000000..df3e980
--- /dev/null
+++ b/spring2/src/test/java/com/unitbv/multipleConfigs/MultipleConfigsTest.java
@@ -0,0 +1,25 @@
+package com.unitbv.multipleConfigs;
+
+
+import com.unitbv.multipleConfigs.appConfig.AppConfig;
+import org.junit.Test;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+public class MultipleConfigsTest {
+ // TODO: create 2 classes: BeanA, BeanB and declare them as beans in 2 config class; use both of them in AppConfig class
+ @Test
+ public void test() {
+ AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
+
+ BeanA beanA = context.getBean("beanA", BeanA.class);
+ BeanB beanB = context.getBean("beanB", BeanB.class);
+
+ assertNotNull(beanA);
+ assertNotNull(beanB);
+
+ context.close();
+
+ }
+}
diff --git a/spring2/src/test/java/com/unitbv/profiles/automatically/ProfilesTest.java b/spring2/src/test/java/com/unitbv/profiles/automatically/ProfilesTest.java
new file mode 100644
index 0000000..73123c0
--- /dev/null
+++ b/spring2/src/test/java/com/unitbv/profiles/automatically/ProfilesTest.java
@@ -0,0 +1,27 @@
+package com.unitbv.profiles.automatically;
+
+import org.junit.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+
+@ExtendWith(SpringExtension.class)
+@ContextConfiguration(classes = AppConfig.class)
+@RunWith(SpringRunner.class)
+public class ProfilesTest {
+
+ @Autowired
+ DataSourceConfig dataSourceConfig;
+
+ // set dev as active profile in profile.properties file; use this file in AppConfig;
+ @Test
+ public void test() {
+ assertInstanceOf(DevDataSourceConfig.class, dataSourceConfig);
+
+ }
+}
diff --git a/spring2/src/test/java/com/unitbv/profiles/programatically/ProfilesTest.java b/spring2/src/test/java/com/unitbv/profiles/programatically/ProfilesTest.java
new file mode 100644
index 0000000..a38c787
--- /dev/null
+++ b/spring2/src/test/java/com/unitbv/profiles/programatically/ProfilesTest.java
@@ -0,0 +1,39 @@
+package com.unitbv.profiles.programatically;
+
+
+import org.junit.Test;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+
+//TODO: define 3 beans in AppConfig, one for each profile: dev, default, prod
+public class ProfilesTest {
+ @Test
+ public void devProfile() {
+ AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
+ ctx.getEnvironment().setActiveProfiles("dev");
+ ctx.register(AppConfig.class);
+ ctx.refresh();
+ assertInstanceOf(DevDataSourceConfig.class, ctx.getBean(DataSourceConfig.class));
+ }
+
+ @Test
+ public void prodProfile() {
+ AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
+ ctx.getEnvironment().setActiveProfiles("prod");
+ ctx.register(AppConfig.class);
+ ctx.refresh();
+
+ assertInstanceOf(ProdDataSourceConfig.class, ctx.getBean(DataSourceConfig.class));
+ }
+
+ @Test
+ public void defaultProfile() {
+ AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
+ ctx.register(AppConfig.class);
+ ctx.refresh();
+
+ assertInstanceOf(DevDataSourceConfig.class, ctx.getBean(DataSourceConfig.class));
+ }
+
+}
diff --git a/spring2/src/test/java/com/unitbv/profiles/stereotype/ProfilesTest.java b/spring2/src/test/java/com/unitbv/profiles/stereotype/ProfilesTest.java
new file mode 100644
index 0000000..0296057
--- /dev/null
+++ b/spring2/src/test/java/com/unitbv/profiles/stereotype/ProfilesTest.java
@@ -0,0 +1,42 @@
+package com.unitbv.profiles.stereotype;
+
+import com.unitbv.profiles.programatically.AppConfig;
+import com.unitbv.profiles.programatically.DataSourceConfig;
+import com.unitbv.profiles.programatically.DevDataSourceConfig;
+import com.unitbv.profiles.programatically.ProdDataSourceConfig;
+import org.junit.Test;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+
+//TODO define DevDataSourceConfig and ProdDataSourceConfig as beans and set profiles: dev and default for DevDataSourceConfig and prod for ProdDataSourceConfig
+public class ProfilesTest {
+ @Test
+ public void devProfile() {
+ AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
+ ctx.getEnvironment().setActiveProfiles("dev");
+ ctx.register(com.unitbv.profiles.programatically.AppConfig.class);
+ ctx.refresh();
+ assertInstanceOf(DevDataSourceConfig.class, ctx.getBean(DataSourceConfig.class));
+ }
+
+ @Test
+ public void prodProfile() {
+ AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
+ ctx.getEnvironment().setActiveProfiles("prod");
+ ctx.register(com.unitbv.profiles.programatically.AppConfig.class);
+ ctx.refresh();
+
+ assertInstanceOf(ProdDataSourceConfig.class, ctx.getBean(com.unitbv.profiles.programatically.DataSourceConfig.class));
+ }
+
+ @Test
+ public void defaultProfile() {
+ AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
+ ctx.register(AppConfig.class);
+ ctx.refresh();
+
+ assertInstanceOf(DevDataSourceConfig.class, ctx.getBean(DataSourceConfig.class));
+ }
+
+}
diff --git a/spring2/src/test/java/com/unitbv/properties/config/PropertiesConfigTest.java b/spring2/src/test/java/com/unitbv/properties/config/PropertiesConfigTest.java
new file mode 100644
index 0000000..666cbc0
--- /dev/null
+++ b/spring2/src/test/java/com/unitbv/properties/config/PropertiesConfigTest.java
@@ -0,0 +1,17 @@
+package com.unitbv.properties.config;
+
+import org.junit.Test;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class PropertiesConfigTest {
+ // Declare Car as bean in AppConfig; read model value from application.properties file
+ @Test
+ public void test() {
+ AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
+ final Car car = ctx.getBean(Car.class);
+ assertEquals(car.getModel(), "Audi");
+
+ }
+}
diff --git a/spring2/src/test/java/com/unitbv/properties/programatically/PropertiesProgramTest.java b/spring2/src/test/java/com/unitbv/properties/programatically/PropertiesProgramTest.java
new file mode 100644
index 0000000..7003dc2
--- /dev/null
+++ b/spring2/src/test/java/com/unitbv/properties/programatically/PropertiesProgramTest.java
@@ -0,0 +1,19 @@
+package com.unitbv.properties.programatically;
+
+import org.junit.Test;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class PropertiesProgramTest {
+ //TODO: define Car bean and PropertySourcesPlaceholderConfigurer bean in App config and read model value from application.properties file using PropertySourcesPlaceholderConfigurer; DO NOT USE PropertySource annotation
+ @Test
+ public void test() {
+ AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
+
+ final Car car = ctx.getBean(Car.class);
+
+ assertEquals(car.getModel(), "Audi");
+
+ }
+}
diff --git a/spring2/src/test/java/com/unitbv/properties/stereotype/PropertiesStereotypeTest.java b/spring2/src/test/java/com/unitbv/properties/stereotype/PropertiesStereotypeTest.java
new file mode 100644
index 0000000..244c6f2
--- /dev/null
+++ b/spring2/src/test/java/com/unitbv/properties/stereotype/PropertiesStereotypeTest.java
@@ -0,0 +1,18 @@
+package com.unitbv.properties.stereotype;
+
+
+import org.junit.Test;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class PropertiesStereotypeTest {
+ //TODO: define Car as a bean and read model directly in Car.class
+ @Test
+ public void test() {
+ AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
+ final Car car = ctx.getBean(Car.class);
+ assertEquals(car.getModel(), "Audi");
+
+ }
+}