Compare commits
86 Commits
devtools
...
dependabot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d90c6fbc71 | ||
|
|
4c4469b43b | ||
|
|
0e40dbfee3 | ||
|
|
d47db42925 | ||
|
|
04dcc8097a | ||
|
|
ec52966e5f | ||
|
|
b982958196 | ||
|
|
974872ed8e | ||
|
|
0edc9e3e8e | ||
|
|
7d4dd46e2c | ||
|
|
5169b74c86 | ||
|
|
b5dc195722 | ||
|
|
47a1d0c4b7 | ||
|
|
cacef37325 | ||
|
|
ab9aa60613 | ||
|
|
782b64a32f | ||
|
|
2f948c0616 | ||
|
|
2e3d9a03b6 | ||
|
|
0e48de379f | ||
|
|
08d2592311 | ||
|
|
313889e494 | ||
|
|
6058641b80 | ||
|
|
ba8ba61586 | ||
|
|
ec595e8bae | ||
|
|
743bf01b0d | ||
|
|
ca9cc4ad65 | ||
|
|
b2ee3aafa3 | ||
|
|
f137ea52db | ||
|
|
13888f806e | ||
|
|
778a3d1d6f | ||
|
|
8b277387a1 | ||
|
|
029a5f03fb | ||
|
|
2958843c5a | ||
|
|
daa95bdf02 | ||
|
|
316fffdd7c | ||
|
|
c65e2b2165 | ||
|
|
44b4842849 | ||
|
|
947c68f0a8 | ||
|
|
927c51a2bb | ||
|
|
07265e54ed | ||
|
|
00b00e6e77 | ||
|
|
1eabfebeb0 | ||
|
|
b9b6ee02c5 | ||
|
|
64f680bd70 | ||
|
|
e833835beb | ||
|
|
c358d28ca6 | ||
|
|
ba285f6ee8 | ||
|
|
72d7a158b2 | ||
|
|
c8f550a222 | ||
|
|
7324634620 | ||
|
|
b1d595be27 | ||
|
|
8e9def0e7e | ||
|
|
4141cefdec | ||
|
|
ffcdc70902 | ||
|
|
445173072d | ||
|
|
bb7b3c1a95 | ||
|
|
3d255abdaf | ||
|
|
308663a9fd | ||
|
|
b793060c05 | ||
|
|
008636f6fa | ||
|
|
467aaa1e07 | ||
|
|
8e79ba1efa | ||
|
|
d222085520 | ||
|
|
3d128c346e | ||
|
|
c4e387b408 | ||
|
|
788e477803 | ||
|
|
5983abbf68 | ||
|
|
2b096d0470 | ||
|
|
712bef33d8 | ||
|
|
7148869bac | ||
|
|
68ef61997d | ||
|
|
12ba1f793e | ||
|
|
e42b7e8c4c | ||
|
|
a8e491c22a | ||
|
|
570b5f4abf | ||
|
|
1c7ea0ab08 | ||
|
|
7bebf8ccfd | ||
|
|
29f039ff97 | ||
|
|
c45f41d171 | ||
|
|
a83e8c34c6 | ||
|
|
1e5e5e2e91 | ||
|
|
31025040dc | ||
|
|
ccc5fdb306 | ||
|
|
8bbf1388b1 | ||
|
|
33649d5d8d | ||
|
|
53bb36722c |
8
.github/workflows/ci.yml
vendored
8
.github/workflows/ci.yml
vendored
@@ -1,6 +1,12 @@
|
||||
name: CI
|
||||
|
||||
on: [push, pull_request]
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- '**/*.md'
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- '**/*.md'
|
||||
|
||||
jobs:
|
||||
|
||||
|
||||
@@ -65,6 +65,11 @@
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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"
|
||||
|
||||
1
core-java/streams/fileswithstreams/.gitignore
vendored
Normal file
1
core-java/streams/fileswithstreams/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/target/
|
||||
117
core-java/streams/fileswithstreams/.mvn/wrapper/MavenWrapperDownloader.java
vendored
Normal file
117
core-java/streams/fileswithstreams/.mvn/wrapper/MavenWrapperDownloader.java
vendored
Normal 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();
|
||||
}
|
||||
|
||||
}
|
||||
BIN
core-java/streams/fileswithstreams/.mvn/wrapper/maven-wrapper.jar
vendored
Normal file
BIN
core-java/streams/fileswithstreams/.mvn/wrapper/maven-wrapper.jar
vendored
Normal file
Binary file not shown.
2
core-java/streams/fileswithstreams/.mvn/wrapper/maven-wrapper.properties
vendored
Normal file
2
core-java/streams/fileswithstreams/.mvn/wrapper/maven-wrapper.properties
vendored
Normal 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
|
||||
@@ -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
|
||||
@@ -0,0 +1,4 @@
|
||||
activeProfiles=
|
||||
eclipse.preferences.version=1
|
||||
resolveWorkspaceProjects=true
|
||||
version=1
|
||||
5
core-java/streams/fileswithstreams/README.md
Normal file
5
core-java/streams/fileswithstreams/README.md
Normal 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
310
core-java/streams/fileswithstreams/mvnw
vendored
Executable 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
core-java/streams/fileswithstreams/mvnw.cmd
vendored
Normal file
182
core-java/streams/fileswithstreams/mvnw.cmd
vendored
Normal 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%
|
||||
34
core-java/streams/fileswithstreams/pom.xml
Normal file
34
core-java/streams/fileswithstreams/pom.xml
Normal 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>
|
||||
@@ -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 + "]";
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
BIN
core-java/streams/fileswithstreams/src/main/resources/books.zip
Normal file
BIN
core-java/streams/fileswithstreams/src/main/resources/books.zip
Normal file
Binary file not shown.
@@ -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
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -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
|
||||
|
@@ -0,0 +1 @@
|
||||
akarui _ あかるい _ bright
|
||||
@@ -0,0 +1 @@
|
||||
/home/u1026/workspace/Learn/junit-5-basics/src/main/resources/books/
|
||||
117
resilience4j/bulkhead/.mvn/wrapper/MavenWrapperDownloader.java
vendored
Normal file
117
resilience4j/bulkhead/.mvn/wrapper/MavenWrapperDownloader.java
vendored
Normal 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();
|
||||
}
|
||||
|
||||
}
|
||||
BIN
resilience4j/bulkhead/.mvn/wrapper/maven-wrapper.jar
vendored
Normal file
BIN
resilience4j/bulkhead/.mvn/wrapper/maven-wrapper.jar
vendored
Normal file
Binary file not shown.
2
resilience4j/bulkhead/.mvn/wrapper/maven-wrapper.properties
vendored
Normal file
2
resilience4j/bulkhead/.mvn/wrapper/maven-wrapper.properties
vendored
Normal 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
|
||||
10
resilience4j/bulkhead/README.md
Normal file
10
resilience4j/bulkhead/README.md
Normal 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
310
resilience4j/bulkhead/mvnw
vendored
Executable 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
182
resilience4j/bulkhead/mvnw.cmd
vendored
Normal 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%
|
||||
113
resilience4j/bulkhead/pom.xml
Normal file
113
resilience4j/bulkhead/pom.xml
Normal 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>
|
||||
@@ -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("-----------------------------------------------------------------------");
|
||||
}
|
||||
}
|
||||
@@ -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("-----------------------------------------------------------------------");
|
||||
}
|
||||
}
|
||||
@@ -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 + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
|
||||
117
resilience4j/timelimiter/.mvn/wrapper/MavenWrapperDownloader.java
vendored
Normal file
117
resilience4j/timelimiter/.mvn/wrapper/MavenWrapperDownloader.java
vendored
Normal 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();
|
||||
}
|
||||
|
||||
}
|
||||
BIN
resilience4j/timelimiter/.mvn/wrapper/maven-wrapper.jar
vendored
Normal file
BIN
resilience4j/timelimiter/.mvn/wrapper/maven-wrapper.jar
vendored
Normal file
Binary file not shown.
2
resilience4j/timelimiter/.mvn/wrapper/maven-wrapper.properties
vendored
Normal file
2
resilience4j/timelimiter/.mvn/wrapper/maven-wrapper.properties
vendored
Normal 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
|
||||
5
resilience4j/timelimiter/Readme.md
Normal file
5
resilience4j/timelimiter/Readme.md
Normal 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
310
resilience4j/timelimiter/mvnw
vendored
Executable 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
182
resilience4j/timelimiter/mvnw.cmd
vendored
Normal 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%
|
||||
117
resilience4j/timelimiter/pom.xml
Normal file
117
resilience4j/timelimiter/pom.xml
Normal 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>
|
||||
@@ -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("----------------------------------------------------------------------------------------------------");
|
||||
}
|
||||
}
|
||||
@@ -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 + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
BIN
spring-boot/.DS_Store
vendored
Normal file
Binary file not shown.
5
spring-boot/argumentresolver/README.md
Normal file
5
spring-boot/argumentresolver/README.md
Normal 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/)
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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!");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
5
spring-boot/boundaries/README.md
Normal file
5
spring-boot/boundaries/README.md
Normal 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
3
spring-boot/cache/README.md
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# Related Blog Posts
|
||||
|
||||
* [Implementing a Cache with Spring Boot](https://reflectoring.io/spring-boot-cache/)
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
3
spring-boot/configuration/README.md
Normal file
3
spring-boot/configuration/README.md
Normal 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/)
|
||||
4
spring-boot/data-migration/flyway/README.md
Normal file
4
spring-boot/data-migration/flyway/README.md
Normal 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/)
|
||||
@@ -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?
|
||||
|
||||
3
spring-boot/dependency-injection/README.md
Normal file
3
spring-boot/dependency-injection/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Related Blog Posts
|
||||
|
||||
* [Why You Should Use Constructor Injection in Spring](https://reflectoring.io/constructor-injection/)
|
||||
3
spring-boot/hazelcast/hazelcast-client-server/README.md
Normal file
3
spring-boot/hazelcast/hazelcast-client-server/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Related Blog Posts
|
||||
|
||||
* [https://reflectoring.io/spring-boot-hazelcast/](https://reflectoring.io/spring-boot-hazelcast/)
|
||||
3
spring-boot/hazelcast/hazelcast-embedded-cache/README.md
Normal file
3
spring-boot/hazelcast/hazelcast-embedded-cache/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Related Blog Posts
|
||||
|
||||
* [https://reflectoring.io/spring-boot-hazelcast/](https://reflectoring.io/spring-boot-hazelcast/)
|
||||
5
spring-boot/hibernate-search/README.md
Normal file
5
spring-boot/hibernate-search/README.md
Normal 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
|
||||
40
spring-boot/hibernate-search/build.gradle
Normal file
40
spring-boot/hibernate-search/build.gradle
Normal 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()
|
||||
}
|
||||
BIN
spring-boot/hibernate-search/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
spring-boot/hibernate-search/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
6
spring-boot/hibernate-search/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
6
spring-boot/hibernate-search/gradle/wrapper/gradle-wrapper.properties
vendored
Normal 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
184
spring-boot/hibernate-search/gradlew
vendored
Normal 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
104
spring-boot/hibernate-search/gradlew.bat
vendored
Normal 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
|
||||
1
spring-boot/hibernate-search/settings.gradle
Normal file
1
spring-boot/hibernate-search/settings.gradle
Normal file
@@ -0,0 +1 @@
|
||||
rootProject.name = 'hibernate-search'
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package io.reflectoring.hibernatesearch.domain;
|
||||
|
||||
public enum Tag {
|
||||
MOVIE,
|
||||
MUSIC,
|
||||
LITERATURE
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
47
spring-boot/hibernate-search/src/main/resources/data.sql
Normal file
47
spring-boot/hibernate-search/src/main/resources/data.sql
Normal 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' );
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
3
spring-boot/mocking/README.md
Normal file
3
spring-boot/mocking/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Related Blog Posts
|
||||
|
||||
* [Mocking with (and without) Spring Boot](https://reflectoring.io/spring-boot-mock/)
|
||||
3
spring-boot/modular/README.md
Normal file
3
spring-boot/modular/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Related Blog Posts
|
||||
|
||||
* [Modularizing a Spring Boot Application](https://reflectoring.io/spring-boot-modules/)
|
||||
3
spring-boot/paging/README.md
Normal file
3
spring-boot/paging/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Related Blog Posts
|
||||
|
||||
* [Paging with Spring Boot](https://reflectoring.io/spring-boot-paging/)
|
||||
3
spring-boot/password-encoding/README.md
Normal file
3
spring-boot/password-encoding/README.md
Normal 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
BIN
spring-boot/spring-boot-docker/.DS_Store
vendored
Normal file
Binary file not shown.
117
spring-boot/spring-boot-docker/.mvn/wrapper/MavenWrapperDownloader.java
vendored
Normal file
117
spring-boot/spring-boot-docker/.mvn/wrapper/MavenWrapperDownloader.java
vendored
Normal 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();
|
||||
}
|
||||
|
||||
}
|
||||
BIN
spring-boot/spring-boot-docker/.mvn/wrapper/maven-wrapper.jar
vendored
Normal file
BIN
spring-boot/spring-boot-docker/.mvn/wrapper/maven-wrapper.jar
vendored
Normal file
Binary file not shown.
2
spring-boot/spring-boot-docker/.mvn/wrapper/maven-wrapper.properties
vendored
Normal file
2
spring-boot/spring-boot-docker/.mvn/wrapper/maven-wrapper.properties
vendored
Normal 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
|
||||
5
spring-boot/spring-boot-docker/Dockerfile
Normal file
5
spring-boot/spring-boot-docker/Dockerfile
Normal 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
Reference in New Issue
Block a user