Merge branch 'master' into master
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
|
||||
<modules>
|
||||
<module>spring-boot</module>
|
||||
<module>spring-boot-1</module>
|
||||
<module>spring-boot-admin</module>
|
||||
<module>spring-boot-angular</module>
|
||||
<module>spring-boot-annotations</module>
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.2/apache-maven-3.5.2-bin.zip
|
||||
@@ -0,0 +1,6 @@
|
||||
## Spring Boot 1.x Actuator
|
||||
|
||||
This module contains articles about Spring Boot Actuator in Spring Boot version 1.x.
|
||||
|
||||
## Relevant articles:
|
||||
- [Spring Boot Actuator](https://www.baeldung.com/spring-boot-actuators)
|
||||
+234
@@ -0,0 +1,234 @@
|
||||
#!/bin/sh
|
||||
# ----------------------------------------------------------------------------
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Maven2 Start Up Batch script
|
||||
#
|
||||
# Required ENV vars:
|
||||
# ------------------
|
||||
# JAVA_HOME - location of a JDK home dir
|
||||
#
|
||||
# Optional ENV vars
|
||||
# -----------------
|
||||
# M2_HOME - location of maven2's installed home dir
|
||||
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
# e.g. to debug Maven itself, use
|
||||
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
if [ -z "$MAVEN_SKIP_RC" ]; then
|
||||
|
||||
if [ -f /etc/mavenrc ]; then
|
||||
. /etc/mavenrc
|
||||
fi
|
||||
|
||||
if [ -f "$HOME/.mavenrc" ]; then
|
||||
. "$HOME/.mavenrc"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
# OS specific support. $var _must_ be set to either true or false.
|
||||
cygwin=false
|
||||
darwin=false
|
||||
mingw=false
|
||||
case "$(uname)" in
|
||||
CYGWIN*) cygwin=true ;;
|
||||
MINGW*) mingw=true ;;
|
||||
Darwin*)
|
||||
darwin=true
|
||||
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
|
||||
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
if [ -x "/usr/libexec/java_home" ]; then
|
||||
export JAVA_HOME="$(/usr/libexec/java_home)"
|
||||
else
|
||||
export JAVA_HOME="/Library/Java/Home"
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
if [ -r /etc/gentoo-release ]; then
|
||||
JAVA_HOME=$(java-config --jre-home)
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$M2_HOME" ]; then
|
||||
## resolve links - $0 may be a link to maven's home
|
||||
PRG="$0"
|
||||
|
||||
# need this for relative symlinks
|
||||
while [ -h "$PRG" ]; do
|
||||
ls=$(ls -ld "$PRG")
|
||||
link=$(expr "$ls" : '.*-> \(.*\)$')
|
||||
if expr "$link" : '/.*' >/dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG="$(dirname "$PRG")/$link"
|
||||
fi
|
||||
done
|
||||
|
||||
saveddir=$(pwd)
|
||||
|
||||
M2_HOME=$(dirname "$PRG")/..
|
||||
|
||||
# make it fully qualified
|
||||
M2_HOME=$(cd "$M2_HOME" && pwd)
|
||||
|
||||
cd "$saveddir"
|
||||
# echo Using m2 at $M2_HOME
|
||||
fi
|
||||
|
||||
# For Cygwin, ensure paths are in UNIX format before anything is touched
|
||||
if $cygwin; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME=$(cygpath --unix "$M2_HOME")
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
|
||||
[ -n "$CLASSPATH" ] &&
|
||||
CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
|
||||
fi
|
||||
|
||||
# For Migwn, 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
|
||||
))"
|
||||
# TODO classpath?
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
javaExecutable="$(which javac)"
|
||||
if [ -n "$javaExecutable" ] && ! [ "$(expr \"$javaExecutable\" : '\([^ ]*\)')" = "no" ]; then
|
||||
# readlink(1) is not available as standard on Solaris 10.
|
||||
readLink=$(which readlink)
|
||||
if [ ! $(expr "$readLink" : '\([^ ]*\)') = "no" ]; then
|
||||
if $darwin; then
|
||||
javaHome="$(dirname \"$javaExecutable\")"
|
||||
javaExecutable="$(cd \"$javaHome\" && pwd -P)/javac"
|
||||
else
|
||||
javaExecutable="$(readlink -f \"$javaExecutable\")"
|
||||
fi
|
||||
javaHome="$(dirname \"$javaExecutable\")"
|
||||
javaHome=$(expr "$javaHome" : '\(.*\)/bin')
|
||||
JAVA_HOME="$javaHome"
|
||||
export JAVA_HOME
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$JAVACMD" ]; then
|
||||
if [ -n "$JAVA_HOME" ]; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ]; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
else
|
||||
JAVACMD="$(which java)"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -x "$JAVACMD" ]; then
|
||||
echo "Error: JAVA_HOME is not defined correctly." >&2
|
||||
echo " We cannot execute $JAVACMD" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
echo "Warning: JAVA_HOME environment variable is not set."
|
||||
fi
|
||||
|
||||
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
|
||||
|
||||
# traverses directory structure from process work directory to filesystem root
|
||||
# first directory with .mvn subdirectory is considered project base directory
|
||||
find_maven_basedir() {
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
echo "Path not specified to find_maven_basedir"
|
||||
return 1
|
||||
fi
|
||||
|
||||
basedir="$1"
|
||||
wdir="$1"
|
||||
while [ "$wdir" != '/' ]; do
|
||||
if [ -d "$wdir"/.mvn ]; then
|
||||
basedir=$wdir
|
||||
break
|
||||
fi
|
||||
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
|
||||
if [ -d "${wdir}" ]; then
|
||||
wdir=$(
|
||||
cd "$wdir/.."
|
||||
pwd
|
||||
)
|
||||
fi
|
||||
# end of workaround
|
||||
done
|
||||
echo "${basedir}"
|
||||
}
|
||||
|
||||
# concatenates all lines of a file
|
||||
concat_lines() {
|
||||
if [ -f "$1" ]; then
|
||||
echo "$(tr -s '\n' ' ' <"$1")"
|
||||
fi
|
||||
}
|
||||
|
||||
BASE_DIR=$(find_maven_basedir "$(pwd)")
|
||||
if [ -z "$BASE_DIR" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
|
||||
echo $MAVEN_PROJECTBASEDIR
|
||||
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
|
||||
|
||||
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
exec "$JAVACMD" \
|
||||
$MAVEN_OPTS \
|
||||
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
|
||||
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
|
||||
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
|
||||
+143
@@ -0,0 +1,143 @@
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Licensed to the Apache Software Foundation (ASF) under one
|
||||
@REM or more contributor license agreements. See the NOTICE file
|
||||
@REM distributed with this work for additional information
|
||||
@REM regarding copyright ownership. The ASF licenses this file
|
||||
@REM to you under the Apache License, Version 2.0 (the
|
||||
@REM "License"); you may not use this file except in compliance
|
||||
@REM with the License. You may obtain a copy of the License at
|
||||
@REM
|
||||
@REM http://www.apache.org/licenses/LICENSE-2.0
|
||||
@REM
|
||||
@REM Unless required by applicable law or agreed to in writing,
|
||||
@REM software distributed under the License is distributed on an
|
||||
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
@REM KIND, either express or implied. See the License for the
|
||||
@REM specific language governing permissions and limitations
|
||||
@REM under the License.
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Maven2 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 key stroke 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 enable echoing my setting MAVEN_BATCH_ECHO to 'on'
|
||||
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
|
||||
|
||||
@REM set %HOME% to equivalent of $HOME
|
||||
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
|
||||
|
||||
@REM Execute a user defined script before this one
|
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
|
||||
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
|
||||
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
|
||||
:skipRcPre
|
||||
|
||||
@setlocal
|
||||
|
||||
set ERROR_CODE=0
|
||||
|
||||
@REM To isolate internal variables from possible post scripts, we use another setlocal
|
||||
@setlocal
|
||||
|
||||
@REM ==== START VALIDATION ====
|
||||
if not "%JAVA_HOME%" == "" goto OkJHome
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME not found in your environment. >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
:OkJHome
|
||||
if exist "%JAVA_HOME%\bin\java.exe" goto init
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME is set to an invalid directory. >&2
|
||||
echo JAVA_HOME = "%JAVA_HOME%" >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
@REM ==== END VALIDATION ====
|
||||
|
||||
:init
|
||||
|
||||
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
|
||||
@REM Fallback to current working directory if not found.
|
||||
|
||||
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
|
||||
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
|
||||
|
||||
set EXEC_DIR=%CD%
|
||||
set WDIR=%EXEC_DIR%
|
||||
:findBaseDir
|
||||
IF EXIST "%WDIR%"\.mvn goto baseDirFound
|
||||
cd ..
|
||||
IF "%WDIR%"=="%CD%" goto baseDirNotFound
|
||||
set WDIR=%CD%
|
||||
goto findBaseDir
|
||||
|
||||
:baseDirFound
|
||||
set MAVEN_PROJECTBASEDIR=%WDIR%
|
||||
cd "%EXEC_DIR%"
|
||||
goto endDetectBaseDir
|
||||
|
||||
:baseDirNotFound
|
||||
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
|
||||
cd "%EXEC_DIR%"
|
||||
|
||||
:endDetectBaseDir
|
||||
|
||||
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
|
||||
|
||||
@setlocal EnableExtensions EnableDelayedExpansion
|
||||
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
|
||||
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
|
||||
|
||||
:endReadAdditionalConfig
|
||||
|
||||
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
|
||||
|
||||
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
|
||||
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
|
||||
if ERRORLEVEL 1 goto error
|
||||
goto end
|
||||
|
||||
:error
|
||||
set ERROR_CODE=1
|
||||
|
||||
:end
|
||||
@endlocal & set ERROR_CODE=%ERROR_CODE%
|
||||
|
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
|
||||
@REM check for post script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
|
||||
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
|
||||
:skipRcPost
|
||||
|
||||
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
|
||||
if "%MAVEN_BATCH_PAUSE%" == "on" pause
|
||||
|
||||
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
|
||||
|
||||
exit /B %ERROR_CODE%
|
||||
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>spring-boot-1</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<description>Module for Spring Boot version 1.x</description>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-boot-1</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../../parent-boot-1</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
package com.baeldung.actuator;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class CustomEndpoint implements Endpoint<List<String>> {
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "customEndpoint";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSensitive() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> invoke() {
|
||||
// Custom logic to build the output
|
||||
List<String> messages = new ArrayList<>();
|
||||
messages.add("This is message 1");
|
||||
messages.add("This is message 2");
|
||||
return messages;
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package com.baeldung.actuator;
|
||||
|
||||
import org.springframework.boot.actuate.health.Health;
|
||||
import org.springframework.boot.actuate.health.HealthIndicator;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component("myHealthCheck")
|
||||
public class HealthCheck implements HealthIndicator {
|
||||
|
||||
@Override
|
||||
public Health health() {
|
||||
int errorCode = check(); // perform some specific health check
|
||||
if (errorCode != 0) {
|
||||
return Health.down().withDetail("Error Code", errorCode).build();
|
||||
}
|
||||
return Health.up().build();
|
||||
}
|
||||
|
||||
public int check() {
|
||||
// Our logic to check health
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package com.baeldung.actuator;
|
||||
|
||||
import org.springframework.boot.actuate.metrics.CounterService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@Service
|
||||
public class LoginServiceImpl {
|
||||
|
||||
private final CounterService counterService;
|
||||
|
||||
public LoginServiceImpl(CounterService counterService) {
|
||||
this.counterService = counterService;
|
||||
}
|
||||
|
||||
public boolean login(String userName, char[] password) {
|
||||
boolean success;
|
||||
if (userName.equals("admin") && Arrays.equals("secret".toCharArray(), password)) {
|
||||
counterService.increment("counter.login.success");
|
||||
success = true;
|
||||
} else {
|
||||
counterService.increment("counter.login.failure");
|
||||
success = false;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.baeldung.actuator;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class SpringBoot {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SpringBoot.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
### server port
|
||||
server.port=8080
|
||||
#port used to expose actuator
|
||||
management.port=8081
|
||||
#CIDR allowed to hit actuator
|
||||
management.address=127.0.0.1
|
||||
# Actuator Configuration
|
||||
# customize /beans endpoint
|
||||
endpoints.beans.id=springbeans
|
||||
endpoints.beans.sensitive=false
|
||||
endpoints.beans.enabled=true
|
||||
# for the Spring Boot version 1.5.0 and above, we have to disable security to expose the health endpoint fully for unauthorized access.
|
||||
# see: https://docs.spring.io/spring-boot/docs/1.5.x/reference/html/production-ready-monitoring.html
|
||||
management.security.enabled=false
|
||||
endpoints.health.sensitive=false
|
||||
# customize /info endpoint
|
||||
info.app.name=Spring Sample Application
|
||||
info.app.description=This is my first spring boot application
|
||||
info.app.version=1.0.0
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
package com.baeldung.actuator;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.actuate.autoconfigure.LocalManagementPort;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.hasItems;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = "management.port=0")
|
||||
public class CustomEndpointIntegrationTest {
|
||||
|
||||
@LocalManagementPort
|
||||
private int port;
|
||||
|
||||
private RestTemplate restTemplate = new RestTemplate();
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@Test
|
||||
public void whenSpringContextIsBootstrapped_thenActuatorCustomEndpointWorks() throws IOException {
|
||||
ResponseEntity<String> entity = restTemplate.getForEntity("http://localhost:" + port + "/customEndpoint", String.class);
|
||||
|
||||
assertThat(entity.getStatusCode(), is(HttpStatus.OK));
|
||||
|
||||
List<String> response = objectMapper.readValue(entity.getBody(), new TypeReference<ArrayList<String>>() {
|
||||
});
|
||||
|
||||
assertThat(response, hasItems("This is message 1", "This is message 2"));
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
package com.baeldung.actuator;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.actuate.autoconfigure.LocalManagementPort;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.collection.IsMapContaining.hasEntry;
|
||||
import static org.hamcrest.collection.IsMapContaining.hasKey;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = "management.port=0")
|
||||
public class HealthCheckIntegrationTest {
|
||||
|
||||
@LocalManagementPort
|
||||
private int port;
|
||||
|
||||
private RestTemplate restTemplate = new RestTemplate();
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@Test
|
||||
public void whenSpringContextIsBootstrapped_thenActuatorHealthEndpointWorks() throws IOException {
|
||||
ResponseEntity<String> entity = restTemplate.getForEntity("http://localhost:" + port + "/health", String.class);
|
||||
|
||||
assertThat(entity.getStatusCode(), is(HttpStatus.OK));
|
||||
|
||||
Map<String, Object> response = objectMapper.readValue(entity.getBody(), new TypeReference<LinkedHashMap<String, Object>>() {
|
||||
});
|
||||
|
||||
assertThat(response, hasEntry("status", "UP"));
|
||||
assertThat(response, hasKey("myHealthCheck"));
|
||||
assertThat(response, hasKey("diskSpace"));
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
package com.baeldung.actuator;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.boot.actuate.health.Health;
|
||||
import org.springframework.boot.actuate.health.Status;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class HealthCheckUnitTest {
|
||||
|
||||
@Test
|
||||
public void whenCheckMethodReturnsZero_thenHealthMethodReturnsStatusUP() {
|
||||
HealthCheck healthCheck = Mockito.spy(new HealthCheck());
|
||||
when(healthCheck.check()).thenReturn(0);
|
||||
Health health = healthCheck.health();
|
||||
|
||||
assertThat(health.getStatus(), is(Status.UP));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenCheckMethodReturnsOtherThanZero_thenHealthMethodReturnsStatusDOWN() {
|
||||
HealthCheck healthCheck = Mockito.spy(new HealthCheck());
|
||||
when(healthCheck.check()).thenReturn(-1);
|
||||
Health health = healthCheck.health();
|
||||
|
||||
assertThat(health.getStatus(), is(Status.DOWN));
|
||||
}
|
||||
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
package com.baeldung.actuator;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.actuate.autoconfigure.LocalManagementPort;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.hasEntry;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = "management.port=0")
|
||||
public class LoginServiceIntegrationTest {
|
||||
|
||||
@LocalManagementPort
|
||||
private int port;
|
||||
|
||||
@Autowired
|
||||
private LoginServiceImpl loginService;
|
||||
|
||||
private RestTemplate restTemplate = new RestTemplate();
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@Test
|
||||
public void whenLoginIsAdmin_thenSuccessCounterIsIncremented() throws IOException {
|
||||
boolean success = loginService.login("admin", "secret".toCharArray());
|
||||
ResponseEntity<String> entity = restTemplate.getForEntity("http://localhost:" + port + "/metrics", String.class);
|
||||
Map<String, Object> response = objectMapper.readValue(entity.getBody(), new TypeReference<HashMap<String, Object>>() {
|
||||
});
|
||||
|
||||
assertThat(success, is(true));
|
||||
assertThat(entity.getStatusCode(), is(HttpStatus.OK));
|
||||
assertThat(response, hasEntry("counter.login.success", 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenLoginIsNotAdmin_thenFailureCounterIsIncremented() throws IOException {
|
||||
boolean success = loginService.login("user", "notsecret".toCharArray());
|
||||
ResponseEntity<String> entity = restTemplate.getForEntity("http://localhost:" + port + "/metrics", String.class);
|
||||
Map<String, Object> response = objectMapper.readValue(entity.getBody(), new TypeReference<HashMap<String, Object>>() {
|
||||
});
|
||||
|
||||
assertThat(success, is(false));
|
||||
assertThat(entity.getStatusCode(), is(HttpStatus.OK));
|
||||
assertThat(response, hasEntry("counter.login.failure", 1));
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package com.baeldung.actuator;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.actuate.metrics.CounterService;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = LoginServiceImpl.class)
|
||||
public class LoginServiceUnitTest {
|
||||
|
||||
@MockBean
|
||||
CounterService counterService;
|
||||
|
||||
@Autowired
|
||||
LoginServiceImpl loginService;
|
||||
|
||||
@Test
|
||||
public void whenLoginUserIsAdmin_thenSuccessCounterIsIncremented() {
|
||||
boolean loginResult = loginService.login("admin", "secret".toCharArray());
|
||||
assertThat(loginResult, is(true));
|
||||
verify(counterService, times(1)).increment("counter.login.success");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenLoginUserIsNotAdmin_thenFailureCounterIsIncremented() {
|
||||
boolean loginResult = loginService.login("user", "notsecret".toCharArray());
|
||||
assertThat(loginResult, is(false));
|
||||
verify(counterService, times(1)).increment("counter.login.failure");
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -36,7 +36,7 @@ public class UserController {
|
||||
|
||||
userRepository.save(user);
|
||||
model.addAttribute("users", userRepository.findAll());
|
||||
return "index";
|
||||
return "redirect:/index";
|
||||
}
|
||||
|
||||
@GetMapping("/edit/{id}")
|
||||
@@ -55,7 +55,7 @@ public class UserController {
|
||||
|
||||
userRepository.save(user);
|
||||
model.addAttribute("users", userRepository.findAll());
|
||||
return "index";
|
||||
return "redirect:/index";
|
||||
}
|
||||
|
||||
@GetMapping("/delete/{id}")
|
||||
|
||||
+2
-2
@@ -41,7 +41,7 @@ public class UserControllerUnitTest {
|
||||
|
||||
when(mockedBindingResult.hasErrors()).thenReturn(false);
|
||||
|
||||
assertThat(userController.addUser(user, mockedBindingResult, mockedModel)).isEqualTo("index");
|
||||
assertThat(userController.addUser(user, mockedBindingResult, mockedModel)).isEqualTo("redirect:/index");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -64,7 +64,7 @@ public class UserControllerUnitTest {
|
||||
|
||||
when(mockedBindingResult.hasErrors()).thenReturn(false);
|
||||
|
||||
assertThat(userController.updateUser(1l, user, mockedBindingResult, mockedModel)).isEqualTo("index");
|
||||
assertThat(userController.updateUser(1l, user, mockedBindingResult, mockedModel)).isEqualTo("redirect:/index");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -41,10 +41,6 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.bytebuddy</groupId>
|
||||
<artifactId>byte-buddy</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
|
||||
@@ -14,38 +14,6 @@
|
||||
<relativePath>../../parent-kotlin</relativePath>
|
||||
</parent>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-snapshots</id>
|
||||
<name>Spring Snapshots</name>
|
||||
<url>https://repo.spring.io/snapshot</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>spring-milestones</id>
|
||||
<name>Spring Milestones</name>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>spring-snapshots</id>
|
||||
<name>Spring Snapshots</name>
|
||||
<url>https://repo.spring.io/snapshot</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</pluginRepository>
|
||||
<pluginRepository>
|
||||
<id>spring-milestones</id>
|
||||
<name>Spring Milestones</name>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
@@ -142,9 +110,9 @@
|
||||
|
||||
<properties>
|
||||
<kotlin.version>1.3.31</kotlin.version>
|
||||
<r2dbc.version>1.0.0.M1</r2dbc.version>
|
||||
<r2dbc-spi.version>1.0.0.M7</r2dbc-spi.version>
|
||||
<h2-r2dbc.version>1.0.0.BUILD-SNAPSHOT</h2-r2dbc.version>
|
||||
<r2dbc.version>1.0.0.RELEASE</r2dbc.version>
|
||||
<r2dbc-spi.version>0.8.2.RELEASE</r2dbc-spi.version>
|
||||
<h2-r2dbc.version>0.8.4.RELEASE</h2-r2dbc.version>
|
||||
<kotlinx-coroutines.version>1.2.1</kotlinx-coroutines.version>
|
||||
</properties>
|
||||
|
||||
|
||||
+3
-5
@@ -2,12 +2,11 @@ package com.baeldung.nonblockingcoroutines.controller
|
||||
|
||||
import com.baeldung.nonblockingcoroutines.model.Product
|
||||
import com.baeldung.nonblockingcoroutines.repository.ProductRepositoryCoroutines
|
||||
import kotlinx.coroutines.CoroutineStart
|
||||
import kotlinx.coroutines.Deferred
|
||||
import kotlinx.coroutines.FlowPreview
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.CoroutineStart
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.http.MediaType.APPLICATION_JSON
|
||||
@@ -15,7 +14,6 @@ import org.springframework.web.bind.annotation.GetMapping
|
||||
import org.springframework.web.bind.annotation.PathVariable
|
||||
import org.springframework.web.reactive.function.client.WebClient
|
||||
import org.springframework.web.reactive.function.client.awaitBody
|
||||
import org.springframework.web.reactive.function.client.awaitExchange
|
||||
|
||||
class ProductControllerCoroutines {
|
||||
@Autowired
|
||||
@@ -38,7 +36,7 @@ class ProductControllerCoroutines {
|
||||
webClient.get()
|
||||
.uri("/stock-service/product/$id/quantity")
|
||||
.accept(APPLICATION_JSON)
|
||||
.awaitExchange().awaitBody<Int>()
|
||||
.retrieve().awaitBody<Int>()
|
||||
}
|
||||
ProductStockView(product.await()!!, quantity.await())
|
||||
}
|
||||
|
||||
+1
-2
@@ -12,7 +12,6 @@ import org.springframework.http.MediaType
|
||||
import org.springframework.stereotype.Component
|
||||
import org.springframework.web.reactive.function.client.WebClient
|
||||
import org.springframework.web.reactive.function.client.awaitBody
|
||||
import org.springframework.web.reactive.function.client.awaitExchange
|
||||
import org.springframework.web.reactive.function.server.ServerRequest
|
||||
import org.springframework.web.reactive.function.server.ServerResponse
|
||||
import org.springframework.web.reactive.function.server.bodyAndAwait
|
||||
@@ -37,7 +36,7 @@ class ProductsHandler(
|
||||
webClient.get()
|
||||
.uri("/stock-service/product/$id/quantity")
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.awaitExchange().awaitBody<Int>()
|
||||
.retrieve().awaitBody<Int>()
|
||||
}
|
||||
return ServerResponse.ok().json().bodyAndAwait(ProductStockView(product.await()!!, quantity.await()))
|
||||
}
|
||||
|
||||
+3
-4
@@ -1,7 +1,7 @@
|
||||
package com.baeldung.nonblockingcoroutines.repository
|
||||
|
||||
import com.baeldung.nonblockingcoroutines.model.Product
|
||||
import org.springframework.data.r2dbc.function.DatabaseClient
|
||||
import org.springframework.data.r2dbc.core.DatabaseClient
|
||||
import org.springframework.stereotype.Repository
|
||||
import reactor.core.publisher.Flux
|
||||
import reactor.core.publisher.Mono
|
||||
@@ -10,7 +10,7 @@ import reactor.core.publisher.Mono
|
||||
class ProductRepository(private val client: DatabaseClient) {
|
||||
|
||||
fun getProductById(id: Int): Mono<Product> {
|
||||
return client.execute().sql("SELECT * FROM products WHERE id = $1")
|
||||
return client.execute("SELECT * FROM products WHERE id = $1")
|
||||
.bind(0, id)
|
||||
.`as`(Product::class.java)
|
||||
.fetch()
|
||||
@@ -18,8 +18,7 @@ class ProductRepository(private val client: DatabaseClient) {
|
||||
}
|
||||
|
||||
fun addNewProduct(name: String, price: Float): Mono<Void> {
|
||||
return client.execute()
|
||||
.sql("INSERT INTO products (name, price) VALUES($1, $2)")
|
||||
return client.execute("INSERT INTO products (name, price) VALUES($1, $2)")
|
||||
.bind(0, name)
|
||||
.bind(1, price)
|
||||
.then()
|
||||
|
||||
+3
-4
@@ -6,14 +6,14 @@ import kotlinx.coroutines.FlowPreview
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.reactive.awaitFirstOrNull
|
||||
import kotlinx.coroutines.reactive.flow.asFlow
|
||||
import org.springframework.data.r2dbc.function.DatabaseClient
|
||||
import org.springframework.data.r2dbc.core.DatabaseClient
|
||||
import org.springframework.stereotype.Repository
|
||||
|
||||
@Repository
|
||||
class ProductRepositoryCoroutines(private val client: DatabaseClient) {
|
||||
|
||||
suspend fun getProductById(id: Int): Product? =
|
||||
client.execute().sql("SELECT * FROM products WHERE id = $1")
|
||||
client.execute("SELECT * FROM products WHERE id = $1")
|
||||
.bind(0, id)
|
||||
.`as`(Product::class.java)
|
||||
.fetch()
|
||||
@@ -21,8 +21,7 @@ class ProductRepositoryCoroutines(private val client: DatabaseClient) {
|
||||
.awaitFirstOrNull()
|
||||
|
||||
suspend fun addNewProduct(name: String, price: Float) =
|
||||
client.execute()
|
||||
.sql("INSERT INTO products (name, price) VALUES($1, $2)")
|
||||
client.execute("INSERT INTO products (name, price) VALUES($1, $2)")
|
||||
.bind(0, name)
|
||||
.bind(1, price)
|
||||
.then()
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
## Spring Boot MVC
|
||||
|
||||
This module contains articles about Spring Web MVC in Spring Boot projects.
|
||||
|
||||
### Relevant Articles:
|
||||
|
||||
- More articles: [[prev -->]](/spring-boot-modules/spring-boot-mvc-2)
|
||||
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>spring-boot-mvc-3</artifactId>
|
||||
<name>spring-boot-mvc-3</name>
|
||||
<packaging>jar</packaging>
|
||||
<description>Module For Spring Boot MVC Web</description>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-boot-2</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../../parent-boot-2</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package com.baeldung.circularviewpath;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
/**
|
||||
* Spring Boot launcher for an application
|
||||
*
|
||||
*/
|
||||
@SpringBootApplication(scanBasePackages = "com.baeldung.controller.circularviewpath")
|
||||
public class CircularViewPathApplication {
|
||||
|
||||
/**
|
||||
* Launches a Spring Boot application
|
||||
*
|
||||
* @param args null
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(CircularViewPathApplication.class, args);
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package com.baeldung.controller.circularviewpath;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
@Controller
|
||||
public class CircularViewPathController {
|
||||
|
||||
/**
|
||||
* A request mapping which may cause circular view path exception
|
||||
*/
|
||||
@GetMapping("/path")
|
||||
public String path() {
|
||||
return "path";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</configuration>
|
||||
@@ -0,0 +1,13 @@
|
||||
<!doctype html>
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
<title>path.html</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p>path.html</p>
|
||||
</body>
|
||||
</html>
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
package com.baeldung.properties.lists;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(classes = SpringListPropertiesApplication.class)
|
||||
public class ListsPropertiesUnitTest {
|
||||
|
||||
@Value("${arrayOfStrings}")
|
||||
private String[] arrayOfStrings;
|
||||
|
||||
@Value("${arrayOfStrings}")
|
||||
private List<String> unexpectedListOfStrings;
|
||||
|
||||
@Value("#{'${arrayOfStrings}'.split(',')}")
|
||||
private List<String> listOfStrings;
|
||||
|
||||
@Value("#{${listOfStrings}}")
|
||||
private List<String> listOfStringsV2;
|
||||
|
||||
@Value("#{'${listOfStringsWithCustomDelimiter}'.split(';')}")
|
||||
private List<String> listOfStringsWithCustomDelimiter;
|
||||
|
||||
@Value("#{'${listOfBooleans}'.split(',')}")
|
||||
private List<Boolean> listOfBooleans;
|
||||
|
||||
@Value("#{'${listOfIntegers}'.split(',')}")
|
||||
private List<Integer> listOfIntegers;
|
||||
|
||||
@Value("#{'${listOfCharacters}'.split(',')}")
|
||||
private List<Character> listOfCharacters;
|
||||
|
||||
@Autowired
|
||||
private Environment environment;
|
||||
|
||||
@Test
|
||||
public void whenContextIsInitialized_thenInjectedArrayContainsExpectedValues() {
|
||||
assertEquals(new String[] {"Baeldung", "dot", "com"}, arrayOfStrings);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenContextIsInitialized_thenInjectedListContainsUnexpectedValues() {
|
||||
assertEquals(Collections.singletonList("Baeldung,dot,com"), unexpectedListOfStrings);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenContextIsInitialized_thenInjectedListContainsExpectedValues() {
|
||||
assertEquals(Arrays.asList("Baeldung", "dot", "com"), listOfStrings);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenContextIsInitialized_thenInjectedListV2ContainsExpectedValues() {
|
||||
assertEquals(Arrays.asList("Baeldung", "dot", "com"), listOfStringsV2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenContextIsInitialized_thenInjectedListWithCustomDelimiterContainsExpectedValues() {
|
||||
assertEquals(Arrays.asList("Baeldung", "dot", "com"), listOfStringsWithCustomDelimiter);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenContextIsInitialized_thenInjectedListOfBasicTypesContainsExpectedValues() {
|
||||
assertEquals(Arrays.asList(false, false, true), listOfBooleans);
|
||||
assertEquals(Arrays.asList(1, 2, 3, 4), listOfIntegers);
|
||||
assertEquals(Arrays.asList('a', 'b', 'c'), listOfCharacters);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenReadingFromSpringEnvironment_thenPropertiesHaveExpectedValues() {
|
||||
String[] arrayOfStrings = environment.getProperty("arrayOfStrings", String[].class);
|
||||
List<String> listOfStrings = (List<String>)environment.getProperty("arrayOfStrings", List.class);
|
||||
|
||||
assertEquals(new String[] {"Baeldung", "dot", "com"}, arrayOfStrings);
|
||||
assertEquals(Arrays.asList("Baeldung", "dot", "com"), listOfStrings);
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package com.baeldung.properties.lists;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
|
||||
@Configuration
|
||||
@PropertySource(value = "lists.properties")
|
||||
public class SpringListPropertiesApplication {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
arrayOfStrings=Baeldung,dot,com
|
||||
listOfStrings={'Baeldung','dot','com'}
|
||||
listOfStringsWithCustomDelimiter=Baeldung;dot;com
|
||||
listOfBooleans=false,false,true
|
||||
listOfIntegers=1,2,3,4
|
||||
listOfCharacters=a,b,c
|
||||
@@ -1,13 +0,0 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
|
||||
# Git
|
||||
.git
|
||||
.cache
|
||||
|
||||
# Classes
|
||||
**/*.class
|
||||
|
||||
# Ignore md files
|
||||
*.md
|
||||
@@ -1,10 +0,0 @@
|
||||
FROM maven:3.6.0-jdk-11
|
||||
WORKDIR /code/spring-boot-modules/spring-boot-properties/
|
||||
COPY ./spring-boot-modules/spring-boot-properties/pom.xml .
|
||||
COPY ./spring-boot-modules/spring-boot-properties/src ./src
|
||||
COPY ./parent-boot-2/pom.xml /code/parent-boot-2/pom.xml
|
||||
COPY ./pom.xml /code/pom.xml
|
||||
COPY ./custom-pmd-0.0.1.jar /code/custom-pmd-0.0.1.jar
|
||||
COPY ./baeldung-pmd-rules.xml /code/baeldung-pmd-rules.xml
|
||||
RUN mvn dependency:resolve
|
||||
CMD ["mvn", "spring-boot:run"]
|
||||
+20
@@ -11,6 +11,9 @@ import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
import com.baeldung.yaml.YAMLConfig.Idm;
|
||||
import com.baeldung.yaml.YAMLConfig.Service;
|
||||
|
||||
@SpringBootApplication
|
||||
public class MyApplication implements CommandLineRunner {
|
||||
|
||||
@@ -26,6 +29,23 @@ public class MyApplication implements CommandLineRunner {
|
||||
System.out.println("using environment:" + myConfig.getEnvironment());
|
||||
System.out.println("name:" + myConfig.getName());
|
||||
System.out.println("servers:" + myConfig.getServers());
|
||||
|
||||
if ("testing".equalsIgnoreCase(myConfig.getEnvironment())) {
|
||||
System.out.println("external:" + myConfig.getExternal());
|
||||
System.out.println("map:" + myConfig.getMap());
|
||||
|
||||
Idm idm = myConfig.getComponent().getIdm();
|
||||
Service service = myConfig.getComponent().getService();
|
||||
System.out.println("Idm:");
|
||||
System.out.println(" Url: " + idm.getUrl());
|
||||
System.out.println(" User: " + idm.getUser());
|
||||
System.out.println(" Password: " + idm.getPassword());
|
||||
System.out.println(" Description: " + idm.getDescription());
|
||||
System.out.println("Service:");
|
||||
System.out.println(" Url: " + service.getUrl());
|
||||
System.out.println(" Token: " + service.getToken());
|
||||
System.out.println(" Description: " + service.getDescription());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+112
@@ -1,7 +1,10 @@
|
||||
package com.baeldung.yaml;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -13,6 +16,9 @@ public class YAMLConfig {
|
||||
private String name;
|
||||
private String environment;
|
||||
private List<String> servers = new ArrayList<String>();
|
||||
private List<String> external = new ArrayList<String>();
|
||||
private Map<String, String> map = new HashMap<String, String>();
|
||||
private Component component = new Component();
|
||||
|
||||
public List<String> getServers() {
|
||||
return servers;
|
||||
@@ -37,5 +43,111 @@ public class YAMLConfig {
|
||||
public void setEnvironment(String environment) {
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
public Component getComponent() {
|
||||
return component;
|
||||
}
|
||||
|
||||
public void setComponent(Component component) {
|
||||
this.component = component;
|
||||
}
|
||||
|
||||
public Map<String, String> getMap() {
|
||||
return map;
|
||||
}
|
||||
|
||||
public void setMap(Map<String, String> map) {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
public List<String> getExternal() {
|
||||
return external;
|
||||
}
|
||||
|
||||
public void setExternal(List<String> external) {
|
||||
this.external = external;
|
||||
}
|
||||
|
||||
public class Component {
|
||||
private Idm idm = new Idm();
|
||||
private Service service = new Service();
|
||||
|
||||
public Idm getIdm() {
|
||||
return idm;
|
||||
}
|
||||
public void setIdm(Idm idm) {
|
||||
this.idm = idm;
|
||||
}
|
||||
|
||||
public Service getService() {
|
||||
return service;
|
||||
}
|
||||
public void setService(Service service) {
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class Idm {
|
||||
private String url;
|
||||
private String user;
|
||||
private String password;
|
||||
private String description;
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String getUser() {
|
||||
return user;
|
||||
}
|
||||
public void setUser(String user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
}
|
||||
|
||||
public class Service {
|
||||
private String url;
|
||||
private String token;
|
||||
private String description;
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
public void setToken(String token) {
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,22 +6,42 @@ spring:
|
||||
---
|
||||
|
||||
spring:
|
||||
profiles: test
|
||||
profiles: test
|
||||
name: test-YAML
|
||||
environment: testing
|
||||
servers:
|
||||
- www.abc.test.com
|
||||
- www.xyz.test.com
|
||||
|
||||
- www.abc.test.com
|
||||
- www.xyz.test.com
|
||||
|
||||
external: [www.abc.test.com, www.xyz.test.com]
|
||||
|
||||
map:
|
||||
firstkey: key1
|
||||
secondkey: key2
|
||||
|
||||
component:
|
||||
idm:
|
||||
url: myurl
|
||||
user: user
|
||||
password: password
|
||||
description: >
|
||||
this should be a long
|
||||
description
|
||||
service:
|
||||
url: myurlservice
|
||||
token: token
|
||||
description: >
|
||||
this should be another long
|
||||
description
|
||||
---
|
||||
|
||||
spring:
|
||||
profiles: prod
|
||||
profiles: prod
|
||||
name: prod-YAML
|
||||
environment: production
|
||||
servers:
|
||||
- www.abc.com
|
||||
- www.xyz.com
|
||||
- www.abc.com
|
||||
- www.xyz.com
|
||||
|
||||
---
|
||||
|
||||
|
||||
+2
@@ -11,6 +11,7 @@ import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = MyApplication.class)
|
||||
@TestPropertySource(properties = {"spring.profiles.active = test"})
|
||||
class YAMLIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
@@ -20,5 +21,6 @@ class YAMLIntegrationTest {
|
||||
void whenProfileTest_thenNameTesting() {
|
||||
assertTrue("testing".equalsIgnoreCase(config.getEnvironment()));
|
||||
assertTrue("test-YAML".equalsIgnoreCase(config.getName()));
|
||||
assertTrue("myurl".equalsIgnoreCase(config.getComponent().getIdm().getUrl()));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user