Compare commits

...

86 Commits

Author SHA1 Message Date
dependabot[bot]
d90c6fbc71 Bump junit from 4.13 to 4.13.1 in /spring-boot/spring-events
Bumps [junit](https://github.com/junit-team/junit4) from 4.13 to 4.13.1.
- [Release notes](https://github.com/junit-team/junit4/releases)
- [Changelog](https://github.com/junit-team/junit4/blob/main/doc/ReleaseNotes4.13.1.md)
- [Commits](https://github.com/junit-team/junit4/compare/r4.13...r4.13.1)

Signed-off-by: dependabot[bot] <support@github.com>
2020-10-13 20:46:39 +00:00
Tom Hombergs
4c4469b43b Merge pull request #52 from murtuza-ranapur/hibernate-search
Hibernate search
2020-10-07 09:00:12 +11:00
murtuza-ranapur
0e40dbfee3 * Removes default test case 2020-10-03 13:18:48 +05:30
Murtuza Ranapur
d47db42925 Merge branch 'master' into hibernate-search 2020-10-03 11:47:44 +05:30
murtuza-ranapur
04dcc8097a Merge remote-tracking branch 'origin/hibernate-search' into hibernate-search 2020-10-03 11:44:48 +05:30
murtuza-ranapur
ec52966e5f * Adds hibernate-search to build-all.sh 2020-10-03 11:44:34 +05:30
Tom Hombergs
b982958196 Merge pull request #56 from susetech/code-examples-suse-branch
Processing Files using Java 8 Streams
2020-09-27 07:52:15 +10:00
Tom Hombergs
974872ed8e Merge branch 'master' into code-examples-suse-branch 2020-09-27 07:41:54 +10:00
Tom Hombergs
0edc9e3e8e fix build and add to build-all.sh 2020-09-27 07:39:25 +10:00
Tom Hombergs
7d4dd46e2c Merge remote-tracking branch 'susetech/code-examples-suse-branch' into code-examples-suse-branch 2020-09-27 07:25:08 +10:00
Tom Hombergs
5169b74c86 Update README.md 2020-09-24 06:56:17 +10:00
Tom Hombergs
b5dc195722 Merge pull request #57 from itsLucario/component-scan
Component scan code example
2020-09-24 06:18:41 +10:00
Nandan Bn
47a1d0c4b7 component-scan readme & build module added 2020-09-23 15:55:31 +05:30
Nandan Bn
cacef37325 Merge remote-tracking branch 'upstream/master' 2020-09-23 15:37:07 +05:30
Nandan Bn
ab9aa60613 Spring Component Scanning 2020-09-23 15:36:39 +05:30
Tom Hombergs
782b64a32f Merge pull request #53 from pratikdas/spring-booot-health-check
added code for health check
2020-09-22 07:01:33 +10:00
Pratik Das
2f948c0616 Merge branch 'spring-booot-health-check' of https://github.com/pratikdas/code-examples into spring-booot-health-check 2020-09-21 21:06:59 +04:00
Pratik Das
2e3d9a03b6 modified few classes 2020-09-21 21:05:38 +04:00
susetech
0e48de379f Read me changes 2020-09-20 19:20:57 +05:30
susetech
08d2592311 Maven wraper 2020-09-20 09:07:28 +05:30
Tom Hombergs
313889e494 Merge branch 'master' into hibernate-search 2020-09-20 07:33:46 +10:00
Tom Hombergs
6058641b80 Merge branch 'master' into spring-booot-health-check 2020-09-20 07:33:13 +10:00
Tom Hombergs
ba8ba61586 Merge branch 'master' into code-examples-suse-branch 2020-09-20 07:32:39 +10:00
Tom Hombergs
ec595e8bae disable tests that make problems on Github Actions 2020-09-20 07:11:41 +10:00
Tom Hombergs
743bf01b0d attempt to make the @Disabled annotation work 2020-09-20 06:59:29 +10:00
Tom Hombergs
ca9cc4ad65 Merge remote-tracking branch 'origin/master' 2020-09-20 06:48:51 +10:00
susetech
b2ee3aafa3 Change in read me file 2020-09-19 22:05:47 +05:30
susetech
f137ea52db Read Me file 2020-09-19 21:48:34 +05:30
susetech
13888f806e Full example code and resources 2020-09-19 16:39:55 +05:30
Pratik Das
778a3d1d6f added mvn wrapper 2020-09-19 10:08:54 +04:00
Pratik Das
8b277387a1 added code for health check 2020-09-19 09:48:42 +04:00
Pratik Das
029a5f03fb added code for health check 2020-09-19 09:44:17 +04:00
Tom Hombergs
2958843c5a disable tests that don't work in Github Actions 2020-09-17 20:54:15 +10:00
Tom Hombergs
daa95bdf02 Merge pull request #51 from saajn/bulkhead
Bulkhead article examples
2020-09-17 07:44:25 +10:00
murtuza-ranapur
316fffdd7c * Adds README.md 2020-09-16 22:35:33 +05:30
Saajan
c65e2b2165 Added bulkhead module 2020-09-16 21:03:20 +05:30
Saajan
44b4842849 Added readme file 2020-09-16 20:59:13 +05:30
Saajan
947c68f0a8 Initial commit 2020-09-16 20:32:08 +05:30
murtuza-ranapur
927c51a2bb * Adds README.md 2020-09-16 18:39:24 +05:30
murtuza-ranapur
07265e54ed * Adds hibernate search example application 2020-09-16 18:26:35 +05:30
susetech
00b00e6e77 Initial commit of processing files with java streams code samples 2020-09-12 12:16:11 +05:30
Tom Hombergs
1eabfebeb0 Merge pull request #50 from pratikdas/spring-boot-docker
added docker related files
2020-09-05 07:49:29 +10:00
Pratik Das
b9b6ee02c5 added docker files wrapper 2020-08-30 13:14:33 +04:00
Pratik Das
64f680bd70 added docker files 2020-08-30 12:23:08 +04:00
Pratik Das
e833835beb added docker files 2020-08-30 12:17:43 +04:00
Tom Hombergs
c358d28ca6 Merge pull request #48 from pratikdas/springboot-logger-dtls
added code for spring boot logging
2020-08-24 06:22:19 +10:00
Pratik Das
ba285f6ee8 added wrapper 2020-08-23 14:57:29 +04:00
Pratik Das
72d7a158b2 renamed module 2020-08-23 14:46:47 +04:00
Tom Hombergs
c8f550a222 Merge pull request #45 from saajn/timelimiter
Code examples for TimeLimiter
2020-08-18 06:58:59 +10:00
Pratik Das
7324634620 updated readme 2020-08-16 17:58:38 +04:00
Pratik Das
b1d595be27 added code for spring boot logging 2020-08-16 16:34:58 +04:00
Tom Hombergs
8e9def0e7e Create README.md 2020-08-15 16:11:56 +10:00
Tom Hombergs
4141cefdec Create README.md 2020-08-15 16:09:42 +10:00
Tom Hombergs
ffcdc70902 Create README.md 2020-08-15 16:09:09 +10:00
Tom Hombergs
445173072d Create README.md 2020-08-15 16:07:47 +10:00
Tom Hombergs
bb7b3c1a95 Create README.md 2020-08-15 16:07:07 +10:00
Tom Hombergs
3d255abdaf Create README.md 2020-08-15 16:06:33 +10:00
Tom Hombergs
308663a9fd Create README.md 2020-08-15 16:06:02 +10:00
Tom Hombergs
b793060c05 Create README.md 2020-08-15 16:05:37 +10:00
Tom Hombergs
008636f6fa Create README.md 2020-08-15 16:05:00 +10:00
Tom Hombergs
467aaa1e07 Create README.md 2020-08-15 16:03:46 +10:00
Tom Hombergs
8e79ba1efa Create README.md 2020-08-15 16:02:37 +10:00
Tom Hombergs
d222085520 Create README.md 2020-08-15 16:01:48 +10:00
Tom Hombergs
3d128c346e Create README.md 2020-08-15 16:01:11 +10:00
Tom Hombergs
c4e387b408 Create README.md 2020-08-15 15:53:55 +10:00
Tom Hombergs
788e477803 Create README.md 2020-08-15 15:53:20 +10:00
Tom Hombergs
5983abbf68 Create README.md 2020-08-15 15:53:08 +10:00
Tom Hombergs
2b096d0470 Create README.md 2020-08-15 15:52:16 +10:00
Tom Hombergs
712bef33d8 Update README.md 2020-08-15 15:38:28 +10:00
Tom Hombergs
7148869bac Update README.md 2020-08-15 15:37:09 +10:00
Tom Hombergs
68ef61997d Create README.md 2020-08-15 15:36:53 +10:00
Tom Hombergs
12ba1f793e Create README.md 2020-08-15 15:32:54 +10:00
Tom Hombergs
e42b7e8c4c Create README.md 2020-08-15 15:31:20 +10:00
Tom Hombergs
a8e491c22a don't run actions on changes to markdown files 2020-08-15 15:29:13 +10:00
Tom Hombergs
570b5f4abf Merge pull request #47 from thombergs/devtools
Devtools
2020-08-12 06:57:04 +10:00
Tom Hombergs
1c7ea0ab08 Merge pull request #46 from yavuztas/38-the-lifecycle-f-spring-beans
38 the lifecycle f spring beans
2020-08-11 06:49:17 +10:00
Yavuz Tas
7bebf8ccfd Merge branch '38-the-lifecycle-f-spring-beans' of https://github.com/yavuztas/code-examples into 38-the-lifecycle-f-spring-beans 2020-08-09 15:57:52 +02:00
Yavuz Tas
29f039ff97 add sample test for Quartz integration 2020-08-09 15:57:28 +02:00
Saajan
c45f41d171 Removed unused test class 2020-08-08 21:26:09 +05:30
Saajan
a83e8c34c6 Back merged from offical repo 2020-08-08 21:23:03 +05:30
Saajan
1e5e5e2e91 Removed commented lines in ratelimiter pom 2020-08-08 21:21:02 +05:30
Saajan
31025040dc Added timelimiter module to build-all 2020-08-08 21:19:48 +05:30
Saajan
ccc5fdb306 Initial check in 2020-08-08 21:14:25 +05:30
Tom Hombergs
8bbf1388b1 Create README.md 2020-08-08 17:56:54 +10:00
Tom Hombergs
33649d5d8d Update README.md 2020-08-08 17:55:02 +10:00
Tom Hombergs
53bb36722c Create README.md 2020-08-08 17:54:35 +10:00
184 changed files with 8172 additions and 14 deletions

View File

@@ -1,6 +1,12 @@
name: CI
on: [push, pull_request]
on:
push:
paths-ignore:
- '**/*.md'
pull_request:
paths-ignore:
- '**/*.md'
jobs:

View File

@@ -65,6 +65,11 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>

View File

@@ -12,6 +12,7 @@ import io.reflectoring.customerregistration.dtos.CustomerCreateRequest;
import io.reflectoring.customerregistration.repositories.CustomerImageStore;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -34,6 +35,7 @@ import software.amazon.awssdk.services.s3.model.NoSuchKeyException;
@ExtendWith(LocalstackDockerExtension.class)
@ActiveProfiles("local")
@LocalstackDockerProperties(services = { "s3" })
@Disabled(value = "Disabled because starting Docker containers like this does not run on GitHub Actions.")
class CustomerImageStoreTest {
private static final Region region = Region.US_EAST_1;

View File

@@ -10,6 +10,7 @@ import io.reflectoring.customerregistration.dtos.CustomerDto;
import io.reflectoring.customerregistration.repositories.CustomerProfileStore;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -37,6 +38,7 @@ import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType;
@ExtendWith(LocalstackDockerExtension.class)
@ActiveProfiles("local")
@LocalstackDockerProperties(services = { "dynamodb"})
@Disabled(value = "Disabled because starting Docker containers like this does not run on GitHub Actions.")
class CustomerProfileStoreTest {
private static final Region region = Region.US_EAST_1;

View File

@@ -86,7 +86,12 @@ if [[ "$MODULE" == "module5" ]]
then
# ADD NEW MODULES HERE
# (add new modules above the rest so you get quicker feedback if it fails)
build_gradle_module "spring-boot/hibernate-search"
build_maven_module "core-java/streams/fileswithstreams"
build_maven_module "spring-boot/spring-boot-health-check"
build_maven_module "spring-boot/spring-boot-logging-2"
build_maven_module "spring-boot/spring-boot-docker"
build_maven_module "spring-boot/spring-component-scanning"
build_gradle_module "spring-boot/devtools-demo"
build_gradle_module "spring-boot/cache"
build_gradle_module "spring-boot/bean-lifecycle"
@@ -128,6 +133,8 @@ then
build_maven_module "solid/lsp"
build_maven_module "resilience4j/retry"
build_maven_module "resilience4j/ratelimiter"
build_maven_module "resilience4j/timelimiter"
build_maven_module "resilience4j/bulkhead"
build_gradle_module "spring-data/spring-data-jdbc-converter"
build_gradle_module "reactive"
build_gradle_module "junit/assumptions"

View File

@@ -0,0 +1 @@
/target/

View File

@@ -0,0 +1,117 @@
/*
* Copyright 2007-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.net.*;
import java.io.*;
import java.nio.channels.*;
import java.util.Properties;
public class MavenWrapperDownloader {
private static final String WRAPPER_VERSION = "0.5.6";
/**
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
*/
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
/**
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
* use instead of the default one.
*/
private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
".mvn/wrapper/maven-wrapper.properties";
/**
* Path where the maven-wrapper.jar will be saved to.
*/
private static final String MAVEN_WRAPPER_JAR_PATH =
".mvn/wrapper/maven-wrapper.jar";
/**
* Name of the property which should be used to override the default download url for the wrapper.
*/
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
public static void main(String args[]) {
System.out.println("- Downloader started");
File baseDirectory = new File(args[0]);
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
// If the maven-wrapper.properties exists, read it and check if it contains a custom
// wrapperUrl parameter.
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
String url = DEFAULT_DOWNLOAD_URL;
if(mavenWrapperPropertyFile.exists()) {
FileInputStream mavenWrapperPropertyFileInputStream = null;
try {
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
Properties mavenWrapperProperties = new Properties();
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
} catch (IOException e) {
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
} finally {
try {
if(mavenWrapperPropertyFileInputStream != null) {
mavenWrapperPropertyFileInputStream.close();
}
} catch (IOException e) {
// Ignore ...
}
}
}
System.out.println("- Downloading from: " + url);
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
if(!outputFile.getParentFile().exists()) {
if(!outputFile.getParentFile().mkdirs()) {
System.out.println(
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
}
}
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
try {
downloadFileFromURL(url, outputFile);
System.out.println("Done");
System.exit(0);
} catch (Throwable e) {
System.out.println("- Error downloading");
e.printStackTrace();
System.exit(1);
}
}
private static void downloadFileFromURL(String urlString, File destination) throws Exception {
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
String username = System.getenv("MVNW_USERNAME");
char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
}
URL website = new URL(urlString);
ReadableByteChannel rbc;
rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream(destination);
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
fos.close();
rbc.close();
}
}

Binary file not shown.

View File

@@ -0,0 +1,2 @@
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar

View File

@@ -0,0 +1,16 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=11
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
org.eclipse.jdt.core.compiler.release=disabled
org.eclipse.jdt.core.compiler.source=11

View File

@@ -0,0 +1,4 @@
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1

View File

@@ -0,0 +1,5 @@
# Files with streams Code Examples
## Related Blog Articles
* [Processing Files using Java 8 Streams](https://reflectoring.io/processing-files-using-java-8-streams/)

310
core-java/streams/fileswithstreams/mvnw vendored Executable file
View File

@@ -0,0 +1,310 @@
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Maven Start Up Batch script
#
# Required ENV vars:
# ------------------
# JAVA_HOME - location of a JDK home dir
#
# Optional ENV vars
# -----------------
# M2_HOME - location of maven2's installed home dir
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
# e.g. to debug Maven itself, use
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ] ; then
if [ -f /etc/mavenrc ] ; then
. /etc/mavenrc
fi
if [ -f "$HOME/.mavenrc" ] ; then
. "$HOME/.mavenrc"
fi
fi
# OS specific support. $var _must_ be set to either true or false.
cygwin=false;
darwin=false;
mingw=false
case "`uname`" in
CYGWIN*) cygwin=true ;;
MINGW*) mingw=true;;
Darwin*) darwin=true
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
if [ -z "$JAVA_HOME" ]; then
if [ -x "/usr/libexec/java_home" ]; then
export JAVA_HOME="`/usr/libexec/java_home`"
else
export JAVA_HOME="/Library/Java/Home"
fi
fi
;;
esac
if [ -z "$JAVA_HOME" ] ; then
if [ -r /etc/gentoo-release ] ; then
JAVA_HOME=`java-config --jre-home`
fi
fi
if [ -z "$M2_HOME" ] ; then
## resolve links - $0 may be a link to maven's home
PRG="$0"
# need this for relative symlinks
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG="`dirname "$PRG"`/$link"
fi
done
saveddir=`pwd`
M2_HOME=`dirname "$PRG"`/..
# make it fully qualified
M2_HOME=`cd "$M2_HOME" && pwd`
cd "$saveddir"
# echo Using m2 at $M2_HOME
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --unix "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
fi
# For Mingw, ensure paths are in UNIX format before anything is touched
if $mingw ; then
[ -n "$M2_HOME" ] &&
M2_HOME="`(cd "$M2_HOME"; pwd)`"
[ -n "$JAVA_HOME" ] &&
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
fi
if [ -z "$JAVA_HOME" ]; then
javaExecutable="`which javac`"
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
# readlink(1) is not available as standard on Solaris 10.
readLink=`which readlink`
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
if $darwin ; then
javaHome="`dirname \"$javaExecutable\"`"
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
else
javaExecutable="`readlink -f \"$javaExecutable\"`"
fi
javaHome="`dirname \"$javaExecutable\"`"
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
JAVA_HOME="$javaHome"
export JAVA_HOME
fi
fi
fi
if [ -z "$JAVACMD" ] ; then
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD="`which java`"
fi
fi
if [ ! -x "$JAVACMD" ] ; then
echo "Error: JAVA_HOME is not defined correctly." >&2
echo " We cannot execute $JAVACMD" >&2
exit 1
fi
if [ -z "$JAVA_HOME" ] ; then
echo "Warning: JAVA_HOME environment variable is not set."
fi
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
if [ -z "$1" ]
then
echo "Path not specified to find_maven_basedir"
return 1
fi
basedir="$1"
wdir="$1"
while [ "$wdir" != '/' ] ; do
if [ -d "$wdir"/.mvn ] ; then
basedir=$wdir
break
fi
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
if [ -d "${wdir}" ]; then
wdir=`cd "$wdir/.."; pwd`
fi
# end of workaround
done
echo "${basedir}"
}
# concatenates all lines of a file
concat_lines() {
if [ -f "$1" ]; then
echo "$(tr -s '\n' ' ' < "$1")"
fi
}
BASE_DIR=`find_maven_basedir "$(pwd)"`
if [ -z "$BASE_DIR" ]; then
exit 1;
fi
##########################################################################################
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
# This allows using the maven wrapper in projects that prohibit checking in binary data.
##########################################################################################
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found .mvn/wrapper/maven-wrapper.jar"
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
fi
if [ -n "$MVNW_REPOURL" ]; then
jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
else
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
fi
while IFS="=" read key value; do
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
esac
done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
if [ "$MVNW_VERBOSE" = true ]; then
echo "Downloading from: $jarUrl"
fi
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
if $cygwin; then
wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
fi
if command -v wget > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found wget ... using wget"
fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
wget "$jarUrl" -O "$wrapperJarPath"
else
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
fi
elif command -v curl > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found curl ... using curl"
fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
curl -o "$wrapperJarPath" "$jarUrl" -f
else
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Falling back to using Java to download"
fi
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
# For Cygwin, switch paths to Windows format before running javac
if $cygwin; then
javaClass=`cygpath --path --windows "$javaClass"`
fi
if [ -e "$javaClass" ]; then
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Compiling MavenWrapperDownloader.java ..."
fi
# Compiling the Java class
("$JAVA_HOME/bin/javac" "$javaClass")
fi
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
# Running the downloader
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Running MavenWrapperDownloader.java ..."
fi
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
fi
fi
fi
fi
##########################################################################################
# End of extension
##########################################################################################
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
if [ "$MVNW_VERBOSE" = true ]; then
echo $MAVEN_PROJECTBASEDIR
fi
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --path --windows "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
fi
# Provide a "standardized" way to retrieve the CLI args that will
# work with both Windows and non-Windows executions.
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
export MAVEN_CMD_LINE_ARGS
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
exec "$JAVACMD" \
$MAVEN_OPTS \
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"

View File

@@ -0,0 +1,182 @@
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM http://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Maven Start Up Batch script
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM M2_HOME - location of maven2's installed home dir
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM set title of command window
title %0
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
:skipRcPre
@setlocal
set ERROR_CODE=0
@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
echo.
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init
echo.
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
@REM ==== END VALIDATION ====
:init
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir
:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir
:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"
:endDetectBaseDir
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
:endReadAdditionalConfig
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
)
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
if "%MVNW_VERBOSE%" == "true" (
echo Found %WRAPPER_JAR%
)
) else (
if not "%MVNW_REPOURL%" == "" (
SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
)
if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %DOWNLOAD_URL%
)
powershell -Command "&{"^
"$webclient = new-object System.Net.WebClient;"^
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
"}"^
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
"}"
if "%MVNW_VERBOSE%" == "true" (
echo Finished downloading %WRAPPER_JAR%
)
)
@REM End of extension
@REM Provide a "standardized" way to retrieve the CLI args that will
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
:error
set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%" == "on" pause
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
exit /B %ERROR_CODE%

View File

@@ -0,0 +1,34 @@
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>fileswithstreams</groupId>
<artifactId>fileswithstreams</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>fileswithstreams</name>
<description>File management with streams</description>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,18 @@
package io.reflectoring.fileswithstreams;
public class Cake {
private int id;
private String name;
private int price;
public Cake(int id, String name, int price) {
this.id = id;
this.name = name;
this.price = price;
}
@Override
public String toString() {
return "Cake [id=" + id + ", name=" + name + ", price=" + price + "]";
}
}

View File

@@ -0,0 +1,209 @@
package io.reflectoring.fileswithstreams;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class FilesWithStreams {
static String folderPath = "src/main/resources/books";
static String filePath = "src/main/resources/books/bookIndex.txt";
static String csvPath = "src/main/resources/cakes.csv";
static String utfFilePath = "src/main/resources/input.txt";
static String jarFile = "src/main/resources/books.zip";
public static void main(String[] args) throws IOException {
System.out.println("-------------------Files with Streams------------------ ");
System.out.println("-------------------Introductory Example------------------ ");
processWithStream();
System.out.println(
"\r\n" + "-------------------Example 1 - Reading line by line from a file------------------ " + "\r\n");
readLineByLineUsingFiles();
System.out.println(
"\r\n" + "-------------------Example 2 - Reading with Buffered Reader------------------" + "\r\n");
readLineByLineUsingBufferedReader();
System.out.println(
"\r\n" + "-------------------Example 3 - Reading all lines from a file------------------ " + "\r\n");
readAllLinesUsingFiles();
System.out.println(
"\r\n" + "...................Example 4 - Reading with parallel streams------------------ " + "\r\n");
readWithParallelStreamAndPrint();
System.out.println(
"\r\n" + "-------------------Example 5 - Reading UTF-encoded file------------------ " + "\r\n");
readUtfEncodedFile();
System.out.println(
"\r\n" + "-------------------Example 6 - Reading, Filtering and Counting------------------ " + "\r\n");
readFilterCountFromFile();
System.out.println("\r\n" + "-------------------Example 7 - Splitting Words------------------ " + "\r\n");
splitWordsFromFile();
System.out.println("\r\n" + "-------------------Example 8 - Loading from CSV - ------------------ " + "\r\n");
loadItemsFromCsvFile();
System.out.println("\r\n" + "...................Example 9 - Listing Directories------------------ " + "\r\n");
listDirectories();
System.out
.println("\r\n" + "...................Example 10 - Listing Regular Files------------------ " + "\r\n");
listRegularFiles();
System.out.println(
"\r\n" + "...................Example 11 - Walking Files Recursively------------------ " + "\r\n");
walkFilesRecursively();
System.out.println("\r\n" + "...................Example 12 - Finding Files------------------ " + "\r\n");
findFiles();
System.out.println(
"\r\n" + "...................Example 13 - Printing JAR fie contents------------------ " + "\r\n");
printJarFileContents();
System.out.println("...................Example 14 - Printing Matching JAR entries------------------ " + "\r\n");
printMatchingJarEntries();
}
static void processWithStream() {
List<String> cities = Arrays.asList("London", "Sydney", "Colombo", "Cairo", "Beijing");
cities.stream().filter(a -> a.startsWith("C")).map(String::toUpperCase).sorted().forEach(System.out::println);
}
static void readLineByLineUsingFiles() throws IOException {
try (Stream<String> lines = Files.lines(Path.of(filePath))) {
lines.forEach(System.out::println);
}
}
static void readLineByLineUsingBufferedReader() throws IOException {
try (Stream<String> lines = (Files.newBufferedReader(Paths.get(filePath)).lines())) {
lines.forEach(System.out::println);
}
}
static void readAllLinesUsingFiles() throws IOException {
List<String> strList = Files.readAllLines(Path.of(filePath));
Stream<String> lines = strList.stream();
lines.forEach(System.out::println);
}
static void readUtfEncodedFile() throws IOException {
try (Stream<String> lines = Files.lines(Path.of(utfFilePath), StandardCharsets.UTF_8)) {
lines.forEach(System.out::println);
}
}
static void loadItemsFromCsvFile() throws IOException {
Pattern pattern = Pattern.compile(",");
try (Stream<String> lines = Files.lines(Path.of(csvPath))) {
List<Cake> cakes = lines.skip(1).map(line -> {
String[] arr = pattern.split(line);
return new Cake(Integer.parseInt(arr[0]), arr[1], Integer.parseInt(arr[2]));
}).collect(Collectors.toList());
cakes.forEach(System.out::println);
}
}
static void readFilterCountFromFile() throws IOException {
try (Stream<String> lines = Files.lines(Path.of(filePath))) {
long i = lines.filter(line -> line.startsWith("A")).count();
System.out.println("The count of lines starting with 'A' is " + i);
}
}
static void splitWordsFromFile() throws IOException {
try (Stream<String> lines = Files.lines(Path.of(filePath))) {
Stream<String> words = lines.flatMap(line -> Stream.of(line.split("\\W+")));
Set<String> wordSet = words.collect(Collectors.toSet());
System.out.println(wordSet);
}
}
static void listDirectories() throws IOException {
try (Stream<Path> paths = Files.list(Path.of(folderPath))) {
paths.filter(Files::isDirectory).forEach(System.out::println);
}
}
static void listRegularFiles() throws IOException {
try (Stream<Path> paths = Files.list(Path.of(folderPath))) {
paths.filter(Files::isRegularFile).forEach(System.out::println);
}
}
static void walkFilesRecursively() throws IOException {
try (Stream<Path> stream = Files.walk(Path.of(folderPath))) {
stream.filter(Files::isRegularFile).forEach(System.out::println);
}
}
static void findFiles() throws IOException {
int depth = Integer.MAX_VALUE;
try (Stream<Path> paths = Files.find(Path.of(folderPath), depth, (path, attr) -> {
return attr.isRegularFile() && path.toString().endsWith(".pdf");
})) {
paths.forEach(System.out::println);
}
}
static void printJarFileContents() throws IOException {
try (JarFile jFile = new JarFile(jarFile)) {
jFile.stream().forEach(file -> System.out.println(file));
}
}
static void printMatchingJarEntries() throws IOException {
try (JarFile jFile = new JarFile(jarFile)) {
Optional<JarEntry> searchResult = jFile.stream().filter(file -> file.getName().contains("Matilda"))
.findAny();
System.out.println(searchResult.get());
}
}
static void readWithParallelStreamAndPrint() throws IOException {
try (Stream<String> lines = (Files.lines(Path.of(filePath)).parallel())) {
lines.forEach(System.out::println);
}
}
}

View File

@@ -0,0 +1,5 @@
Pride and Prejudice- pride-and-prejudice.pdf
Anne of Avonlea - anne-of-avonlea.pdf
Anne of Green Gables - anne-of-green-gables.pdf
Matilda - Matilda.pdf
Why Icebergs Float - Why-Icebergs-Float.pdf

View File

@@ -0,0 +1,6 @@
#Cakes
1, Pound Cake,100
2, Red Velvet Cake,500
3, Carrot Cake,300
4, Sponge Cake,400
5, Chiffon Cake,600
1 #Cakes
2 1, Pound Cake,100
3 2, Red Velvet Cake,500
4 3, Carrot Cake,300
5 4, Sponge Cake,400
6 5, Chiffon Cake,600

View File

@@ -0,0 +1 @@
akarui _ あかるい _ bright

View File

@@ -0,0 +1 @@
/home/u1026/workspace/Learn/junit-5-basics/src/main/resources/books/

View File

@@ -0,0 +1,117 @@
/*
* Copyright 2007-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.net.*;
import java.io.*;
import java.nio.channels.*;
import java.util.Properties;
public class MavenWrapperDownloader {
private static final String WRAPPER_VERSION = "0.5.6";
/**
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
*/
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
/**
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
* use instead of the default one.
*/
private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
".mvn/wrapper/maven-wrapper.properties";
/**
* Path where the maven-wrapper.jar will be saved to.
*/
private static final String MAVEN_WRAPPER_JAR_PATH =
".mvn/wrapper/maven-wrapper.jar";
/**
* Name of the property which should be used to override the default download url for the wrapper.
*/
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
public static void main(String args[]) {
System.out.println("- Downloader started");
File baseDirectory = new File(args[0]);
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
// If the maven-wrapper.properties exists, read it and check if it contains a custom
// wrapperUrl parameter.
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
String url = DEFAULT_DOWNLOAD_URL;
if(mavenWrapperPropertyFile.exists()) {
FileInputStream mavenWrapperPropertyFileInputStream = null;
try {
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
Properties mavenWrapperProperties = new Properties();
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
} catch (IOException e) {
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
} finally {
try {
if(mavenWrapperPropertyFileInputStream != null) {
mavenWrapperPropertyFileInputStream.close();
}
} catch (IOException e) {
// Ignore ...
}
}
}
System.out.println("- Downloading from: " + url);
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
if(!outputFile.getParentFile().exists()) {
if(!outputFile.getParentFile().mkdirs()) {
System.out.println(
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
}
}
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
try {
downloadFileFromURL(url, outputFile);
System.out.println("Done");
System.exit(0);
} catch (Throwable e) {
System.out.println("- Error downloading");
e.printStackTrace();
System.exit(1);
}
}
private static void downloadFileFromURL(String urlString, File destination) throws Exception {
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
String username = System.getenv("MVNW_USERNAME");
char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
}
URL website = new URL(urlString);
ReadableByteChannel rbc;
rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream(destination);
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
fos.close();
rbc.close();
}
}

Binary file not shown.

View File

@@ -0,0 +1,2 @@
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar

View File

@@ -0,0 +1,10 @@
# Bulkhead with Resilience4J
Run the Examples program.
## Blog posts
* [Implementing Bulkhead with Resilience4j](https://reflectoring.io/bulkhead-with-resilience4j)

310
resilience4j/bulkhead/mvnw vendored Executable file
View File

@@ -0,0 +1,310 @@
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Maven Start Up Batch script
#
# Required ENV vars:
# ------------------
# JAVA_HOME - location of a JDK home dir
#
# Optional ENV vars
# -----------------
# M2_HOME - location of maven2's installed home dir
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
# e.g. to debug Maven itself, use
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ] ; then
if [ -f /etc/mavenrc ] ; then
. /etc/mavenrc
fi
if [ -f "$HOME/.mavenrc" ] ; then
. "$HOME/.mavenrc"
fi
fi
# OS specific support. $var _must_ be set to either true or false.
cygwin=false;
darwin=false;
mingw=false
case "`uname`" in
CYGWIN*) cygwin=true ;;
MINGW*) mingw=true;;
Darwin*) darwin=true
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
if [ -z "$JAVA_HOME" ]; then
if [ -x "/usr/libexec/java_home" ]; then
export JAVA_HOME="`/usr/libexec/java_home`"
else
export JAVA_HOME="/Library/Java/Home"
fi
fi
;;
esac
if [ -z "$JAVA_HOME" ] ; then
if [ -r /etc/gentoo-release ] ; then
JAVA_HOME=`java-config --jre-home`
fi
fi
if [ -z "$M2_HOME" ] ; then
## resolve links - $0 may be a link to maven's home
PRG="$0"
# need this for relative symlinks
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG="`dirname "$PRG"`/$link"
fi
done
saveddir=`pwd`
M2_HOME=`dirname "$PRG"`/..
# make it fully qualified
M2_HOME=`cd "$M2_HOME" && pwd`
cd "$saveddir"
# echo Using m2 at $M2_HOME
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --unix "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
fi
# For Mingw, ensure paths are in UNIX format before anything is touched
if $mingw ; then
[ -n "$M2_HOME" ] &&
M2_HOME="`(cd "$M2_HOME"; pwd)`"
[ -n "$JAVA_HOME" ] &&
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
fi
if [ -z "$JAVA_HOME" ]; then
javaExecutable="`which javac`"
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
# readlink(1) is not available as standard on Solaris 10.
readLink=`which readlink`
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
if $darwin ; then
javaHome="`dirname \"$javaExecutable\"`"
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
else
javaExecutable="`readlink -f \"$javaExecutable\"`"
fi
javaHome="`dirname \"$javaExecutable\"`"
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
JAVA_HOME="$javaHome"
export JAVA_HOME
fi
fi
fi
if [ -z "$JAVACMD" ] ; then
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD="`which java`"
fi
fi
if [ ! -x "$JAVACMD" ] ; then
echo "Error: JAVA_HOME is not defined correctly." >&2
echo " We cannot execute $JAVACMD" >&2
exit 1
fi
if [ -z "$JAVA_HOME" ] ; then
echo "Warning: JAVA_HOME environment variable is not set."
fi
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
if [ -z "$1" ]
then
echo "Path not specified to find_maven_basedir"
return 1
fi
basedir="$1"
wdir="$1"
while [ "$wdir" != '/' ] ; do
if [ -d "$wdir"/.mvn ] ; then
basedir=$wdir
break
fi
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
if [ -d "${wdir}" ]; then
wdir=`cd "$wdir/.."; pwd`
fi
# end of workaround
done
echo "${basedir}"
}
# concatenates all lines of a file
concat_lines() {
if [ -f "$1" ]; then
echo "$(tr -s '\n' ' ' < "$1")"
fi
}
BASE_DIR=`find_maven_basedir "$(pwd)"`
if [ -z "$BASE_DIR" ]; then
exit 1;
fi
##########################################################################################
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
# This allows using the maven wrapper in projects that prohibit checking in binary data.
##########################################################################################
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found .mvn/wrapper/maven-wrapper.jar"
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
fi
if [ -n "$MVNW_REPOURL" ]; then
jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
else
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
fi
while IFS="=" read key value; do
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
esac
done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
if [ "$MVNW_VERBOSE" = true ]; then
echo "Downloading from: $jarUrl"
fi
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
if $cygwin; then
wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
fi
if command -v wget > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found wget ... using wget"
fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
wget "$jarUrl" -O "$wrapperJarPath"
else
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
fi
elif command -v curl > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found curl ... using curl"
fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
curl -o "$wrapperJarPath" "$jarUrl" -f
else
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Falling back to using Java to download"
fi
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
# For Cygwin, switch paths to Windows format before running javac
if $cygwin; then
javaClass=`cygpath --path --windows "$javaClass"`
fi
if [ -e "$javaClass" ]; then
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Compiling MavenWrapperDownloader.java ..."
fi
# Compiling the Java class
("$JAVA_HOME/bin/javac" "$javaClass")
fi
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
# Running the downloader
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Running MavenWrapperDownloader.java ..."
fi
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
fi
fi
fi
fi
##########################################################################################
# End of extension
##########################################################################################
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
if [ "$MVNW_VERBOSE" = true ]; then
echo $MAVEN_PROJECTBASEDIR
fi
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --path --windows "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
fi
# Provide a "standardized" way to retrieve the CLI args that will
# work with both Windows and non-Windows executions.
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
export MAVEN_CMD_LINE_ARGS
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
exec "$JAVACMD" \
$MAVEN_OPTS \
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"

182
resilience4j/bulkhead/mvnw.cmd vendored Normal file
View File

@@ -0,0 +1,182 @@
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM http://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Maven Start Up Batch script
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM M2_HOME - location of maven2's installed home dir
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM set title of command window
title %0
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
:skipRcPre
@setlocal
set ERROR_CODE=0
@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
echo.
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init
echo.
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
@REM ==== END VALIDATION ====
:init
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir
:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir
:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"
:endDetectBaseDir
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
:endReadAdditionalConfig
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
)
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
if "%MVNW_VERBOSE%" == "true" (
echo Found %WRAPPER_JAR%
)
) else (
if not "%MVNW_REPOURL%" == "" (
SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
)
if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %DOWNLOAD_URL%
)
powershell -Command "&{"^
"$webclient = new-object System.Net.WebClient;"^
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
"}"^
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
"}"
if "%MVNW_VERBOSE%" == "true" (
echo Finished downloading %WRAPPER_JAR%
)
)
@REM End of extension
@REM Provide a "standardized" way to retrieve the CLI args that will
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
:error
set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%" == "on" pause
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
exit /B %ERROR_CODE%

View File

@@ -0,0 +1,113 @@
<?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>
<groupId>io.reflectoring.resilience4j.bulkhead</groupId>
<artifactId>bulkhead</artifactId>
<version>1.0-SNAPSHOT</version>
<name>bulkhead</name>
<url>https://reflectoring.io</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.release>11</maven.compiler.release>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/io.github.resilience4j/resilience4j-retry -->
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-bulkhead</artifactId>
<version>1.5.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.github.resilience4j/resilience4j-core -->
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-core</artifactId>
<version>1.5.0</version>
</dependency>
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-all</artifactId>
<version>1.5.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.github.resilience4j/resilience4j-micrometer -->
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-micrometer</artifactId>
<version>1.5.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.micrometer/micrometer-core -->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-core</artifactId>
<version>1.5.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

View File

@@ -0,0 +1,237 @@
package io.reflectoring.resilience4j.bulkhead;
import io.github.resilience4j.bulkhead.Bulkhead;
import io.github.resilience4j.bulkhead.BulkheadConfig;
import io.github.resilience4j.bulkhead.BulkheadRegistry;
import io.github.resilience4j.micrometer.tagged.TaggedBulkheadMetrics;
import io.micrometer.core.instrument.Meter;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
import io.reflectoring.resilience4j.bulkhead.model.Flight;
import io.reflectoring.resilience4j.bulkhead.model.SearchRequest;
import io.reflectoring.resilience4j.bulkhead.services.FlightSearchService;
import java.time.Duration;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.StreamSupport;
public class Examples
{
void printDefaultValues() {
BulkheadConfig config = BulkheadConfig.ofDefaults();
System.out.println("Max concurrent calls = " + config.getMaxConcurrentCalls());
System.out.println("Max wait duration = " + config.getMaxWaitDuration());
System.out.println("Writable stack trace enabled = " + config.isWritableStackTraceEnabled());
System.out.println("Fair call handling enabled = " + config.isFairCallHandlingEnabled());
}
void basicExample() {
BulkheadConfig config = BulkheadConfig.custom()
.maxConcurrentCalls(2)
.maxWaitDuration(Duration.ofSeconds(2))
.build();
BulkheadRegistry registry = BulkheadRegistry.of(config);
Bulkhead bulkhead = registry.bulkhead("flightSearchService");
FlightSearchService service = new FlightSearchService();
SearchRequest request = new SearchRequest("NYC", "LAX", "08/30/2020");
Supplier<List<Flight>> flightsSupplier = () -> service.searchFlightsTakingOneSecond(request);
Supplier<List<Flight>> decoratedFlightsSupplier = Bulkhead.decorateSupplier(bulkhead, flightsSupplier);
for (int i=0; i<4; i++) {
CompletableFuture
.supplyAsync(decoratedFlightsSupplier)
.thenAccept(flights -> System.out.println("Received results"));
}
}
void basicExample_BulkheadFullException() {
BulkheadConfig config = BulkheadConfig.custom()
.maxConcurrentCalls(2)
.maxWaitDuration(Duration.ofSeconds(1))
.build();
BulkheadRegistry registry = BulkheadRegistry.of(config);
Bulkhead bulkhead = registry.bulkhead("flightSearchService");
FlightSearchService service = new FlightSearchService();
SearchRequest request = new SearchRequest("NYC", "LAX", "08/30/2020");
Supplier<List<Flight>> flightsSupplier = () -> service.searchFlightsTakingOneSecond(request);
Supplier<List<Flight>> decoratedFlightsSupplier = Bulkhead.decorateSupplier(bulkhead, flightsSupplier);
for (int i=0; i<3; i++) {
CompletableFuture
.supplyAsync(decoratedFlightsSupplier)
.whenComplete( (r, t) -> {
if (t != null) {
Throwable cause = t.getCause();
if (cause != null) {
cause.printStackTrace();
}
}
if (r != null) {
System.out.println("Received results");
}
});
}
}
void bulkheadException_WithStackTraceOff() {
BulkheadConfig config = BulkheadConfig.custom()
.maxConcurrentCalls(2)
.maxWaitDuration(Duration.ofSeconds(1))
.writableStackTraceEnabled(false)
.build();
BulkheadRegistry registry = BulkheadRegistry.of(config);
Bulkhead bulkhead = registry.bulkhead("flightSearchService");
FlightSearchService service = new FlightSearchService();
SearchRequest request = new SearchRequest("NYC", "LAX", "08/30/2020");
Supplier<List<Flight>> flightsSupplier = () -> service.searchFlightsTakingOneSecond(request);
Supplier<List<Flight>> decoratedFlightsSupplier = Bulkhead.decorateSupplier(bulkhead, flightsSupplier);
for (int i=0; i<3; i++) {
CompletableFuture
.supplyAsync(decoratedFlightsSupplier)
.whenComplete( (r, t) -> {
if (t != null) {
Throwable cause = t.getCause();
if (cause != null) {
cause.printStackTrace();
}
}
if (r != null) {
System.out.println("Received results");
}
});
}
}
void eventsExample() {
BulkheadConfig config = BulkheadConfig.custom()
.maxWaitDuration(Duration.ofMillis(500))
.maxConcurrentCalls(3)
.build();
BulkheadRegistry registry = BulkheadRegistry.of(config);
Bulkhead bulkhead = registry.bulkhead("flightSearch");
bulkhead.getEventPublisher().onCallPermitted(e -> System.out.println(e.toString()));
bulkhead.getEventPublisher().onCallFinished(e -> System.out.println(e.toString()));
bulkhead.getEventPublisher().onCallRejected(e -> System.out.println(e.toString()));
FlightSearchService service = new FlightSearchService();
SearchRequest request = new SearchRequest("NYC", "LAX", "08/30/2020");
Supplier<List<Flight>> flightsSupplier = () -> service.searchFlightsTakingRandomTime(request);
Supplier<List<Flight>> decoratedFlightsSupplier = Bulkhead.decorateSupplier(bulkhead, flightsSupplier);
for (int i=0; i<5; i++) {
CompletableFuture
.supplyAsync(decoratedFlightsSupplier)
.whenComplete( (r, t) -> {
if (t != null) {
t.printStackTrace();
}
if (r != null) {
System.out.println("Received results");
}
});
}
}
void metricsExample() {
BulkheadConfig config = BulkheadConfig.custom()
.maxWaitDuration(Duration.ofMillis(500))
.maxConcurrentCalls(8)
.build();
BulkheadRegistry registry = BulkheadRegistry.of(config);
Bulkhead bulkhead = registry.bulkhead("flightSearchService");
MeterRegistry meterRegistry = new SimpleMeterRegistry();
TaggedBulkheadMetrics.ofBulkheadRegistry(registry).bindTo(meterRegistry);
bulkhead.getEventPublisher().onCallPermitted(e -> printMetricDetails(meterRegistry));
bulkhead.getEventPublisher().onCallRejected(e -> printMetricDetails(meterRegistry));
bulkhead.getEventPublisher().onCallFinished(e -> printMetricDetails(meterRegistry));
FlightSearchService service = new FlightSearchService();
SearchRequest request = new SearchRequest("NYC", "LAX", "08/30/2020");
Supplier<List<Flight>> flightsSupplier = () -> service.searchFlightsTakingRandomTime(request);
Supplier<List<Flight>> decoratedFlightsSupplier = Bulkhead.decorateSupplier(bulkhead, flightsSupplier);
for (int i=0; i<5; i++) {
CompletableFuture.supplyAsync(decoratedFlightsSupplier)
.whenComplete( (r, t) -> {
if (r != null) {
System.out.println("Received results");
}
});
}
}
void printMetricDetails(MeterRegistry meterRegistry) {
Consumer<Meter> meterConsumer = meter -> {
String desc = meter.getId().getDescription();
String metricName = meter.getId().getName();
Double metricValue = StreamSupport.stream(meter.measure().spliterator(), false)
.filter(m -> m.getStatistic().name().equals("VALUE"))
.findFirst()
.map(m -> m.getValue())
.orElse(0.0);
System.out.println(desc + " - " + metricName + ": " + metricValue);
};
meterRegistry.forEachMeter(meterConsumer);
}
static void delay(int seconds) {
// sleep to simulate delay
try {
Thread.sleep(seconds * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main( String[] args )
{
Examples examples = new Examples();
System.out.println("---------------------------- printDefaultValues -------------------------------------------");
examples.printDefaultValues();
System.out.println("-----------------------------------------------------------------------");
System.out.println("---------------------------- basicExample -------------------------------------------");
examples.basicExample();
delay(3);
System.out.println("-----------------------------------------------------------------------");
System.out.println("---------------------------- basicExample_BulkheadFullException -------------------------------------------");
examples.basicExample_BulkheadFullException();
delay(3);
System.out.println("-----------------------------------------------------------------------");
System.out.println("---------------------------- bulkheadException_WithStackTraceOff -------------------------------------------");
examples.bulkheadException_WithStackTraceOff();
delay(10);
System.out.println("-----------------------------------------------------------------------");
System.out.println("---------------------------- eventsExample -------------------------------------------");
examples.eventsExample();
delay(5); // delay just to let the above operation complete
System.out.println("-----------------------------------------------------------------------");
System.out.println("---------------------------- metricsExample -------------------------------------------");
examples.metricsExample();
delay(15);
System.out.println("-----------------------------------------------------------------------");
}
}

View File

@@ -0,0 +1,302 @@
package io.reflectoring.resilience4j.bulkhead;
import io.github.resilience4j.bulkhead.ThreadPoolBulkhead;
import io.github.resilience4j.bulkhead.ThreadPoolBulkheadConfig;
import io.github.resilience4j.bulkhead.ThreadPoolBulkheadRegistry;
import io.github.resilience4j.micrometer.tagged.TaggedThreadPoolBulkheadMetrics;
import io.micrometer.core.instrument.Meter;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
import io.reflectoring.resilience4j.bulkhead.model.Flight;
import io.reflectoring.resilience4j.bulkhead.model.SearchRequest;
import io.reflectoring.resilience4j.bulkhead.services.FlightSearchService;
import io.reflectoring.resilience4j.bulkhead.utils.RequestTrackingIdHolder;
import io.reflectoring.resilience4j.bulkhead.utils.RequestTrackingIdPropagator;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CompletionStage;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.StreamSupport;
public class ThreadpoolBulkheadExamples
{
void printDefaultValues() {
ThreadPoolBulkheadConfig config = ThreadPoolBulkheadConfig.ofDefaults();
System.out.println("Max thread pool size = " + config.getMaxThreadPoolSize());
System.out.println("Max core thread pool size = " + config.getCoreThreadPoolSize());
System.out.println("Keep alive duration = " + config.getKeepAliveDuration());
System.out.println("Queue capacity = " + config.getQueueCapacity());
}
void basicExample() {
ThreadPoolBulkheadConfig config = ThreadPoolBulkheadConfig.custom()
.maxThreadPoolSize(2)
.coreThreadPoolSize(1)
.queueCapacity(1)
.build();
ThreadPoolBulkheadRegistry registry = ThreadPoolBulkheadRegistry.of(config);
ThreadPoolBulkhead bulkhead = registry.bulkhead("flightSearchService");
FlightSearchService service = new FlightSearchService();
SearchRequest request = new SearchRequest("NYC", "LAX", "09/30/2020");
Supplier<List<Flight>> flightsSupplier = () -> service.searchFlightsTakingOneSecond(request);
Supplier<CompletionStage<List<Flight>>> decoratedFlightsSupplier = ThreadPoolBulkhead.decorateSupplier(bulkhead, flightsSupplier);
for (int i=0; i<3; i++) {
decoratedFlightsSupplier
.get()
.whenComplete((r,t) -> {
if (r != null) {
System.out.println("Received results");
}
if (t != null) {
t.printStackTrace();
}
});
}
}
void basicExample_BulkheadFullException() {
ThreadPoolBulkheadConfig config = ThreadPoolBulkheadConfig.custom()
.maxThreadPoolSize(2)
.coreThreadPoolSize(1)
.queueCapacity(1)
.build();
ThreadPoolBulkheadRegistry registry = ThreadPoolBulkheadRegistry.of(config);
ThreadPoolBulkhead bulkhead = registry.bulkhead("flightSearchService");
FlightSearchService service = new FlightSearchService();
SearchRequest request = new SearchRequest("NYC", "LAX", "08/30/2020");
Supplier<List<Flight>> flightsSupplier = () -> service.searchFlightsTakingOneSecond(request);
Supplier<CompletionStage<List<Flight>>> decoratedFlightsSupplier = ThreadPoolBulkhead.decorateSupplier(bulkhead, flightsSupplier);
for (int i=0; i<4; i++) {
decoratedFlightsSupplier
.get()
.whenComplete((r,t) -> {
if (r != null) {
System.out.println("Received results");
}
if (t != null) {
t.printStackTrace();
}
});
}
}
void bulkheadException_WithStackTraceOff() {
ThreadPoolBulkheadConfig config = ThreadPoolBulkheadConfig.custom()
.maxThreadPoolSize(2)
.coreThreadPoolSize(1)
.queueCapacity(1)
.writableStackTraceEnabled(false)
.build();
ThreadPoolBulkheadRegistry registry = ThreadPoolBulkheadRegistry.of(config);
ThreadPoolBulkhead bulkhead = registry.bulkhead("flightSearchService");
FlightSearchService service = new FlightSearchService();
SearchRequest request = new SearchRequest("NYC", "LAX", "09/30/2020");
Supplier<List<Flight>> flightsSupplier = () -> service.searchFlightsTakingOneSecond(request);
Supplier<CompletionStage<List<Flight>>> decoratedFlightsSupplier = ThreadPoolBulkhead.decorateSupplier(bulkhead, flightsSupplier);
for (int i=0; i<4; i++) {
decoratedFlightsSupplier
.get()
.whenComplete((r,t) -> {
if (r != null) {
System.out.println("Received results");
}
if (t != null) {
t.printStackTrace();
}
});
}
}
void metricsExample() {
ThreadPoolBulkheadConfig config = ThreadPoolBulkheadConfig.custom()
.maxThreadPoolSize(5)
.coreThreadPoolSize(3)
.queueCapacity(5)
.writableStackTraceEnabled(false)
.build();
ThreadPoolBulkheadRegistry registry = ThreadPoolBulkheadRegistry.of(config);
ThreadPoolBulkhead bulkhead = registry.bulkhead("flightSearchService");
MeterRegistry meterRegistry = new SimpleMeterRegistry();
TaggedThreadPoolBulkheadMetrics.ofThreadPoolBulkheadRegistry(registry).bindTo(meterRegistry);
bulkhead.getEventPublisher().onCallPermitted(e -> printMetricDetails(meterRegistry));
bulkhead.getEventPublisher().onCallRejected(e -> printMetricDetails(meterRegistry));
bulkhead.getEventPublisher().onCallFinished(e -> printMetricDetails(meterRegistry));
FlightSearchService service = new FlightSearchService();
SearchRequest request = new SearchRequest("NYC", "LAX", "09/30/2020");
Supplier<List<Flight>> flightsSupplier = () -> service.searchFlightsTakingOneSecond(request);
Supplier<CompletionStage<List<Flight>>> decoratedFlightsSupplier = ThreadPoolBulkhead.decorateSupplier(bulkhead, flightsSupplier);
for (int i=0; i<11; i++) {
decoratedFlightsSupplier
.get()
.whenComplete((r,t) -> {
if (r != null) {
System.out.println("Received results");
}
if (t != null) {
t.printStackTrace();
}
});
}
}
void contextPropagationExample_WithoutContextPropagator() {
ThreadPoolBulkheadConfig config = ThreadPoolBulkheadConfig.custom()
.maxThreadPoolSize(2)
.coreThreadPoolSize(1)
.queueCapacity(1)
.build();
ThreadPoolBulkheadRegistry registry = ThreadPoolBulkheadRegistry.of(config);
ThreadPoolBulkhead bulkhead = registry.bulkhead("flightSearchService");
FlightSearchService service = new FlightSearchService();
SearchRequest request = new SearchRequest("NYC", "LAX", "09/30/2020");
Supplier<List<Flight>> flightsSupplier = () -> service.searchFlightsTakingOneSecond_PrintCorrelationId(request);
Supplier<CompletionStage<List<Flight>>> decoratedFlightsSupplier = ThreadPoolBulkhead.decorateSupplier(bulkhead, flightsSupplier);
for (int i=0; i<2; i++) {
String trackingId = UUID.randomUUID().toString();
System.out.println("Setting trackingId " + trackingId + " on parent, main thread before calling flight search");
RequestTrackingIdHolder.setRequestTrackingId(trackingId);
decoratedFlightsSupplier
.get()
.whenComplete((r,t) -> {
if (r != null) {
System.out.println("Received results");
}
if (t != null) {
t.printStackTrace();
}
});
}
}
void contextPropagationExample_WithPropagation() {
ThreadPoolBulkheadConfig config = ThreadPoolBulkheadConfig.custom()
.maxThreadPoolSize(2)
.coreThreadPoolSize(1)
.queueCapacity(1)
.contextPropagator(new RequestTrackingIdPropagator())
.build();
ThreadPoolBulkheadRegistry registry = ThreadPoolBulkheadRegistry.of(config);
ThreadPoolBulkhead bulkhead = registry.bulkhead("flightSearchService");
FlightSearchService service = new FlightSearchService();
SearchRequest request = new SearchRequest("NYC", "LAX", "09/30/2020");
Supplier<List<Flight>> flightsSupplier = () -> service.searchFlightsTakingOneSecond_PrintCorrelationId(request);
Supplier<CompletionStage<List<Flight>>> decoratedFlightsSupplier = ThreadPoolBulkhead.decorateSupplier(bulkhead, flightsSupplier);
for (int i=0; i<2; i++) {
String trackingId = UUID.randomUUID().toString();
System.out.println("Setting trackingId " + trackingId + " on parent, main thread before calling flight search");
RequestTrackingIdHolder.setRequestTrackingId(trackingId);
decoratedFlightsSupplier
.get()
.whenComplete((r,t) -> {
if (r != null) {
System.out.println("Received results");
}
if (t != null) {
t.printStackTrace();
}
});
}
}
void printMetricDetails(MeterRegistry meterRegistry) {
Consumer<Meter> meterConsumer = meter -> {
String desc = meter.getId().getDescription();
String metricName = meter.getId().getName();
Double metricValue = StreamSupport.stream(meter.measure().spliterator(), false)
.filter(m -> m.getStatistic().name().equals("VALUE"))
.findFirst()
.map(m -> m.getValue())
.orElse(0.0);
System.out.println(desc + " - " + metricName + ": " + metricValue);
};
meterRegistry.forEachMeter(meterConsumer);
}
static void delay(int seconds) {
// sleep to simulate delay
try {
Thread.sleep(seconds * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main( String[] args )
{
ThreadpoolBulkheadExamples examples = new ThreadpoolBulkheadExamples();
System.out.println("---------------------------- printDefaultValues -------------------------------------------");
examples.printDefaultValues();
System.out.println("-----------------------------------------------------------------------");
System.out.println("---------------------------- basicExample -------------------------------------------");
examples.basicExample();
delay(5);
System.out.println("-----------------------------------------------------------------------");
System.out.println("---------------------------- basicExample_BulkheadFullException -------------------------------------------");
try {
examples.basicExample_BulkheadFullException();
}
catch (Exception e) {
// do nothing
}
delay(10);
System.out.println("-----------------------------------------------------------------------");
System.out.println("---------------------------- bulkheadException_WithStackTraceOff -------------------------------------------");
try {
examples.bulkheadException_WithStackTraceOff();
}
catch (Exception e) {
// do nothing
}
delay(10);
System.out.println("-----------------------------------------------------------------------");
System.out.println("---------------------------- metricsExample -------------------------------------------");
try {
examples.metricsExample();
}
catch (Exception e) {
}
delay(15);
System.out.println("-----------------------------------------------------------------------");
System.out.println("---------------------------- contextPropagationExample_WithoutContextPropagator -------------------------------------------");
examples.contextPropagationExample_WithoutContextPropagator();
System.out.println("-----------------------------------------------------------------------");
System.out.println("---------------------------- contextPropagationExample_WithPropagation -------------------------------------------");
examples.contextPropagationExample_WithPropagation();
delay(10);
System.out.println("-----------------------------------------------------------------------");
}
}

View File

@@ -0,0 +1,60 @@
package io.reflectoring.resilience4j.bulkhead.model;
public class Flight {
String flightNumber;
String flightDate;
String from;
String to;
public Flight() {
}
public Flight(String flightNumber, String flightDate, String from, String to) {
this.flightNumber = flightNumber;
this.flightDate = flightDate;
this.from = from;
this.to = to;
}
public String getFlightNumber() {
return flightNumber;
}
public void setFlightNumber(String flightNumber) {
this.flightNumber = flightNumber;
}
public String getFlightDate() {
return flightDate;
}
public void setFlightDate(String flightDate) {
this.flightDate = flightDate;
}
public String getFrom() {
return from;
}
public void setFrom(String from) {
this.from = from;
}
public String getTo() {
return to;
}
public void setTo(String to) {
this.to = to;
}
@Override
public String toString() {
return "Flight{" +
"flightNumber='" + flightNumber + '\'' +
", flightDate='" + flightDate + '\'' +
", from='" + from + '\'' +
", to='" + to + '\'' +
'}';
}
}

View File

@@ -0,0 +1,25 @@
package io.reflectoring.resilience4j.bulkhead.model;
public class SearchRequest {
String from;
String to;
String flightDate;
public SearchRequest(String from, String to, String flightDate) {
this.from = from;
this.to = to;
this.flightDate = flightDate;
}
public String getFrom() {
return from;
}
public String getTo() {
return to;
}
public String getFlightDate() {
return flightDate;
}
}

View File

@@ -0,0 +1,70 @@
package io.reflectoring.resilience4j.bulkhead.services;
import io.reflectoring.resilience4j.bulkhead.model.Flight;
import io.reflectoring.resilience4j.bulkhead.model.SearchRequest;
import io.reflectoring.resilience4j.bulkhead.utils.RequestTrackingIdHolder;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
public class FlightSearchService {
Random random = new Random();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss SSS");
public List<Flight> searchFlightsTakingRandomTime(SearchRequest request) {
long delay = random.nextInt(3000);
try {
Thread.sleep(delay);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Searching for flights; "
+ "current time = " + LocalDateTime.now().format(formatter) +
"; current thread = " + Thread.currentThread().getName());
List<Flight> flights = Arrays.asList(
new Flight("XY 765", request.getFlightDate(), request.getFrom(), request.getTo()),
new Flight("XY 746", request.getFlightDate(), request.getFrom(), request.getTo())
);
System.out.println("Flight search successful");
return flights;
}
public List<Flight> searchFlightsTakingOneSecond(SearchRequest request) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Searching for flights; "
+ "current time = " + LocalDateTime.now().format(formatter) +
"; current thread = " + Thread.currentThread().getName());
List<Flight> flights = Arrays.asList(
new Flight("XY 765", request.getFlightDate(), request.getFrom(), request.getTo()),
new Flight("XY 746", request.getFlightDate(), request.getFrom(), request.getTo())
);
System.out.println("Flight search successful at " + LocalDateTime.now().format(formatter));
return flights;
}
public List<Flight> searchFlightsTakingOneSecond_PrintCorrelationId(SearchRequest request) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Searching for flights; "
+ "current time = " + LocalDateTime.now().format(formatter) +
"; current thread = " + Thread.currentThread().getName() + "; Request Tracking Id = " + RequestTrackingIdHolder.getRequestTrackingId());
List<Flight> flights = Arrays.asList(
new Flight("XY 765", request.getFlightDate(), request.getFrom(), request.getTo()),
new Flight("XY 746", request.getFlightDate(), request.getFrom(), request.getTo())
);
System.out.println("Flight search successful at " + LocalDateTime.now().format(formatter));
return flights;
}
}

View File

@@ -0,0 +1,22 @@
package io.reflectoring.resilience4j.bulkhead.utils;
public class RequestTrackingIdHolder {
private static ThreadLocal<String> threadLocal = new ThreadLocal<>();
public static String getRequestTrackingId() {
return threadLocal.get();
}
public static void setRequestTrackingId(String id) {
if (threadLocal.get() != null) {
threadLocal.set(null);
threadLocal.remove();
}
threadLocal.set(id);
}
public static void clear() {
threadLocal.set(null);
threadLocal.remove();
}
}

View File

@@ -0,0 +1,30 @@
package io.reflectoring.resilience4j.bulkhead.utils;
import io.github.resilience4j.bulkhead.ContextPropagator;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Supplier;
public class RequestTrackingIdPropagator implements ContextPropagator {
@Override
public Supplier<Optional> retrieve() {
System.out.println("Getting request tracking id from thread: " + Thread.currentThread().getName());
return () -> Optional.of(RequestTrackingIdHolder.getRequestTrackingId());
}
@Override
public Consumer<Optional> copy() {
return optional -> {
System.out.println("Setting request tracking id " + optional.get() + " on thread: " + Thread.currentThread().getName());
optional.ifPresent(s -> RequestTrackingIdHolder.setRequestTrackingId(s.toString()));
};
}
@Override
public Consumer<Optional> clear() {
return optional -> {
System.out.println("Clearing request tracking id on thread: " + Thread.currentThread().getName());
optional.ifPresent(s -> RequestTrackingIdHolder.clear());
};
}
}

View File

@@ -13,8 +13,6 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- <maven.compiler.source>1.8</maven.compiler.source>-->
<!-- <maven.compiler.target>1.8</maven.compiler.target>-->
<maven.compiler.release>11</maven.compiler.release>
</properties>

View File

@@ -0,0 +1,117 @@
/*
* Copyright 2007-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.net.*;
import java.io.*;
import java.nio.channels.*;
import java.util.Properties;
public class MavenWrapperDownloader {
private static final String WRAPPER_VERSION = "0.5.6";
/**
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
*/
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
/**
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
* use instead of the default one.
*/
private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
".mvn/wrapper/maven-wrapper.properties";
/**
* Path where the maven-wrapper.jar will be saved to.
*/
private static final String MAVEN_WRAPPER_JAR_PATH =
".mvn/wrapper/maven-wrapper.jar";
/**
* Name of the property which should be used to override the default download url for the wrapper.
*/
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
public static void main(String args[]) {
System.out.println("- Downloader started");
File baseDirectory = new File(args[0]);
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
// If the maven-wrapper.properties exists, read it and check if it contains a custom
// wrapperUrl parameter.
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
String url = DEFAULT_DOWNLOAD_URL;
if(mavenWrapperPropertyFile.exists()) {
FileInputStream mavenWrapperPropertyFileInputStream = null;
try {
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
Properties mavenWrapperProperties = new Properties();
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
} catch (IOException e) {
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
} finally {
try {
if(mavenWrapperPropertyFileInputStream != null) {
mavenWrapperPropertyFileInputStream.close();
}
} catch (IOException e) {
// Ignore ...
}
}
}
System.out.println("- Downloading from: " + url);
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
if(!outputFile.getParentFile().exists()) {
if(!outputFile.getParentFile().mkdirs()) {
System.out.println(
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
}
}
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
try {
downloadFileFromURL(url, outputFile);
System.out.println("Done");
System.exit(0);
} catch (Throwable e) {
System.out.println("- Error downloading");
e.printStackTrace();
System.exit(1);
}
}
private static void downloadFileFromURL(String urlString, File destination) throws Exception {
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
String username = System.getenv("MVNW_USERNAME");
char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
}
URL website = new URL(urlString);
ReadableByteChannel rbc;
rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream(destination);
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
fos.close();
rbc.close();
}
}

Binary file not shown.

View File

@@ -0,0 +1,2 @@
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar

View File

@@ -0,0 +1,5 @@
Code for the examples used in the article at
https://reflectoring.io/time-limiting-with-resilience4j
Run the Examples program.

310
resilience4j/timelimiter/mvnw vendored Executable file
View File

@@ -0,0 +1,310 @@
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Maven Start Up Batch script
#
# Required ENV vars:
# ------------------
# JAVA_HOME - location of a JDK home dir
#
# Optional ENV vars
# -----------------
# M2_HOME - location of maven2's installed home dir
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
# e.g. to debug Maven itself, use
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ] ; then
if [ -f /etc/mavenrc ] ; then
. /etc/mavenrc
fi
if [ -f "$HOME/.mavenrc" ] ; then
. "$HOME/.mavenrc"
fi
fi
# OS specific support. $var _must_ be set to either true or false.
cygwin=false;
darwin=false;
mingw=false
case "`uname`" in
CYGWIN*) cygwin=true ;;
MINGW*) mingw=true;;
Darwin*) darwin=true
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
if [ -z "$JAVA_HOME" ]; then
if [ -x "/usr/libexec/java_home" ]; then
export JAVA_HOME="`/usr/libexec/java_home`"
else
export JAVA_HOME="/Library/Java/Home"
fi
fi
;;
esac
if [ -z "$JAVA_HOME" ] ; then
if [ -r /etc/gentoo-release ] ; then
JAVA_HOME=`java-config --jre-home`
fi
fi
if [ -z "$M2_HOME" ] ; then
## resolve links - $0 may be a link to maven's home
PRG="$0"
# need this for relative symlinks
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG="`dirname "$PRG"`/$link"
fi
done
saveddir=`pwd`
M2_HOME=`dirname "$PRG"`/..
# make it fully qualified
M2_HOME=`cd "$M2_HOME" && pwd`
cd "$saveddir"
# echo Using m2 at $M2_HOME
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --unix "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
fi
# For Mingw, ensure paths are in UNIX format before anything is touched
if $mingw ; then
[ -n "$M2_HOME" ] &&
M2_HOME="`(cd "$M2_HOME"; pwd)`"
[ -n "$JAVA_HOME" ] &&
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
fi
if [ -z "$JAVA_HOME" ]; then
javaExecutable="`which javac`"
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
# readlink(1) is not available as standard on Solaris 10.
readLink=`which readlink`
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
if $darwin ; then
javaHome="`dirname \"$javaExecutable\"`"
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
else
javaExecutable="`readlink -f \"$javaExecutable\"`"
fi
javaHome="`dirname \"$javaExecutable\"`"
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
JAVA_HOME="$javaHome"
export JAVA_HOME
fi
fi
fi
if [ -z "$JAVACMD" ] ; then
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD="`which java`"
fi
fi
if [ ! -x "$JAVACMD" ] ; then
echo "Error: JAVA_HOME is not defined correctly." >&2
echo " We cannot execute $JAVACMD" >&2
exit 1
fi
if [ -z "$JAVA_HOME" ] ; then
echo "Warning: JAVA_HOME environment variable is not set."
fi
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
if [ -z "$1" ]
then
echo "Path not specified to find_maven_basedir"
return 1
fi
basedir="$1"
wdir="$1"
while [ "$wdir" != '/' ] ; do
if [ -d "$wdir"/.mvn ] ; then
basedir=$wdir
break
fi
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
if [ -d "${wdir}" ]; then
wdir=`cd "$wdir/.."; pwd`
fi
# end of workaround
done
echo "${basedir}"
}
# concatenates all lines of a file
concat_lines() {
if [ -f "$1" ]; then
echo "$(tr -s '\n' ' ' < "$1")"
fi
}
BASE_DIR=`find_maven_basedir "$(pwd)"`
if [ -z "$BASE_DIR" ]; then
exit 1;
fi
##########################################################################################
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
# This allows using the maven wrapper in projects that prohibit checking in binary data.
##########################################################################################
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found .mvn/wrapper/maven-wrapper.jar"
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
fi
if [ -n "$MVNW_REPOURL" ]; then
jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
else
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
fi
while IFS="=" read key value; do
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
esac
done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
if [ "$MVNW_VERBOSE" = true ]; then
echo "Downloading from: $jarUrl"
fi
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
if $cygwin; then
wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
fi
if command -v wget > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found wget ... using wget"
fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
wget "$jarUrl" -O "$wrapperJarPath"
else
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
fi
elif command -v curl > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found curl ... using curl"
fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
curl -o "$wrapperJarPath" "$jarUrl" -f
else
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Falling back to using Java to download"
fi
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
# For Cygwin, switch paths to Windows format before running javac
if $cygwin; then
javaClass=`cygpath --path --windows "$javaClass"`
fi
if [ -e "$javaClass" ]; then
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Compiling MavenWrapperDownloader.java ..."
fi
# Compiling the Java class
("$JAVA_HOME/bin/javac" "$javaClass")
fi
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
# Running the downloader
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Running MavenWrapperDownloader.java ..."
fi
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
fi
fi
fi
fi
##########################################################################################
# End of extension
##########################################################################################
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
if [ "$MVNW_VERBOSE" = true ]; then
echo $MAVEN_PROJECTBASEDIR
fi
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --path --windows "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
fi
# Provide a "standardized" way to retrieve the CLI args that will
# work with both Windows and non-Windows executions.
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
export MAVEN_CMD_LINE_ARGS
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
exec "$JAVACMD" \
$MAVEN_OPTS \
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"

182
resilience4j/timelimiter/mvnw.cmd vendored Normal file
View File

@@ -0,0 +1,182 @@
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM http://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Maven Start Up Batch script
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM M2_HOME - location of maven2's installed home dir
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM set title of command window
title %0
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
:skipRcPre
@setlocal
set ERROR_CODE=0
@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
echo.
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init
echo.
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
@REM ==== END VALIDATION ====
:init
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir
:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir
:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"
:endDetectBaseDir
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
:endReadAdditionalConfig
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
)
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
if "%MVNW_VERBOSE%" == "true" (
echo Found %WRAPPER_JAR%
)
) else (
if not "%MVNW_REPOURL%" == "" (
SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
)
if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %DOWNLOAD_URL%
)
powershell -Command "&{"^
"$webclient = new-object System.Net.WebClient;"^
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
"}"^
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
"}"
if "%MVNW_VERBOSE%" == "true" (
echo Finished downloading %WRAPPER_JAR%
)
)
@REM End of extension
@REM Provide a "standardized" way to retrieve the CLI args that will
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
:error
set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%" == "on" pause
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
exit /B %ERROR_CODE%

View File

@@ -0,0 +1,117 @@
<?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>
<groupId>io.reflectoring.resilience4j.timelimiter</groupId>
<artifactId>timelimiter</artifactId>
<version>1.0-SNAPSHOT</version>
<name>timelimiter</name>
<url>https://reflectoring.io</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.release>11</maven.compiler.release>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/io.github.resilience4j/resilience4j-retry -->
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-timelimiter</artifactId>
<version>1.5.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.github.resilience4j/resilience4j-core -->
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-core</artifactId>
<version>1.5.0</version>
</dependency>
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-all</artifactId>
<version>1.5.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.github.resilience4j/resilience4j-micrometer -->
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-micrometer</artifactId>
<version>1.5.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.micrometer/micrometer-core -->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-core</artifactId>
<version>1.5.0</version>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<release>11</release>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

View File

@@ -0,0 +1,324 @@
package io.reflectoring.resilience4j.timelimiter;
import io.github.resilience4j.micrometer.tagged.TaggedTimeLimiterMetrics;
import io.github.resilience4j.timelimiter.TimeLimiter;
import io.github.resilience4j.timelimiter.TimeLimiterConfig;
import io.github.resilience4j.timelimiter.TimeLimiterRegistry;
import io.micrometer.core.instrument.Measurement;
import io.micrometer.core.instrument.Meter;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
import io.reflectoring.resilience4j.timelimiter.model.Flight;
import io.reflectoring.resilience4j.timelimiter.model.SearchRequest;
import io.reflectoring.resilience4j.timelimiter.services.FlightSearchService;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.StreamSupport;
public class Examples {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss SSS");
void printDefaultValues() {
TimeLimiterConfig config = TimeLimiterConfig.ofDefaults();
System.out.println(
"getTimeoutDuration in ms = " + Duration.from(config.getTimeoutDuration()).toMillis());
System.out.println("shouldCancelRunningFuture = " + config.shouldCancelRunningFuture());
}
void basicExample_Successful() {
TimeLimiterConfig config = TimeLimiterConfig.custom()
.timeoutDuration(Duration.ofSeconds(2))
.build();
TimeLimiterRegistry registry = TimeLimiterRegistry.of(config);
TimeLimiter limiter = registry.timeLimiter("flightSearch");
FlightSearchService service = new FlightSearchService();
SearchRequest request = new SearchRequest("NYC", "LAX", "08/30/2020");
Supplier<List<Flight>> flightSupplier = () -> service.searchFlightsTakingOneSecond(request);
Supplier<CompletionStage<List<Flight>>> origCompletionStageSupplier = () -> CompletableFuture
.supplyAsync(flightSupplier);
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
Supplier<CompletionStage<List<Flight>>> decoratedCompletionStageSupplier = limiter
.decorateCompletionStage(scheduler, origCompletionStageSupplier);
decoratedCompletionStageSupplier.get().whenComplete((result, ex) -> {
if (ex != null) {
System.out.println("Exception " +
ex.getMessage() +
" on thread " +
Thread.currentThread().getName() +
" at " +
LocalDateTime.now().format(formatter));
}
if (result != null) {
System.out.println(result + " on thread " + Thread.currentThread().getName());
}
});
scheduler.shutdown();
}
void basicExample_TimeoutException() {
TimeLimiterConfig config = TimeLimiterConfig.custom()
.timeoutDuration(Duration.ofMillis(500))
.build();
TimeLimiterRegistry registry = TimeLimiterRegistry.of(config);
TimeLimiter limiter = registry.timeLimiter("flightSearch");
FlightSearchService service = new FlightSearchService();
SearchRequest request = new SearchRequest("NYC", "LAX", "08/30/2020");
Supplier<List<Flight>> flightSupplier = () -> service.searchFlightsTakingOneSecond(request);
Supplier<CompletionStage<List<Flight>>> origCompletionStageSupplier = () -> CompletableFuture
.supplyAsync(flightSupplier);
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
Supplier<CompletionStage<List<Flight>>> decoratedCompletionStageSupplier = limiter
.decorateCompletionStage(scheduler, origCompletionStageSupplier);
decoratedCompletionStageSupplier.get().whenComplete((result, ex) -> {
if (ex != null) {
System.out.println("Exception " +
ex.getMessage() +
" on thread " +
Thread.currentThread().getName() +
" at " +
LocalDateTime.now().format(formatter));
}
if (result != null) {
System.out.println(result + " on thread " + Thread.currentThread().getName());
}
});
scheduler.shutdown();
}
void basicExample_ExcecuteCompletionStage() {
TimeLimiterConfig config = TimeLimiterConfig.custom()
.timeoutDuration(Duration.ofMillis(500))
.build();
TimeLimiterRegistry registry = TimeLimiterRegistry.of(config);
TimeLimiter limiter = registry.timeLimiter("flightSearch");
FlightSearchService service = new FlightSearchService();
SearchRequest request = new SearchRequest("NYC", "LAX", "08/30/2020");
Supplier<List<Flight>> flightSupplier = () -> service.searchFlightsTakingOneSecond(request);
Supplier<CompletionStage<List<Flight>>> origCompletionStageSupplier = () -> CompletableFuture
.supplyAsync(flightSupplier);
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
CompletionStage<List<Flight>> decoratedCompletionStage = limiter
.executeCompletionStage(scheduler, origCompletionStageSupplier);
decoratedCompletionStage.whenComplete((result, ex) -> {
if (ex != null) {
System.out.println("Exception " +
ex.getMessage() +
" on thread " +
Thread.currentThread().getName() +
" at " +
LocalDateTime.now().format(formatter));
}
if (result != null) {
System.out.println(result + " on thread " + Thread.currentThread().getName());
}
});
scheduler.shutdown();
}
void whenToUseExample() {
CompletableFuture.supplyAsync(this::slowMethod).thenAccept(System.out::println);
}
void whenToUseExample_Blocking()
throws InterruptedException, ExecutionException, TimeoutException {
CompletableFuture<Integer> completableFuture = CompletableFuture
.supplyAsync(this::slowMethod);
Integer result = completableFuture.get(3000, TimeUnit.MILLISECONDS);
System.out.println(result);
}
int slowMethod() {
System.out.println(Thread.currentThread().getName());
// sleep to simulate delay
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 0;
}
static void delay(int seconds) {
// sleep to simulate delay
try {
Thread.sleep(seconds * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
void eventsExample() {
TimeLimiterConfig config = TimeLimiterConfig.custom()
.cancelRunningFuture(false)
.timeoutDuration(Duration.ofSeconds(2))
.build();
TimeLimiterRegistry registry = TimeLimiterRegistry.of(config);
TimeLimiter limiter = registry.timeLimiter("flightSearch");
limiter.getEventPublisher().onSuccess(e -> System.out.println(e.toString()));
limiter.getEventPublisher().onError(e -> System.out.println(e.toString()));
limiter.getEventPublisher().onTimeout(e -> System.out.println(e.toString()));
FlightSearchService service = new FlightSearchService();
SearchRequest request = new SearchRequest("NYC", "LAX", "07/31/2020");
Supplier<List<Flight>> flightsSupplier = () -> service.searchFlightsTakingRandomTime(request);
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
Supplier<CompletionStage<List<Flight>>> origCompletionStageSupplier = () -> CompletableFuture
.supplyAsync(flightsSupplier);
Supplier<CompletionStage<List<Flight>>> decoratedCompletionStageSupplier = limiter
.decorateCompletionStage(scheduler, origCompletionStageSupplier);
for (int i = 0; i < 10; i++) {
int attempt = i;
decoratedCompletionStageSupplier
.get()
.whenComplete((r, t) -> {
if (t != null) {
System.out.println("Error occurred on search " + attempt + ": " + t.getMessage());
}
if (r != null) {
System.out
.println("Search " + attempt + " successful, found " + r.size() + " flights");
}
});
}
scheduler.shutdown();
}
void metricsExample() {
TimeLimiterConfig config = TimeLimiterConfig.custom()
.cancelRunningFuture(false)
.timeoutDuration(Duration.ofSeconds(2))
.build();
TimeLimiterRegistry registry = TimeLimiterRegistry.of(config);
TimeLimiter limiter = registry.timeLimiter("flightSearch");
MeterRegistry meterRegistry = new SimpleMeterRegistry();
TaggedTimeLimiterMetrics.ofTimeLimiterRegistry(registry).bindTo(meterRegistry);
FlightSearchService service = new FlightSearchService();
SearchRequest request = new SearchRequest("NYC", "LAX", "07/31/2020");
Supplier<List<Flight>> flightsSupplier = () -> service.searchFlightsTakingRandomTime(request);
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
Supplier<CompletionStage<List<Flight>>> origCompletionStageSupplier = () -> CompletableFuture
.supplyAsync(flightsSupplier);
Supplier<CompletionStage<List<Flight>>> decoratedCompletionStageSupplier = limiter
.decorateCompletionStage(scheduler, origCompletionStageSupplier);
List<CompletableFuture<List<Flight>>> futures = new ArrayList<>();
for (int i = 0; i < 10; i++) {
int attempt = i;
CompletionStage<List<Flight>> stage = decoratedCompletionStageSupplier
.get()
.whenComplete((r, t) -> {
if (t != null) {
System.out.println("Error occurred on search " + attempt + ": " + t.getMessage());
}
if (r != null) {
System.out
.println("Search " + attempt + " successful, found " + r.size() + " flights");
}
});
futures.add(stage.toCompletableFuture());
}
CompletableFuture
.allOf(futures.toArray(new CompletableFuture[0]))
.whenComplete((r, t) -> printMetricDetails(meterRegistry));
scheduler.shutdown();
}
void printMetricDetails(MeterRegistry meterRegistry) {
Consumer<Meter> meterConsumer = meter -> {
String desc = meter.getId().getDescription();
String metricName = meter.getId().getName();
String metricKind = meter.getId().getTag("kind");
Double metricValue = StreamSupport.stream(meter.measure().spliterator(), false)
.filter(m -> m.getStatistic().name().equals("COUNT"))
.findFirst()
.map(Measurement::getValue)
.orElse(0.0);
System.out.println(desc + " - " + metricName + "(" + metricKind + ")" + ": " + metricValue);
};
meterRegistry.forEachMeter(meterConsumer);
}
public static void main(String[] args) {
Examples examples = new Examples();
System.out.println("----------------------------------------------------------------------------------------------------");
System.out.println("----------------------- printDefaultValues ----------------------------------------------------");
examples.printDefaultValues();
System.out.println("----------------------------------------------------------------------------------------------------");
System.out.println("----------------------- whenToUseExample ----------------------------------------------------");
examples.whenToUseExample();
delay(2); // delay just to let the above async operation to complete
System.out.println("----------------------------------------------------------------------------------------------------");
System.out.println("----------------------- whenToUseExample_Blocking ----------------------------------------------------");
try {
examples.whenToUseExample_Blocking();
} catch (InterruptedException | ExecutionException| TimeoutException e) {
e.printStackTrace();
}
delay(2); // delay just to let the above async operation to complete
System.out.println("----------------------------------------------------------------------------------------------------");
System.out.println("----------------------- basicExample_Successful ----------------------------------------------------");
examples.basicExample_Successful();
delay(2); // delay just to let the above async operation to complete
System.out.println("----------------------------------------------------------------------------------------------------");
System.out.println("----------------------- basicExample_TimeoutException ----------------------------------------------");
examples.basicExample_TimeoutException();
delay(2); // delay just to let the above async operation to complete
System.out.println("----------------------------------------------------------------------------------------------------");
System.out.println("-------------------------basicExample_ExcecuteCompletionStage --------------------------------------");
examples.basicExample_ExcecuteCompletionStage();
delay(2); // delay just to let the above async operation to complete
System.out.println("----------------------------------------------------------------------------------------------------");
System.out.println("----------------------- eventsExample ----------------------------------------------------");
examples.eventsExample();
delay(10); // delay just to let the above async operation to complete
System.out.println("----------------------------------------------------------------------------------------------------");
System.out.println("----------------------- metricsExample ----------------------------------------------------");
examples.metricsExample();
delay(10); // delay just to let the above async operation to complete
System.out.println("----------------------------------------------------------------------------------------------------");
}
}

View File

@@ -0,0 +1,60 @@
package io.reflectoring.resilience4j.timelimiter.model;
public class Flight {
String flightNumber;
String flightDate;
String from;
String to;
public Flight() {
}
public Flight(String flightNumber, String flightDate, String from, String to) {
this.flightNumber = flightNumber;
this.flightDate = flightDate;
this.from = from;
this.to = to;
}
public String getFlightNumber() {
return flightNumber;
}
public void setFlightNumber(String flightNumber) {
this.flightNumber = flightNumber;
}
public String getFlightDate() {
return flightDate;
}
public void setFlightDate(String flightDate) {
this.flightDate = flightDate;
}
public String getFrom() {
return from;
}
public void setFrom(String from) {
this.from = from;
}
public String getTo() {
return to;
}
public void setTo(String to) {
this.to = to;
}
@Override
public String toString() {
return "Flight{" +
"flightNumber='" + flightNumber + '\'' +
", flightDate='" + flightDate + '\'' +
", from='" + from + '\'' +
", to='" + to + '\'' +
'}';
}
}

View File

@@ -0,0 +1,25 @@
package io.reflectoring.resilience4j.timelimiter.model;
public class SearchRequest {
String from;
String to;
String flightDate;
public SearchRequest(String from, String to, String flightDate) {
this.from = from;
this.to = to;
this.flightDate = flightDate;
}
public String getFrom() {
return from;
}
public String getTo() {
return to;
}
public String getFlightDate() {
return flightDate;
}
}

View File

@@ -0,0 +1,51 @@
package io.reflectoring.resilience4j.timelimiter.services;
import io.reflectoring.resilience4j.timelimiter.model.Flight;
import io.reflectoring.resilience4j.timelimiter.model.SearchRequest;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
public class FlightSearchService {
Random random = new Random();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss SSS");
public List<Flight> searchFlightsTakingRandomTime(SearchRequest request) {
long delay = random.nextInt(3000);
try {
Thread.sleep(delay);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Searching for flights; "
+ "current time = " + LocalDateTime.now().format(formatter) +
"; current thread = " + Thread.currentThread().getName());
List<Flight> flights = Arrays.asList(
new Flight("XY 765", request.getFlightDate(), request.getFrom(), request.getTo()),
new Flight("XY 746", request.getFlightDate(), request.getFrom(), request.getTo())
);
System.out.println("Flight search successful");
return flights;
}
public List<Flight> searchFlightsTakingOneSecond(SearchRequest request) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Searching for flights; "
+ "current time = " + LocalDateTime.now().format(formatter) +
"; current thread = " + Thread.currentThread().getName());
List<Flight> flights = Arrays.asList(
new Flight("XY 765", request.getFlightDate(), request.getFrom(), request.getTo()),
new Flight("XY 746", request.getFlightDate(), request.getFrom(), request.getTo())
);
System.out.println("Flight search successful at " + LocalDateTime.now().format(formatter));
return flights;
}
}

BIN
spring-boot/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,5 @@
# Custom Argument Resolvers with Spring Boot
## Blog posts
* [Custom Web Controller Arguments with Spring MVC and Spring Boot](https://reflectoring.io/spring-boot-argumentresolver/)

View File

@@ -2,4 +2,5 @@
This code shows how to hook in to the phases of the Spring bean lifecycle.
Read more in the Blog post: [Hooking into the Spring Bean Lifecycle](https://reflectoring.io/spring-bean-lifecycle)
## Blog Posts
* [Hooking into the Spring Bean Lifecycle](https://reflectoring.io/spring-bean-lifecycle)

View File

@@ -5,6 +5,7 @@ import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;
@Configuration
public class QuartzConfig {
@@ -12,17 +13,20 @@ public class QuartzConfig {
@Autowired
ApplicationContext applicationContext;
@Bean
public SpringBeanJobFactory springBeanJobFactory() {
AutowireCapableJobFactory jobFactory = new AutowireCapableJobFactory();
jobFactory.setApplicationContext(applicationContext);
return jobFactory;
}
/**
* Create custom {@link SchedulerFactoryBean} for Quartz
*/
@Bean
public SchedulerFactoryBean schedulerFactoryBean(){
AutowireCapableJobFactory jobFactory = new AutowireCapableJobFactory();
jobFactory.setApplicationContext(applicationContext);
SchedulerFactoryBean factoryBean = new SchedulerFactoryBean();
factoryBean.setJobFactory(jobFactory);
factoryBean.setJobFactory(springBeanJobFactory());
return factoryBean;
}

View File

@@ -0,0 +1,16 @@
package io.reflectoring.beanlifecycle.quartz;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.springframework.beans.factory.annotation.Autowired;
public class SampleJob implements Job {
@Autowired
private SampleServiceBean service;
@Override
public void execute(JobExecutionContext jobExecutionContext) {
service.hello();
}
}

View File

@@ -0,0 +1,16 @@
package io.reflectoring.beanlifecycle.quartz;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
@Service
public class SampleServiceBean {
Logger logger = LoggerFactory.getLogger(SampleServiceBean.class);
public void hello() {
logger.info("hello from Quartz Job!");
}
}

View File

@@ -0,0 +1,27 @@
package io.reflectoring.beanlifecycle.quartz;
import org.junit.jupiter.api.Test;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class SpringQuartzTests {
@Autowired
Scheduler quartzScheduler;
@Test
public void testQuartzJobHasCapabaleOfAutowireSpringBeans() throws SchedulerException, InterruptedException {
JobDetail jobDetail = JobBuilder.newJob(SampleJob.class).build();
Trigger trigger = TriggerBuilder.newTrigger()
.withSchedule(SimpleScheduleBuilder.repeatSecondlyForever())
.startNow().build();
quartzScheduler.scheduleJob(jobDetail, trigger);
Thread.sleep(5000);
}
}

View File

@@ -0,0 +1,5 @@
# Clean Architecture Boundaries with Spring Boot and ArchUnit
## Blog posts
* [Clean Architecture Boundaries with Spring Boot and ArchUnit](https://reflectoring.io/java-components-clean-boundaries/)

3
spring-boot/cache/README.md vendored Normal file
View File

@@ -0,0 +1,3 @@
# Related Blog Posts
* [Implementing a Cache with Spring Boot](https://reflectoring.io/spring-boot-cache/)

View File

@@ -3,6 +3,7 @@ package io.reflectoring.cache.rest;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.reflectoring.cache.AbstractIntegrationTest;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
@@ -17,6 +18,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
@SpringBootTest
@AutoConfigureMockMvc
@ActiveProfiles("client")
@Disabled("makes problems on Github Actions")
class CarResourceClientCacheIntegrationTest extends AbstractIntegrationTest {
@Autowired

View File

@@ -2,6 +2,7 @@ package io.reflectoring.cache.rest;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
@@ -16,6 +17,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
@SpringBootTest
@AutoConfigureMockMvc
@ActiveProfiles("embedded")
@Disabled("makes problems on Github Actions")
class CarResourceEmbeddedCacheIntegrationTest {
@Autowired

View File

@@ -0,0 +1,3 @@
# Related Blog Posts
* [Validate Spring Boot Configuration Parameters at Startup](https://reflectoring.io/validate-spring-boot-configuration-parameters-at-startup/)

View File

@@ -0,0 +1,4 @@
# Related Blog Posts
* [One-Stop Guide to Database Migration with Flyway and Spring Boot](https://reflectoring.io/database-migration-spring-boot-flyway/)
* [Tool-based Database Refactoring: Flyway vs. Liquibase](https://reflectoring.io/database-refactoring-flyway-vs-liquibase/)

View File

@@ -17,6 +17,11 @@ The project also demonstrates the following.
* It demonstrates use of liquibase [change log parameters](src/main/resources/db/changelog/db.changelog-yaml-example.yaml#L21-L33)
* IT demonstrates use of liquibase [context](src/main/resources/db/changelog/db.changelog-xml-example.xml#L5)
## Related Blog Posts
* [One-Stop Guide to Database Migration with Liquibase and Spring Boot](https://reflectoring.io/database-migration-spring-boot-liquibase/)
* [Tool-based Database Refactoring: Flyway vs. Liquibase](https://reflectoring.io/database-refactoring-flyway-vs-liquibase/)
## How to Run the project and tests
### Have Docker and Docker Compose in your machine?

View File

@@ -0,0 +1,3 @@
# Related Blog Posts
* [Why You Should Use Constructor Injection in Spring](https://reflectoring.io/constructor-injection/)

View File

@@ -0,0 +1,3 @@
# Related Blog Posts
* [https://reflectoring.io/spring-boot-hazelcast/](https://reflectoring.io/spring-boot-hazelcast/)

View File

@@ -0,0 +1,3 @@
# Related Blog Posts
* [https://reflectoring.io/spring-boot-hazelcast/](https://reflectoring.io/spring-boot-hazelcast/)

View File

@@ -0,0 +1,5 @@
# Hibernate Search Tutorial
This example code demonstrates the following:
* How to configure Hibernate search with Elasticsearch integration
* How to configure entities for indexing
* Some examples to queries

View File

@@ -0,0 +1,40 @@
plugins {
id 'org.springframework.boot' version '2.2.2.RELEASE'
id 'io.spring.dependency-management' version '1.0.10.RELEASE'
id 'java'
}
group = 'io.reflectoring'
version = '1.0.0'
sourceCompatibility = '11'
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.hibernate:hibernate-search-orm:5.11.5.Final'
implementation 'org.hibernate:hibernate-search-elasticsearch:5.11.5.Final'
implementation 'org.mapstruct:mapstruct:1.3.1.Final'
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.h2database:h2'
annotationProcessor 'org.projectlombok:lombok'
annotationProcessor 'org.mapstruct:mapstruct-processor:1.3.1.Final'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
test {
useJUnitPlatform()
}

Binary file not shown.

View File

@@ -0,0 +1,6 @@
#Mon Sep 07 12:46:19 IST 2020
distributionUrl=https\://services.gradle.org/distributions/gradle-6.4.1-all.zip
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME

184
spring-boot/hibernate-search/gradlew vendored Normal file
View File

@@ -0,0 +1,184 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
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
SAVED="$(pwd)"
cd "$(dirname \"$PRG\")/" >/dev/null
APP_HOME="$(pwd -P)"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=$(basename "$0")
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn() {
echo "$*"
}
die() {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$(uname)" in
CYGWIN*)
cygwin=true
;;
Darwin*)
darwin=true
;;
MINGW*)
msys=true
;;
NONSTOP*)
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
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
if [ ! -x "$JAVACMD" ]; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ]; then
MAX_FD_LIMIT=$(ulimit -H -n)
if [ $? -eq 0 ]; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ]; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ]; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ]; then
APP_HOME=$(cygpath --path --mixed "$APP_HOME")
CLASSPATH=$(cygpath --path --mixed "$CLASSPATH")
JAVACMD=$(cygpath --unix "$JAVACMD")
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=$(find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null)
SEP=""
for dir in $ROOTDIRSRAW; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ]; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@"; do
CHECK=$(echo "$arg" | egrep -c "$OURCYGPATTERN" -)
CHECK2=$(echo "$arg" | egrep -c "^-") ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ]; then ### Added a condition
eval $(echo args$i)=$(cygpath --path --ignore --mixed "$arg")
else
eval $(echo args$i)="\"$arg\""
fi
i=$(expr $i + 1)
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save() {
for i; do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/"; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"

104
spring-boot/hibernate-search/gradlew.bat vendored Normal file
View File

@@ -0,0 +1,104 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem 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, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@@ -0,0 +1 @@
rootProject.name = 'hibernate-search'

View File

@@ -0,0 +1,15 @@
package io.reflectoring.hibernatesearch;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class HibernateSearchApplication {
public static void main(String[] args) {
SpringApplication.run(HibernateSearchApplication.class, args);
}
}

View File

@@ -0,0 +1,25 @@
package io.reflectoring.hibernatesearch.configuration;
import io.reflectoring.hibernatesearch.service.IndexingService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
@Component
@Slf4j
@RequiredArgsConstructor
public class StartupEvent implements ApplicationListener<ApplicationReadyEvent> {
private final IndexingService service;
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
try {
service.initiateIndexing();
} catch (InterruptedException e) {
log.error("Failed to reindex entities ",e);
}
}
}

View File

@@ -0,0 +1,63 @@
package io.reflectoring.hibernatesearch.controller;
import io.reflectoring.hibernatesearch.controller.dto.PostResponse;
import io.reflectoring.hibernatesearch.controller.dto.UserResponse;
import io.reflectoring.hibernatesearch.controller.mapper.PostMapper;
import io.reflectoring.hibernatesearch.controller.mapper.UserMapper;
import io.reflectoring.hibernatesearch.service.IndexingService;
import io.reflectoring.hibernatesearch.service.SearchService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.stream.Collectors;
@RestController
@Slf4j
@RequiredArgsConstructor
class IndexController {
private final IndexingService indexingService;
private final SearchService searchService;
private final PostMapper postMapper;
private final UserMapper userMapper;
@PostMapping("/reindex")
public void reindex() throws InterruptedException {
indexingService.initiateIndexing();
}
@GetMapping("/user")
public List<UserResponse> getUser(@RequestParam String first,
@RequestParam Integer max,
@RequestParam Integer page){
return searchService.getUserByFirst(first, max, page)
.stream().map(userMapper::toResponse).collect(Collectors.toList());
}
@GetMapping("/user/projection")
public List<UserResponse> getProjectUser(@RequestParam String first,
@RequestParam Integer max,
@RequestParam Integer page){
return searchService.getUserByFirstWithProjection(first, max, page)
.stream().map(userMapper::toResponse).collect(Collectors.toList());
}
@GetMapping("/post")
public List<PostResponse> getPost(@RequestParam Long likeCount,
@RequestParam(required = false) String hashTags,
@RequestParam(required = false) String tag){
return searchService.getBasedOnLikeCountTags(likeCount, hashTags, tag)
.stream().map(postMapper::toResponse).collect(Collectors.toList());
}
@GetMapping("/post/word")
public List<PostResponse> getPostByWord(@RequestParam String word){
return searchService.getPostBasedOnWord(word)
.stream().map(postMapper::toResponse).collect(Collectors.toList());
}
}

View File

@@ -0,0 +1,21 @@
package io.reflectoring.hibernatesearch.controller.dto;
import io.reflectoring.hibernatesearch.domain.Tag;
import lombok.Getter;
import lombok.Setter;
import java.time.LocalDateTime;
@Getter
@Setter
public class PostResponse {
private String id;
private String body;
private UserResponse user;
private Tag tag;
private String imageUrl;
private String imageDescription;
private String hashTags;
private long likeCount;
private LocalDateTime createdAt;
}

View File

@@ -0,0 +1,14 @@
package io.reflectoring.hibernatesearch.controller.dto;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class UserResponse {
private String id;
private String first;
private String middle;
private String last;
private Integer age;
}

View File

@@ -0,0 +1,10 @@
package io.reflectoring.hibernatesearch.controller.mapper;
import io.reflectoring.hibernatesearch.controller.dto.PostResponse;
import io.reflectoring.hibernatesearch.domain.Post;
import org.mapstruct.Mapper;
@Mapper(componentModel = "spring", uses = UserMapper.class)
public interface PostMapper {
PostResponse toResponse(Post post);
}

View File

@@ -0,0 +1,10 @@
package io.reflectoring.hibernatesearch.controller.mapper;
import io.reflectoring.hibernatesearch.controller.dto.UserResponse;
import io.reflectoring.hibernatesearch.domain.User;
import org.mapstruct.Mapper;
@Mapper(componentModel = "spring")
public interface UserMapper {
UserResponse toResponse(User user);
}

View File

@@ -0,0 +1,47 @@
package io.reflectoring.hibernatesearch.domain;
import lombok.Getter;
import lombok.Setter;
import org.apache.lucene.analysis.core.LowerCaseFilterFactory;
import org.hibernate.search.annotations.*;
import javax.persistence.*;
import java.time.LocalDateTime;
@Getter
@Setter
@Entity
@Indexed(index = "idx_post")
@NormalizerDef(name = "lower",
filters = @TokenFilterDef(factory = LowerCaseFilterFactory.class))
public class Post {
@Id
private String id;
@Field(name = "body")
@Field(name = "bodyFiltered", analyzer = @Analyzer(definition = "stop"))
private String body;
@ManyToOne
@IndexedEmbedded
private User user;
@Field(normalizer = @Normalizer(definition = "lower"))
@Enumerated(EnumType.STRING)
private Tag tag;
private String imageUrl;
private String imageDescription;
@Field
private String hashTags;
@Field
@SortableField
private long likeCount;
@Field(analyze = Analyze.NO)
@SortableField
private LocalDateTime createdAt;
}

View File

@@ -0,0 +1,7 @@
package io.reflectoring.hibernatesearch.domain;
public enum Tag {
MOVIE,
MUSIC,
LITERATURE
}

View File

@@ -0,0 +1,37 @@
package io.reflectoring.hibernatesearch.domain;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.search.annotations.*;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import java.util.List;
@Getter
@Setter
@Entity
@Indexed(index = "idx_user")
public class User {
@Id
private String id;
@Field(store = Store.YES)
@Field(name = "fullName")
private String first;
@Field(index = Index.NO, store = Store.YES)
private String middle;
@Field(store = Store.YES)
@Field(name = "fullName")
private String last;
@Field
private Integer age;
@ContainedIn
@OneToMany(mappedBy = "user")
private List<Post> post;
}

View File

@@ -0,0 +1,26 @@
package io.reflectoring.hibernatesearch.service;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.search.jpa.FullTextEntityManager;
import org.hibernate.search.jpa.Search;
import org.springframework.stereotype.Service;
import javax.persistence.EntityManager;
import javax.transaction.Transactional;
@Service
@RequiredArgsConstructor
@Slf4j
public class IndexingService {
private final EntityManager em;
@Transactional
public void initiateIndexing() throws InterruptedException {
log.info("Initiating indexing...");
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(em);
fullTextEntityManager.createIndexer().startAndWait();
log.info("All entities indexed");
}
}

View File

@@ -0,0 +1,95 @@
package io.reflectoring.hibernatesearch.service;
import io.reflectoring.hibernatesearch.domain.Post;
import io.reflectoring.hibernatesearch.domain.User;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.lucene.search.Query;
import org.hibernate.search.jpa.FullTextEntityManager;
import org.hibernate.search.jpa.FullTextQuery;
import org.hibernate.search.jpa.Search;
import org.hibernate.search.query.dsl.QueryBuilder;
import org.springframework.stereotype.Component;
import javax.persistence.EntityManager;
import java.util.ArrayList;
import java.util.List;
@Component
@Slf4j
@RequiredArgsConstructor
public class SearchService {
private final EntityManager entityManager;
public List<Post> getBasedOnLikeCountTags(Long likeCount, String hashTags, String tag){
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager);
QueryBuilder qb = fullTextEntityManager.getSearchFactory().buildQueryBuilder()
.forEntity(Post.class)
.get();
Query likeCountGreater = qb.range().onField("likeCount").above(likeCount).createQuery();
Query hashTagsQuery = qb.keyword().onField("hashTags").matching(hashTags).createQuery();
Query tagQuery = qb.keyword().onField("tag").matching(tag).createQuery();
Query finalQuery = qb.bool().must(likeCountGreater).should(tagQuery).should(hashTagsQuery).createQuery();
FullTextQuery fullTextQuery = fullTextEntityManager.createFullTextQuery(finalQuery, Post.class);
fullTextQuery.setSort(qb.sort().byScore().createSort());
return (List<Post>) fullTextQuery.getResultList();
}
public List<Post> getPostBasedOnWord(String word){
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager);
QueryBuilder qb = fullTextEntityManager.getSearchFactory().buildQueryBuilder()
.forEntity(Post.class)
.get();
Query foodQuery = qb.keyword().onFields("bodyFiltered","hashTags").matching(word).createQuery();
FullTextQuery fullTextQuery = fullTextEntityManager.createFullTextQuery(foodQuery, Post.class);
return (List<Post>) fullTextQuery.getResultList();
}
public List<User> getUserByFirst(String first, int max, int page){
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager);
QueryBuilder qb = fullTextEntityManager.getSearchFactory().buildQueryBuilder()
.forEntity(User.class)
.get();
Query similarToUser = qb.keyword().wildcard().onField("first")
.matching(first).createQuery();
Query finalQuery = qb.bool().must(similarToUser).createQuery();
FullTextQuery fullTextQuery = fullTextEntityManager.createFullTextQuery(finalQuery, User.class);
fullTextQuery.setSort(qb.sort().byField("age").desc().andByScore().createSort());
fullTextQuery.setMaxResults(max);
fullTextQuery.setFirstResult(page);
return (List<User>) fullTextQuery.getResultList();
}
public List<User> getUserByFirstWithProjection(String first, int max, int page){
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager);
QueryBuilder qb = fullTextEntityManager.getSearchFactory().buildQueryBuilder()
.forEntity(User.class)
.get();
Query similarToUser = qb.keyword().fuzzy().withEditDistanceUpTo(2).onField("first")
.matching(first).createQuery();
Query finalQuery = qb.bool().must(similarToUser).createQuery();
FullTextQuery fullTextQuery = fullTextEntityManager.createFullTextQuery(finalQuery, User.class);
fullTextQuery.setProjection(FullTextQuery.ID, "first","last","middle","age");
fullTextQuery.setSort(qb.sort().byField("age").desc().andByScore().createSort());
fullTextQuery.setMaxResults(max);
fullTextQuery.setFirstResult(page);
return getUserList(fullTextQuery.getResultList());
}
private List<User> getUserList(List<Object[]> resultList) {
List<User> users = new ArrayList<>();
for (Object[] objects : resultList) {
User user = new User();
user.setId((String) objects[0]);
user.setFirst((String) objects[1]);
user.setLast((String) objects[2]);
user.setMiddle((String) objects[3]);
user.setAge((Integer) objects[4]);
users.add(user);
}
return users;
}
}

View File

@@ -0,0 +1,15 @@
spring:
jpa:
show-sql: true
generate-ddl: true
hibernate:
ddl-auto: create-drop
properties:
hibernate:
search:
default:
indexmanager: elasticsearch
elasticsearch:
host: http://192.168.0.103:9200
index_schema_management_strategy: drop-and-create
required_index_status: yellow

View File

@@ -0,0 +1,47 @@
insert into user (id, first, last, middle, age) values ( 'c_1', 'John', 'Doe', 'Maven' , 31);
insert into user (id, first, last, middle, age) values ( 'c_2', 'Jane', 'Dove', 'Gradle', 41);
insert into post (id, body, created_at, hash_tags, image_description, image_url, like_count, tag, user_id)
values ( 'p_1', 'The tattered work gloves speak of the many hours of hard labor he endured throughout his life', now(),
'#work#labour', 'Office', 'uri://sample1', 20, 'LITERATURE', 'c_1' );
insert into post (id, body, created_at, hash_tags, image_description, image_url, like_count, tag, user_id)
values ( 'p_2', 'Dolores wouldn''t have eaten the meal if she had known what it actually was.', now(),
'#food', 'Office', 'uri://sample1', 7686, 'MUSIC', 'c_1' );
insert into post (id, body, created_at, hash_tags, image_description, image_url, like_count, tag, user_id)
values ( 'p_3', 'It caught him off guard that space smelled of seared steak.', now(),
'#food#stale#caughtinact', 'Office', 'uri://sample1', 1234, 'LITERATURE', 'c_1' );
insert into post (id, body, created_at, hash_tags, image_description, image_url, like_count, tag, user_id)
values ( 'p_4', '25 years later, she still regretted that specific moment.', now(),
'#ages', 'Office', 'uri://sample1', 679, 'MOVIE', 'c_1' );
insert into post (id, body, created_at, hash_tags, image_description, image_url, like_count, tag, user_id)
values ( 'p_5', 'She had a habit of taking showers in lemonade.', now(),
'#bath', 'Office', 'uri://sample1', 23, 'LITERATURE', 'c_1' );
insert into post (id, body, created_at, hash_tags, image_description, image_url, like_count, tag, user_id)
values ( 'p_6', 'She is never happy until she finds something to be unhappy about; then, she is overjoyed.', now(),
'#feelings', 'Office', 'uri://sample1', 4569877, 'MOVIE', 'c_2' );
insert into post (id, body, created_at, hash_tags, image_description, image_url, like_count, tag, user_id)
values ( 'p_7', 'They throw cabbage that turns your brain into emotional baggage.', now(),
'#food', 'Office', 'uri://sample1', 1000, 'MUSIC', 'c_2' );
insert into post (id, body, created_at, hash_tags, image_description, image_url, like_count, tag, user_id)
values ( 'p_8', 'There''s a message for you if you look up.', now(),
'#message', 'Office', 'uri://sample1', 20, 'LITERATURE', 'c_2' );
insert into post (id, body, created_at, hash_tags, image_description, image_url, like_count, tag, user_id)
values ( 'p_9', 'Please wait outside of the house.', now(),
'#house#labour', 'Office', 'uri://sample1', 40, 'MUSIC', 'c_2' );
insert into post (id, body, created_at, hash_tags, image_description, image_url, like_count, tag, user_id)
values ( 'p_10', 'Honestly, I didn''t care much for the first season, so I didn''t bother with the second.', now(),
'#honest#season#time', 'Office', 'uri://sample1', 20000, 'MOVIE', 'c_2' );

View File

@@ -0,0 +1,3 @@
# Related Blog Posts
* [Mocking with (and without) Spring Boot](https://reflectoring.io/spring-boot-mock/)

View File

@@ -0,0 +1,3 @@
# Related Blog Posts
* [Modularizing a Spring Boot Application](https://reflectoring.io/spring-boot-modules/)

View File

@@ -0,0 +1,3 @@
# Related Blog Posts
* [Paging with Spring Boot](https://reflectoring.io/spring-boot-paging/)

View File

@@ -0,0 +1,3 @@
# Related Blog Posts
* [Handling Passwords with Spring Boot and Spring Security](https://reflectoring.io/spring-security-password-handling/)

BIN
spring-boot/spring-boot-docker/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,117 @@
/*
* Copyright 2007-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.net.*;
import java.io.*;
import java.nio.channels.*;
import java.util.Properties;
public class MavenWrapperDownloader {
private static final String WRAPPER_VERSION = "0.5.6";
/**
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
*/
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
/**
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
* use instead of the default one.
*/
private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
".mvn/wrapper/maven-wrapper.properties";
/**
* Path where the maven-wrapper.jar will be saved to.
*/
private static final String MAVEN_WRAPPER_JAR_PATH =
".mvn/wrapper/maven-wrapper.jar";
/**
* Name of the property which should be used to override the default download url for the wrapper.
*/
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
public static void main(String args[]) {
System.out.println("- Downloader started");
File baseDirectory = new File(args[0]);
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
// If the maven-wrapper.properties exists, read it and check if it contains a custom
// wrapperUrl parameter.
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
String url = DEFAULT_DOWNLOAD_URL;
if(mavenWrapperPropertyFile.exists()) {
FileInputStream mavenWrapperPropertyFileInputStream = null;
try {
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
Properties mavenWrapperProperties = new Properties();
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
} catch (IOException e) {
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
} finally {
try {
if(mavenWrapperPropertyFileInputStream != null) {
mavenWrapperPropertyFileInputStream.close();
}
} catch (IOException e) {
// Ignore ...
}
}
}
System.out.println("- Downloading from: " + url);
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
if(!outputFile.getParentFile().exists()) {
if(!outputFile.getParentFile().mkdirs()) {
System.out.println(
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
}
}
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
try {
downloadFileFromURL(url, outputFile);
System.out.println("Done");
System.exit(0);
} catch (Throwable e) {
System.out.println("- Error downloading");
e.printStackTrace();
System.exit(1);
}
}
private static void downloadFileFromURL(String urlString, File destination) throws Exception {
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
String username = System.getenv("MVNW_USERNAME");
char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
}
URL website = new URL(urlString);
ReadableByteChannel rbc;
rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream(destination);
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
fos.close();
rbc.close();
}
}

Binary file not shown.

View File

@@ -0,0 +1,2 @@
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar

View File

@@ -0,0 +1,5 @@
FROM adoptopenjdk/openjdk11:alpine-jre
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} application.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/application.jar"]

Some files were not shown because too many files have changed in this diff Show More