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 predicate){ + public List filterUsers(Predicate predicate) { return users.stream() .filter(predicate) .collect(Collectors.toList()); } // Sort users using the given Comparator - public List sortUsers(Comparator comparator){ + public List sortUsers(Comparator 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 @@ java8 rest-service + spring1 + spring2 + eureka + + org.springframework + spring-context + 5.3.15 + org.junit.jupiter junit-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 users) { + + } + + @Override + public void deleteAll(Iterable 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"); + + } +}