diff --git a/pom.xml b/pom.xml
index d73ba312a..2a5e70329 100644
--- a/pom.xml
+++ b/pom.xml
@@ -30,6 +30,15 @@
true
+
+ standalone/contracts
+ standalone/dsl/http-server
+ standalone/dsl/http-client
+ standalone/restdocs/http-server
+ standalone/restdocs/http-client
+ standalone/webclient/http-server
+ standalone/webclient/http-client
+
common
wiremock
wiremock-for-contract-docs
@@ -93,6 +102,15 @@
false
+
+ standalone/contracts
+ standalone/dsl/http-server
+ standalone/dsl/http-client
+ standalone/restdocs/http-server
+ standalone/restdocs/http-client
+ standalone/webclient/http-server
+ standalone/webclient/http-client
+
beer_contracts
wiremock
wiremock-for-contract-docs
@@ -149,16 +167,6 @@
consumer_kotlin
-
- highmem
-
- false
-
-
- producer_java
- consumer_java
-
-
diff --git a/scripts/runGradleBuilds.sh b/scripts/runGradleBuilds.sh
index cd0d99a56..c5a6902de 100755
--- a/scripts/runGradleBuilds.sh
+++ b/scripts/runGradleBuilds.sh
@@ -60,6 +60,15 @@ function build_gradle() {
if [[ "${BUILD_COMMON}" == "true" ]]; then
build common
fi
+ # Standalone
+ build standalone/contracts
+ build standalone/dsl/http-server
+ build standalone/dsl/http-client
+ build standalone/restdocs/http-server
+ build standalone/restdocs/http-client
+ build standalone/webclient/http-server
+ build standalone/webclient/http-client
+
build producer
build producer_testng
# build producer_jaxrs
diff --git a/standalone/contracts/.mvn/wrapper/maven-wrapper.jar b/standalone/contracts/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 000000000..c6feb8bb6
Binary files /dev/null and b/standalone/contracts/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/standalone/contracts/.mvn/wrapper/maven-wrapper.properties b/standalone/contracts/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 000000000..6637cedb2
--- /dev/null
+++ b/standalone/contracts/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.3.9/apache-maven-3.3.9-bin.zip
\ No newline at end of file
diff --git a/standalone/contracts/README.adoc b/standalone/contracts/README.adoc
new file mode 100644
index 000000000..d5daaa6fe
--- /dev/null
+++ b/standalone/contracts/README.adoc
@@ -0,0 +1,68 @@
+= Common contracts repo
+
+This repo contains all contracts for apps in the system.
+
+== As a consumer
+
+You are working offline in order to play around with the API of the producer.
+What you need to do is to have the producer's stubs installed locally. To do that
+you have to (from the root of the repo)
+
+[source,bash]
+----
+cd com/example/server/
+mvn clean install -DskipTests
+----
+
+Then if you do `ls ./target` you'll see `server-0.0.1-SNAPSHOT-stubs.jar`. This jar will
+ contain the stubs generated from your contracts. That way you
+can reference the `com.example:server:+:stubs` dependency in your consumer tests.
+
+== As a producer
+
+Assuming that the consumers have filed a PR with the proposed contract the producers
+can work offline to generate tests and stubs. To work offline, as a producer you just have
+to go to the root folder of the contracts and:
+
+[source,bash]
+----
+./mvnw clean install -DskipTests
+----
+
+Then if you do `ls ./target` you'll see `contracts-0.0.1-SNAPSHOT.jar`. This file contains
+all DSL contracts, for all applications.
+
+Now the producer can include the `contracts-0.0.1-SNAPSHOT.jar` from your local maven repository.
+You can achieve that by setting the proper flag in plugin properties.
+
+Example for Maven
+
+[source,xml]
+----
+
+ org.springframework.cloud
+ spring-cloud-contract-maven-plugin
+
+ LOCAL
+
+ com.example.standalone
+ contracts
+
+
+
+----
+
+and for Gradle:
+
+[source,groovy]
+----
+contracts {
+ testFramework ='Spock'
+ testMode = 'JaxRsClient'
+ baseClassForTests = 'org.springframework.cloud.MvcSpec'
+ stubsMode = 'LOCAL'
+ contractDependency {
+ stringNotation = "com.example:contracts"
+ }
+}
+----
\ No newline at end of file
diff --git a/standalone/contracts/com/example/server/client1/expectation.groovy b/standalone/contracts/com/example/server/client1/expectation.groovy
new file mode 100644
index 000000000..ba3850f75
--- /dev/null
+++ b/standalone/contracts/com/example/server/client1/expectation.groovy
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package contracts
+
+org.springframework.cloud.contract.spec.Contract.make {
+ request { // (1)
+ method 'PUT' // (2)
+ url '/fraudcheck' // (3)
+ body([ // (4)
+ clientId : $(regex('[0-9]{10}')),
+ loanAmount: 99999
+ ])
+ headers { // (5)
+ contentType('application/vnd.fraud.v1+json')
+ }
+ }
+ response { // (6)
+ status OK() // (7)
+ body([ // (8)
+ fraudCheckStatus: "FRAUD",
+ rejectionReason : "Amount too high"
+ ])
+ headers { // (9)
+ contentType('application/vnd.fraud.v1+json')
+ }
+ }
+}
+
+/*
+Since we don't want to force on the user to hardcode values of fields that are dynamic
+(timestamps, database ids etc.), one can parametrize those entries. If you wrap your field's
+ value in a `$(...)` or `value(...)` and provide a dynamic value of a field then
+ the concrete value will be generated for you. If you want to be really explicit about
+ which side gets which value you can do that by using the `value(consumer(...), producer(...))` notation.
+ That way what's present in the `consumer` section will end up in the produced stub. What's
+ there in the `producer` will end up in the autogenerated test. If you provide only the
+ regular expression side without the concrete value then Spring Cloud Contract will generate one for you.
+
+From the Consumer perspective, when shooting a request in the integration test:
+
+(1) - If the consumer sends a request
+(2) - With the "PUT" method
+(3) - to the URL "/fraudcheck"
+(4) - with the JSON body that
+ * has a field `clientId` that matches a regular expression `[0-9]{10}`
+ * has a field `loanAmount` that is equal to `99999`
+(5) - with header `Content-Type` equal to `application/vnd.fraud.v1+json`
+(6) - then the response will be sent with
+(7) - status equal `200`
+(8) - and JSON body equal to
+ { "fraudCheckStatus": "FRAUD", "rejectionReason": "Amount too high" }
+(9) - with header `Content-Type` equal to `application/vnd.fraud.v1+json`
+
+From the Producer perspective, in the autogenerated producer-side test:
+
+(1) - A request will be sent to the producer
+(2) - With the "PUT" method
+(3) - to the URL "/fraudcheck"
+(4) - with the JSON body that
+ * has a field `clientId` that will have a generated value that matches a regular expression `[0-9]{10}`
+ * has a field `loanAmount` that is equal to `99999`
+(5) - with header `Content-Type` equal to `application/vnd.fraud.v1+json`
+(6) - then the test will assert if the response has been sent with
+(7) - status equal `200`
+(8) - and JSON body equal to
+ { "fraudCheckStatus": "FRAUD", "rejectionReason": "Amount too high" }
+(9) - with header `Content-Type` matching `application/vnd.fraud.v1+json.*`
+ */
diff --git a/standalone/contracts/com/example/server/client2/expectation.groovy b/standalone/contracts/com/example/server/client2/expectation.groovy
new file mode 100644
index 000000000..bd1ad7b71
--- /dev/null
+++ b/standalone/contracts/com/example/server/client2/expectation.groovy
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package contracts
+
+org.springframework.cloud.contract.spec.Contract.make {
+ request { // (1)
+ method 'PUT' // (2)
+ url '/fraudcheck2' // (3)
+ body([ // (4)
+ clientId : value(consumer(regex('[0-9]{10}'))),
+ loanAmount: 99999
+ ])
+ headers { // (5)
+ header('Content-Type', 'application/vnd.fraud.v1+json')
+ }
+ }
+ response { // (6)
+ status OK() // (7)
+ body([ // (8)
+ fraudCheckStatus: "FRAUD",
+ rejectionReason : "Amount too high"
+ ])
+ headers { // (9)
+ header('Content-Type': value(
+ producer(regex('application/vnd.fraud.v1.json.*')),
+ consumer('application/vnd.fraud.v1+json'))
+ )
+ }
+ }
+}
+
+/*
+Since we don't want to force on the user to hardcode values of fields that are dynamic
+(timestamps, database ids etc.), one can provide parametrize those entries by using the
+`value(consumer(...), producer(...))` method. That way what's present in the `consumer`
+section will end up in the produced stub. What's there in the `producer` will end up in the
+autogenerated test. If you provide only the regular expression side without the concrete
+value then Spring Cloud Contract will generate one for you.
+
+From the Consumer perspective, when shooting a request in the integration test:
+
+(1) - If the consumer sends a request
+(2) - With the "PUT" method
+(3) - to the URL "/fraudcheck"
+(4) - with the JSON body that
+ * has a field `clientId` that matches a regular expression `[0-9]{10}`
+ * has a field `loanAmount` that is equal to `99999`
+(5) - with header `Content-Type` equal to `application/vnd.fraud.v1+json`
+(6) - then the response will be sent with
+(7) - status equal `200`
+(8) - and JSON body equal to
+ { "fraudCheckStatus": "FRAUD", "rejectionReason": "Amount too high" }
+(9) - with header `Content-Type` equal to `application/vnd.fraud.v1+json`
+
+From the Producer perspective, in the autogenerated producer-side test:
+
+(1) - A request will be sent to the producer
+(2) - With the "PUT" method
+(3) - to the URL "/fraudcheck"
+(4) - with the JSON body that
+ * has a field `clientId` that will have a generated value that matches a regular expression `[0-9]{10}`
+ * has a field `loanAmount` that is equal to `99999`
+(5) - with header `Content-Type` equal to `application/vnd.fraud.v1+json`
+(6) - then the test will assert if the response has been sent with
+(7) - status equal `200`
+(8) - and JSON body equal to
+ { "fraudCheckStatus": "FRAUD", "rejectionReason": "Amount too high" }
+(9) - with header `Content-Type` matching `application/vnd.fraud.v1+json.*`
+ */
diff --git a/standalone/contracts/com/example/server/client3/expectation.groovy b/standalone/contracts/com/example/server/client3/expectation.groovy
new file mode 100644
index 000000000..1a850d19c
--- /dev/null
+++ b/standalone/contracts/com/example/server/client3/expectation.groovy
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package contracts
+
+org.springframework.cloud.contract.spec.Contract.make {
+ request { // (1)
+ method 'PUT' // (2)
+ url '/fraudcheck3' // (3)
+ body([ // (4)
+ clientId : value(consumer(regex('[0-9]{10}'))),
+ loanAmount: 99999
+ ])
+ headers { // (5)
+ header('Content-Type', 'application/vnd.fraud.v1+json')
+ }
+ }
+ response { // (6)
+ status OK() // (7)
+ body([ // (8)
+ fraudCheckStatus: "FRAUD",
+ rejectionReason : "Amount too high"
+ ])
+ headers { // (9)
+ header('Content-Type': value(
+ producer(regex('application/vnd.fraud.v1.json.*')),
+ consumer('application/vnd.fraud.v1+json'))
+ )
+ }
+ }
+}
+
+/*
+Since we don't want to force on the user to hardcode values of fields that are dynamic
+(timestamps, database ids etc.), one can provide parametrize those entries by using the
+`value(consumer(...), producer(...))` method. That way what's present in the `consumer`
+section will end up in the produced stub. What's there in the `producer` will end up in the
+autogenerated test. If you provide only the regular expression side without the concrete
+value then Spring Cloud Contract will generate one for you.
+
+From the Consumer perspective, when shooting a request in the integration test:
+
+(1) - If the consumer sends a request
+(2) - With the "PUT" method
+(3) - to the URL "/fraudcheck"
+(4) - with the JSON body that
+ * has a field `clientId` that matches a regular expression `[0-9]{10}`
+ * has a field `loanAmount` that is equal to `99999`
+(5) - with header `Content-Type` equal to `application/vnd.fraud.v1+json`
+(6) - then the response will be sent with
+(7) - status equal `200`
+(8) - and JSON body equal to
+ { "fraudCheckStatus": "FRAUD", "rejectionReason": "Amount too high" }
+(9) - with header `Content-Type` equal to `application/vnd.fraud.v1+json`
+
+From the Producer perspective, in the autogenerated producer-side test:
+
+(1) - A request will be sent to the producer
+(2) - With the "PUT" method
+(3) - to the URL "/fraudcheck"
+(4) - with the JSON body that
+ * has a field `clientId` that will have a generated value that matches a regular expression `[0-9]{10}`
+ * has a field `loanAmount` that is equal to `99999`
+(5) - with header `Content-Type` equal to `application/vnd.fraud.v1+json`
+(6) - then the test will assert if the response has been sent with
+(7) - status equal `200`
+(8) - and JSON body equal to
+ { "fraudCheckStatus": "FRAUD", "rejectionReason": "Amount too high" }
+(9) - with header `Content-Type` matching `application/vnd.fraud.v1+json.*`
+ */
diff --git a/standalone/contracts/com/example/server/pom.xml b/standalone/contracts/com/example/server/pom.xml
new file mode 100644
index 000000000..fc0d3e2cf
--- /dev/null
+++ b/standalone/contracts/com/example/server/pom.xml
@@ -0,0 +1,80 @@
+
+
+ 4.0.0
+
+ com.example
+ server
+ 0.0.1
+
+ Server Stubs
+ POM used to install locally stubs for consumer side
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.2.7
+
+
+
+
+ UTF-8
+ 17
+ 4.1.5-SNAPSHOT
+ true
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-contract-maven-plugin
+ ${spring-cloud-contract.version}
+ true
+
+
+ ${project.basedir}
+
+
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
diff --git a/standalone/contracts/mvnw b/standalone/contracts/mvnw
new file mode 100755
index 000000000..63fcc8f0f
--- /dev/null
+++ b/standalone/contracts/mvnw
@@ -0,0 +1,234 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# 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.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven2 Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# M2_HOME - location of maven2's installed home dir
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ #
+ # Look for the Apple JDKs first to preserve the existing behaviour, and then look
+ # for the new JDKs provided by Oracle.
+ #
+ if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK ] ; then
+ #
+ # Apple JDKs
+ #
+ export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home
+ fi
+
+ if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Java/JavaVirtualMachines/CurrentJDK ] ; then
+ #
+ # Apple JDKs
+ #
+ export JAVA_HOME=/System/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home
+ fi
+
+ if [ -z "$JAVA_HOME" ] && [ -L "/Library/Java/JavaVirtualMachines/CurrentJDK" ] ; then
+ #
+ # Oracle JDKs
+ #
+ export JAVA_HOME=/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home
+ fi
+
+ if [ -z "$JAVA_HOME" ] && [ -x "/usr/libexec/java_home" ]; then
+ #
+ # Apple JDKs
+ #
+ export JAVA_HOME=`/usr/libexec/java_home`
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=`java-config --jre-home`
+ fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+ ## resolve links - $0 may be a link to maven's home
+ PRG="$0"
+
+ # need this for relative symlinks
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG="`dirname "$PRG"`/$link"
+ fi
+ done
+
+ saveddir=`pwd`
+
+ M2_HOME=`dirname "$PRG"`/..
+
+ # make it fully qualified
+ M2_HOME=`cd "$M2_HOME" && pwd`
+
+ cd "$saveddir"
+ # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --unix "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Migwn, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME="`(cd "$M2_HOME"; pwd)`"
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+ # TODO classpath?
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="`which javac`"
+ if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=`which readlink`
+ if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+ if $darwin ; then
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+ else
+ javaExecutable="`readlink -f \"$javaExecutable\"`"
+ fi
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="`which java`"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# 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"`
+fi
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+ local basedir=$(pwd)
+ local wdir=$(pwd)
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ wdir=$(cd "$wdir/.."; pwd)
+ done
+ echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ echo "$(tr -s '\n' ' ' < "$1")"
+ fi
+}
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-$(find_maven_basedir)}
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# 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_CMD_LINE_ARGS
+
diff --git a/standalone/contracts/mvnw.cmd b/standalone/contracts/mvnw.cmd
new file mode 100644
index 000000000..66e928bd1
--- /dev/null
+++ b/standalone/contracts/mvnw.cmd
@@ -0,0 +1,145 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM https://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven2 Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
+if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+set MAVEN_CMD_LINE_ARGS=%MAVEN_CONFIG% %*
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+
+set WRAPPER_JAR=""%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar""
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CMD_LINE_ARGS%
+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%
diff --git a/standalone/contracts/pom.xml b/standalone/contracts/pom.xml
new file mode 100644
index 000000000..d559dfdbf
--- /dev/null
+++ b/standalone/contracts/pom.xml
@@ -0,0 +1,59 @@
+
+
+ 4.0.0
+
+ com.example.standalone
+ contracts
+ 0.0.1
+
+ Contracts
+ Contains all the Spring Cloud Contracts, well, contracts. JAR used by the
+ producers to generate tests and stubs
+
+
+
+ UTF-8
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-assembly-plugin
+
+
+ contracts
+ prepare-package
+
+ single
+
+
+ true
+
+ ${project.basedir}/src/assembly/contracts.xml
+
+
+ false
+
+
+
+
+
+ maven-jar-plugin
+ 3.4.2
+
+
+ default-jar
+ none
+
+ jar
+
+
+
+
+
+
+
+
diff --git a/standalone/contracts/src/assembly/contracts.xml b/standalone/contracts/src/assembly/contracts.xml
new file mode 100644
index 000000000..478cdc59d
--- /dev/null
+++ b/standalone/contracts/src/assembly/contracts.xml
@@ -0,0 +1,23 @@
+
+ project
+
+ jar
+
+ false
+
+
+ ${project.basedir}
+ /
+ true
+
+ **/${project.build.directory}/**
+ mvnw
+ mvnw.cmd
+ .mvn/**
+ src/**
+
+
+
+
diff --git a/standalone/dsl/http-client/.gitignore b/standalone/dsl/http-client/.gitignore
new file mode 100644
index 000000000..b05ba7bd6
--- /dev/null
+++ b/standalone/dsl/http-client/.gitignore
@@ -0,0 +1,6 @@
+
+target/
+
+.gradle
+build/
+
diff --git a/standalone/dsl/http-client/.mvn/jvm.config b/standalone/dsl/http-client/.mvn/jvm.config
new file mode 100644
index 000000000..0e7dabeff
--- /dev/null
+++ b/standalone/dsl/http-client/.mvn/jvm.config
@@ -0,0 +1 @@
+-Xmx1024m -XX:CICompilerCount=1 -XX:TieredStopAtLevel=1 -Djava.security.egd=file:/dev/./urandom
\ No newline at end of file
diff --git a/standalone/dsl/http-client/.mvn/maven.config b/standalone/dsl/http-client/.mvn/maven.config
new file mode 100644
index 000000000..a68299056
--- /dev/null
+++ b/standalone/dsl/http-client/.mvn/maven.config
@@ -0,0 +1 @@
+-P spring
diff --git a/standalone/dsl/http-client/.mvn/wrapper/MavenWrapperDownloader.java b/standalone/dsl/http-client/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 000000000..b901097f2
--- /dev/null
+++ b/standalone/dsl/http-client/.mvn/wrapper/MavenWrapperDownloader.java
@@ -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();
+ }
+
+}
diff --git a/standalone/dsl/http-client/.mvn/wrapper/maven-wrapper.jar b/standalone/dsl/http-client/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 000000000..c1dd12f17
Binary files /dev/null and b/standalone/dsl/http-client/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/standalone/dsl/http-client/.mvn/wrapper/maven-wrapper.properties b/standalone/dsl/http-client/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 000000000..015dfe682
--- /dev/null
+++ b/standalone/dsl/http-client/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,18 @@
+# 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.
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.3/apache-maven-3.8.3-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar
diff --git a/standalone/dsl/http-client/README.adoc b/standalone/dsl/http-client/README.adoc
new file mode 100644
index 000000000..cdcb0e4a5
--- /dev/null
+++ b/standalone/dsl/http-client/README.adoc
@@ -0,0 +1,26 @@
+= Http Client
+
+== Prerequisites
+
+First you have to publish to Maven Local the stubs of the *http-server* module
+
+== How to run it?
+
+Run
+
+[source=groovy]
+--------
+./gradlew clean build
+--------
+
+or
+
+--------
+./mvnw clean package
+--------
+
+To
+
+- build the app
+- use spring-cloud-contract-stub-runner-spring[Stub Runner Spring] to download the stub of `Http Server`
+- run the tests against stubbed server
\ No newline at end of file
diff --git a/standalone/dsl/http-client/build.gradle b/standalone/dsl/http-client/build.gradle
new file mode 100644
index 000000000..2cc4918bc
--- /dev/null
+++ b/standalone/dsl/http-client/build.gradle
@@ -0,0 +1,65 @@
+plugins {
+ id "groovy"
+ id "org.springframework.boot"
+ id "io.spring.dependency-management"
+ id "maven-publish"
+}
+
+group = 'com.example'
+version = '0.0.1'
+
+repositories {
+ mavenCentral()
+ mavenLocal()
+ maven { url "https://repo.spring.io/snapshot" }
+ maven { url "https://repo.spring.io/milestone" }
+}
+
+dependencyManagement {
+ imports {
+ mavenBom "org.springframework.cloud:spring-cloud-contract-dependencies:$verifierVersion"
+ mavenBom "org.springframework.cloud:spring-cloud-stream-dependencies:$springCloudStreamVersion"
+ }
+}
+
+dependencies {
+ implementation("org.springframework.boot:spring-boot-starter-web")
+ implementation("org.springframework.boot:spring-boot-starter-actuator")
+ implementation("org.springframework.cloud:spring-cloud-starter-stream-rabbit")
+
+ testImplementation(group: 'org.springframework.cloud', name: 'spring-cloud-stream-test-binder')
+ testImplementation "org.springframework.cloud:spring-cloud-starter-contract-stub-runner"
+ testImplementation "org.springframework.cloud:spring-cloud-starter-contract-verifier"
+ testImplementation('org.springframework.boot:spring-boot-starter-test') {
+ exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
+ }
+}
+
+test {
+ useJUnitPlatform()
+ systemProperty 'spring.profiles.active', 'gradle'
+ testLogging {
+ exceptionFormat = 'full'
+ }
+ afterSuite { desc, result ->
+ if (!desc.parent) {
+ println "Results: (${result.testCount} tests, ${result.successfulTestCount} successes, ${result.failedTestCount} failures, ${result.skippedTestCount} skipped)"
+ if (result.testCount == 0) {
+ throw new IllegalStateException("No tests were found. Failing the build")
+ }
+ }
+ }
+}
+
+task resolveDependencies {
+ doLast {
+ project.rootProject.allprojects.each { subProject ->
+ subProject.buildscript.configurations.each { configuration ->
+ configuration.resolve()
+ }
+ subProject.configurations.each { configuration ->
+ configuration.resolve()
+ }
+ }
+ }
+}
diff --git a/standalone/dsl/http-client/gradle.properties b/standalone/dsl/http-client/gradle.properties
new file mode 100644
index 000000000..0b984780b
--- /dev/null
+++ b/standalone/dsl/http-client/gradle.properties
@@ -0,0 +1,4 @@
+org.gradle.daemon=false
+verifierVersion=4.1.5-SNAPSHOT
+springCloudStreamVersion=4.1.4-SNAPSHOT
+bootVersion=3.2.7
diff --git a/standalone/dsl/http-client/gradle/wrapper/gradle-wrapper.jar b/standalone/dsl/http-client/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 000000000..c1962a79e
Binary files /dev/null and b/standalone/dsl/http-client/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/standalone/dsl/http-client/gradle/wrapper/gradle-wrapper.properties b/standalone/dsl/http-client/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 000000000..c30b486a8
--- /dev/null
+++ b/standalone/dsl/http-client/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
+networkTimeout=10000
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/standalone/dsl/http-client/gradlew b/standalone/dsl/http-client/gradlew
new file mode 100755
index 000000000..aeb74cbb4
--- /dev/null
+++ b/standalone/dsl/http-client/gradlew
@@ -0,0 +1,245 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original 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 POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
+done
+
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+ echo "$*"
+} >&2
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+} >&2
+
+# 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 ;; #(
+ MSYS* | 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" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC3045
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC3045
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+
+# 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"'
+
+# Collect all arguments for the java command;
+# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+# shell script including quotes and variable substitutions, so put them in
+# double quotes to make sure that they get re-expanded; and
+# * put everything else in single quotes, so that it's not re-expanded.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+ die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/standalone/dsl/http-client/gradlew.bat b/standalone/dsl/http-client/gradlew.bat
new file mode 100644
index 000000000..93e3f59f1
--- /dev/null
+++ b/standalone/dsl/http-client/gradlew.bat
@@ -0,0 +1,92 @@
+@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=.
+@rem This is normally unused
+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% equ 0 goto execute
+
+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 execute
+
+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
+
+: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 %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if %ERRORLEVEL% equ 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!
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/standalone/dsl/http-client/mvnw b/standalone/dsl/http-client/mvnw
new file mode 100755
index 000000000..5643201c7
--- /dev/null
+++ b/standalone/dsl/http-client/mvnw
@@ -0,0 +1,316 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# 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 /usr/local/etc/mavenrc ] ; then
+ . /usr/local/etc/mavenrc
+ fi
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ export JAVA_HOME="`/usr/libexec/java_home`"
+ else
+ export JAVA_HOME="/Library/Java/Home"
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=`java-config --jre-home`
+ fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+ ## resolve links - $0 may be a link to maven's home
+ PRG="$0"
+
+ # need this for relative symlinks
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG="`dirname "$PRG"`/$link"
+ fi
+ done
+
+ saveddir=`pwd`
+
+ M2_HOME=`dirname "$PRG"`/..
+
+ # make it fully qualified
+ M2_HOME=`cd "$M2_HOME" && pwd`
+
+ cd "$saveddir"
+ # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --unix "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME="`(cd "$M2_HOME"; pwd)`"
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="`which javac`"
+ if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=`which readlink`
+ if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+ if $darwin ; then
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+ else
+ javaExecutable="`readlink -f \"$javaExecutable\"`"
+ fi
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="`\\unset -f command; \\command -v java`"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=`cd "$wdir/.."; pwd`
+ fi
+ # end of workaround
+ done
+ echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ echo "$(tr -s '\n' ' ' < "$1")"
+ fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found .mvn/wrapper/maven-wrapper.jar"
+ fi
+else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+ fi
+ if [ -n "$MVNW_REPOURL" ]; then
+ jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+ else
+ jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+ fi
+ while IFS="=" read key value; do
+ case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
+ esac
+ done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Downloading from: $jarUrl"
+ fi
+ wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+ if $cygwin; then
+ wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
+ fi
+
+ if command -v wget > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found wget ... using wget"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ else
+ wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ fi
+ elif command -v curl > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found curl ... using curl"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl -o "$wrapperJarPath" "$jarUrl" -f
+ else
+ curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
+ fi
+
+ else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Falling back to using Java to download"
+ fi
+ javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaClass=`cygpath --path --windows "$javaClass"`
+ fi
+ if [ -e "$javaClass" ]; then
+ if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Compiling MavenWrapperDownloader.java ..."
+ fi
+ # Compiling the Java class
+ ("$JAVA_HOME/bin/javac" "$javaClass")
+ fi
+ if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ # Running the downloader
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Running MavenWrapperDownloader.java ..."
+ fi
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+if [ "$MVNW_VERBOSE" = true ]; then
+ echo $MAVEN_PROJECTBASEDIR
+fi
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --path --windows "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ $MAVEN_DEBUG_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.home=${M2_HOME}" \
+ "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/standalone/dsl/http-client/mvnw.cmd b/standalone/dsl/http-client/mvnw.cmd
new file mode 100644
index 000000000..8a15b7f31
--- /dev/null
+++ b/standalone/dsl/http-client/mvnw.cmd
@@ -0,0 +1,188 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM 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 "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
+if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Found %WRAPPER_JAR%
+ )
+) else (
+ if not "%MVNW_REPOURL%" == "" (
+ SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+ )
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %DOWNLOAD_URL%
+ )
+
+ powershell -Command "&{"^
+ "$webclient = new-object System.Net.WebClient;"^
+ "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+ "}"^
+ "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
+ "}"
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Finished downloading %WRAPPER_JAR%
+ )
+)
+@REM End of extension
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% ^
+ %JVM_CONFIG_MAVEN_PROPS% ^
+ %MAVEN_OPTS% ^
+ %MAVEN_DEBUG_OPTS% ^
+ -classpath %WRAPPER_JAR% ^
+ "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
+ %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
+if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%"=="on" pause
+
+if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
+
+cmd /C exit /B %ERROR_CODE%
diff --git a/standalone/dsl/http-client/pom.xml b/standalone/dsl/http-client/pom.xml
new file mode 100644
index 000000000..16b23051a
--- /dev/null
+++ b/standalone/dsl/http-client/pom.xml
@@ -0,0 +1,242 @@
+
+
+ 4.0.0
+
+ com.example
+ http-client-dsl
+ 0.0.1
+
+ Spring Cloud Contract Verifier Http Client Sample
+ Spring Cloud Contract Verifier Http Client Sample
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.2.7
+
+
+
+
+ UTF-8
+ 17
+ 4.1.5-SNAPSHOT
+ 4.1.4-SNAPSHOT
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+ org.apache.httpcomponents.client5
+ httpclient5
+
+
+ org.slf4j
+ slf4j-api
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-stream-rabbit
+
+
+
+ org.springframework.cloud
+ spring-cloud-stream-test-binder
+ test
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-contract-stub-runner
+ test
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-contract-verifier
+ test
+
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-contract-dependencies
+ ${spring-cloud-contract.version}
+ pom
+ import
+
+
+ org.springframework.cloud
+ spring-cloud-stream-dependencies
+ ${spring-cloud-stream.version}
+ pom
+ import
+
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ maven-deploy-plugin
+ 2.8.2
+
+ true
+
+
+
+ org.apache.maven.plugins
+ maven-clean-plugin
+ 3.0.0
+
+
+
+ build
+
+
+ target
+
+
+
+
+
+ maven-surefire-plugin
+
+ true
+
+
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
+
+ integration
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 1.6.0
+
+
+ gradle
+ test
+
+ ./gradlew
+
+ clean
+ build
+ publishToMavenLocal
+
+ -x
+ test
+
+ -PverifierVersion=${spring-cloud-contract.version}
+
+
+
+
+ exec
+
+
+
+
+
+
+
+
+ windows
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 1.6.0
+
+
+ gradle
+ test
+
+ gradlew.bat
+
+ clean
+ build
+ publishToMavenLocal
+
+ -x
+ test
+
+ -PverifierVersion=${spring-cloud-contract.version}
+
+
+
+
+ exec
+
+
+
+
+
+
+
+
+
+
diff --git a/standalone/dsl/http-client/settings.gradle b/standalone/dsl/http-client/settings.gradle
new file mode 100644
index 000000000..b125e5419
--- /dev/null
+++ b/standalone/dsl/http-client/settings.gradle
@@ -0,0 +1,14 @@
+pluginManagement {
+ repositories {
+ mavenLocal()
+ maven { url "https://repo.spring.io/snapshot" }
+ maven { url "https://repo.spring.io/milestone" }
+ gradlePluginPortal()
+ }
+ plugins {
+ id "org.springframework.boot" version "${bootVersion}"
+ id "io.spring.dependency-management" version "1.1.3"
+ }
+}
+
+rootProject.name = 'http-client-dsl-gradle'
diff --git a/standalone/dsl/http-client/src/main/java/com/example/loan/Application.java b/standalone/dsl/http-client/src/main/java/com/example/loan/Application.java
new file mode 100644
index 000000000..6e1c77d27
--- /dev/null
+++ b/standalone/dsl/http-client/src/main/java/com/example/loan/Application.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.loan;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+}
diff --git a/standalone/dsl/http-client/src/main/java/com/example/loan/Listener.java b/standalone/dsl/http-client/src/main/java/com/example/loan/Listener.java
new file mode 100644
index 000000000..51f6cd301
--- /dev/null
+++ b/standalone/dsl/http-client/src/main/java/com/example/loan/Listener.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.loan;
+
+import java.util.function.Consumer;
+
+import org.springframework.stereotype.Component;
+
+@Component("listener")
+class Listener implements Consumer {
+
+ int count = 0;
+
+ public void logSensorData(SensorData data) {
+ System.out.println(data);
+ this.count = this.count + 1;
+ }
+
+ public int getCount() {
+ return this.count;
+ }
+
+ @Override
+ public void accept(SensorData sensorData) {
+ this.logSensorData(sensorData);
+ }
+}
diff --git a/standalone/dsl/http-client/src/main/java/com/example/loan/LoanApplicationService.java b/standalone/dsl/http-client/src/main/java/com/example/loan/LoanApplicationService.java
new file mode 100644
index 000000000..ad400366f
--- /dev/null
+++ b/standalone/dsl/http-client/src/main/java/com/example/loan/LoanApplicationService.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.loan;
+
+import com.example.loan.model.FraudCheckStatus;
+import com.example.loan.model.FraudServiceRequest;
+import com.example.loan.model.FraudServiceResponse;
+import com.example.loan.model.LoanApplication;
+import com.example.loan.model.LoanApplicationResult;
+import com.example.loan.model.LoanApplicationStatus;
+import com.example.loan.model.Response;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.web.client.RestTemplateBuilder;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestTemplate;
+
+@Service
+public class LoanApplicationService {
+
+ private final RestTemplate restTemplate;
+
+ private int port = 6565;
+
+ private String prefix = "";
+
+ @Autowired
+ public LoanApplicationService(RestTemplateBuilder builder) {
+ this.restTemplate = builder.build();
+ }
+
+ public LoanApplicationResult loanApplication(LoanApplication loanApplication) {
+ FraudServiceRequest request = new FraudServiceRequest(loanApplication);
+
+ FraudServiceResponse response = sendRequestToFraudDetectionService(request);
+
+ return buildResponseFromFraudResult(response);
+ }
+
+ private FraudServiceResponse sendRequestToFraudDetectionService(
+ FraudServiceRequest request) {
+ HttpHeaders httpHeaders = new HttpHeaders();
+ httpHeaders.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
+
+ // tag::client_call_server[]
+ ResponseEntity response = restTemplate.exchange(
+ "http://localhost:" + port + fraudCheck(), HttpMethod.PUT,
+ new HttpEntity<>(request, httpHeaders), FraudServiceResponse.class);
+ // end::client_call_server[]
+
+ return response.getBody();
+ }
+
+ private String fraudCheck() {
+ return "/" + prefix + "fraudcheck";
+ }
+
+ private LoanApplicationResult buildResponseFromFraudResult(
+ FraudServiceResponse response) {
+ LoanApplicationStatus applicationStatus = null;
+ if (FraudCheckStatus.OK == response.getFraudCheckStatus()) {
+ applicationStatus = LoanApplicationStatus.LOAN_APPLIED;
+ }
+ else if (FraudCheckStatus.FRAUD == response.getFraudCheckStatus()) {
+ applicationStatus = LoanApplicationStatus.LOAN_APPLICATION_REJECTED;
+ }
+
+ return new LoanApplicationResult(applicationStatus,
+ response.getRejectionReason());
+ }
+
+ public int countAllFrauds() {
+ HttpHeaders httpHeaders = new HttpHeaders();
+ httpHeaders.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
+ ResponseEntity response = restTemplate.exchange(
+ "http://localhost:" + port + "/" + prefix + "frauds", HttpMethod.GET,
+ new HttpEntity<>(httpHeaders), Response.class);
+ return response.getBody().getCount();
+ }
+
+ public int countDrunks() {
+ HttpHeaders httpHeaders = new HttpHeaders();
+ httpHeaders.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
+ ResponseEntity response = restTemplate.exchange(
+ "http://localhost:" + port + "/"+ prefix + "drunks", HttpMethod.GET,
+ new HttpEntity<>(httpHeaders), Response.class);
+ return response.getBody().getCount();
+ }
+
+ public String getCookies() {
+ HttpHeaders httpHeaders = new HttpHeaders();
+ httpHeaders.add("Cookie", "name=foo");
+ httpHeaders.add("Cookie", "name2=bar");
+ ResponseEntity response = restTemplate.exchange(
+ "http://localhost:" + port + "/" + prefix + "frauds/name", HttpMethod.GET,
+ new HttpEntity<>(httpHeaders), String.class);
+ return response.getBody();
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+ public void setPrefix(String prefix) {
+ this.prefix = prefix;
+ }
+}
diff --git a/standalone/dsl/http-client/src/main/java/com/example/loan/SensorData.java b/standalone/dsl/http-client/src/main/java/com/example/loan/SensorData.java
new file mode 100644
index 000000000..c2f496de9
--- /dev/null
+++ b/standalone/dsl/http-client/src/main/java/com/example/loan/SensorData.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2016-2020 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.
+ */
+
+package com.example.loan;
+
+/**
+ * @author Marius Bogoevici
+ */
+public class SensorData {
+
+ private Long id;
+
+ private Double temperature;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public Double getTemperature() {
+ return temperature;
+ }
+
+ public void setTemperature(Double temperature) {
+ this.temperature = temperature;
+ }
+
+}
diff --git a/standalone/dsl/http-client/src/main/java/com/example/loan/model/Client.java b/standalone/dsl/http-client/src/main/java/com/example/loan/model/Client.java
new file mode 100644
index 000000000..8fac47b2f
--- /dev/null
+++ b/standalone/dsl/http-client/src/main/java/com/example/loan/model/Client.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.loan.model;
+
+public class Client {
+
+ private String pesel;
+
+ public Client() {
+ }
+
+ public Client(String pesel) {
+ this.pesel = pesel;
+ }
+
+ public String getPesel() {
+ return pesel;
+ }
+
+ public void setPesel(String pesel) {
+ this.pesel = pesel;
+ }
+
+}
diff --git a/standalone/dsl/http-client/src/main/java/com/example/loan/model/FraudCheckStatus.java b/standalone/dsl/http-client/src/main/java/com/example/loan/model/FraudCheckStatus.java
new file mode 100644
index 000000000..01f296911
--- /dev/null
+++ b/standalone/dsl/http-client/src/main/java/com/example/loan/model/FraudCheckStatus.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.loan.model;
+
+public enum FraudCheckStatus {
+
+ OK, FRAUD
+
+}
diff --git a/standalone/dsl/http-client/src/main/java/com/example/loan/model/FraudServiceRequest.java b/standalone/dsl/http-client/src/main/java/com/example/loan/model/FraudServiceRequest.java
new file mode 100644
index 000000000..2933acb39
--- /dev/null
+++ b/standalone/dsl/http-client/src/main/java/com/example/loan/model/FraudServiceRequest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.loan.model;
+
+import java.math.BigDecimal;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class FraudServiceRequest {
+
+ @JsonProperty("client.id")
+ private String clientId;
+
+ private BigDecimal loanAmount;
+
+ public FraudServiceRequest() {
+ }
+
+ public FraudServiceRequest(LoanApplication loanApplication) {
+ this.clientId = loanApplication.getClient().getPesel();
+ this.loanAmount = loanApplication.getAmount();
+ }
+
+ public String getClientId() {
+ return clientId;
+ }
+
+ public void setClientId(String clientId) {
+ this.clientId = clientId;
+ }
+
+ public BigDecimal getLoanAmount() {
+ return loanAmount;
+ }
+
+ public void setLoanAmount(BigDecimal loanAmount) {
+ this.loanAmount = loanAmount;
+ }
+
+}
diff --git a/standalone/dsl/http-client/src/main/java/com/example/loan/model/FraudServiceResponse.java b/standalone/dsl/http-client/src/main/java/com/example/loan/model/FraudServiceResponse.java
new file mode 100644
index 000000000..1847a1248
--- /dev/null
+++ b/standalone/dsl/http-client/src/main/java/com/example/loan/model/FraudServiceResponse.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.loan.model;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class FraudServiceResponse {
+
+ private FraudCheckStatus fraudCheckStatus;
+
+ @JsonProperty("rejection.reason")
+ private String rejectionReason;
+
+ public FraudServiceResponse() {
+ }
+
+ public FraudCheckStatus getFraudCheckStatus() {
+ return fraudCheckStatus;
+ }
+
+ public void setFraudCheckStatus(FraudCheckStatus fraudCheckStatus) {
+ this.fraudCheckStatus = fraudCheckStatus;
+ }
+
+ public String getRejectionReason() {
+ return rejectionReason;
+ }
+
+ public void setRejectionReason(String rejectionReason) {
+ this.rejectionReason = rejectionReason;
+ }
+
+}
diff --git a/standalone/dsl/http-client/src/main/java/com/example/loan/model/LoanApplication.java b/standalone/dsl/http-client/src/main/java/com/example/loan/model/LoanApplication.java
new file mode 100644
index 000000000..e2f4aa251
--- /dev/null
+++ b/standalone/dsl/http-client/src/main/java/com/example/loan/model/LoanApplication.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.loan.model;
+
+import java.math.BigDecimal;
+
+public class LoanApplication {
+
+ private Client client;
+
+ private BigDecimal amount;
+
+ private String loanApplicationId;
+
+ public LoanApplication() {
+ }
+
+ public LoanApplication(Client client, double amount) {
+ this.client = client;
+ this.amount = BigDecimal.valueOf(amount);
+ }
+
+ public Client getClient() {
+ return client;
+ }
+
+ public void setClient(Client client) {
+ this.client = client;
+ }
+
+ public BigDecimal getAmount() {
+ return amount;
+ }
+
+ public void setAmount(BigDecimal amount) {
+ this.amount = amount;
+ }
+
+ public String getLoanApplicationId() {
+ return loanApplicationId;
+ }
+
+ public void setLoanApplicationId(String loanApplicationId) {
+ this.loanApplicationId = loanApplicationId;
+ }
+
+}
diff --git a/standalone/dsl/http-client/src/main/java/com/example/loan/model/LoanApplicationResult.java b/standalone/dsl/http-client/src/main/java/com/example/loan/model/LoanApplicationResult.java
new file mode 100644
index 000000000..73501084b
--- /dev/null
+++ b/standalone/dsl/http-client/src/main/java/com/example/loan/model/LoanApplicationResult.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.loan.model;
+
+public class LoanApplicationResult {
+
+ private LoanApplicationStatus loanApplicationStatus;
+
+ private String rejectionReason;
+
+ public LoanApplicationResult() {
+ }
+
+ public LoanApplicationResult(LoanApplicationStatus loanApplicationStatus,
+ String rejectionReason) {
+ this.loanApplicationStatus = loanApplicationStatus;
+ this.rejectionReason = rejectionReason;
+ }
+
+ public LoanApplicationStatus getLoanApplicationStatus() {
+ return loanApplicationStatus;
+ }
+
+ public void setLoanApplicationStatus(LoanApplicationStatus loanApplicationStatus) {
+ this.loanApplicationStatus = loanApplicationStatus;
+ }
+
+ public String getRejectionReason() {
+ return rejectionReason;
+ }
+
+ public void setRejectionReason(String rejectionReason) {
+ this.rejectionReason = rejectionReason;
+ }
+
+}
diff --git a/standalone/dsl/http-client/src/main/java/com/example/loan/model/LoanApplicationStatus.java b/standalone/dsl/http-client/src/main/java/com/example/loan/model/LoanApplicationStatus.java
new file mode 100644
index 000000000..5afde21af
--- /dev/null
+++ b/standalone/dsl/http-client/src/main/java/com/example/loan/model/LoanApplicationStatus.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.loan.model;
+
+public enum LoanApplicationStatus {
+
+ LOAN_APPLIED, LOAN_APPLICATION_REJECTED
+
+}
diff --git a/standalone/dsl/http-client/src/main/java/com/example/loan/model/Response.java b/standalone/dsl/http-client/src/main/java/com/example/loan/model/Response.java
new file mode 100644
index 000000000..37ea6013e
--- /dev/null
+++ b/standalone/dsl/http-client/src/main/java/com/example/loan/model/Response.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.loan.model;
+
+public class Response {
+
+ private int count;
+
+ public Response(int count) {
+ this.count = count;
+ }
+
+ public Response() {
+ }
+
+ public int getCount() {
+ return this.count;
+ }
+
+ public void setCount(int count) {
+ this.count = count;
+ }
+
+}
diff --git a/standalone/dsl/http-client/src/main/resources/application.yml b/standalone/dsl/http-client/src/main/resources/application.yml
new file mode 100644
index 000000000..2de2007e6
--- /dev/null
+++ b/standalone/dsl/http-client/src/main/resources/application.yml
@@ -0,0 +1,7 @@
+server.port: 8090
+spring:
+ cloud:
+ function:
+ definition: listener
+ stream:
+ bindings.listener-in-0.destination: sensor_data
\ No newline at end of file
diff --git a/standalone/dsl/http-client/src/test/java/com/example/loan/GoodbyeWorldTests.java b/standalone/dsl/http-client/src/test/java/com/example/loan/GoodbyeWorldTests.java
new file mode 100644
index 000000000..1328eba40
--- /dev/null
+++ b/standalone/dsl/http-client/src/test/java/com/example/loan/GoodbyeWorldTests.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.loan;
+
+import org.junit.jupiter.api.Test;
+
+
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner;
+import org.springframework.cloud.contract.stubrunner.spring.StubRunnerPort;
+import org.springframework.cloud.contract.stubrunner.spring.StubRunnerProperties;
+
+import org.springframework.web.client.RestTemplate;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+// tag::autoconfigure_stubrunner[]
+
+@SpringBootTest(webEnvironment = WebEnvironment.NONE)
+@AutoConfigureStubRunner(ids = {
+ "com.example:http-server-dsl"},
+ repositoryRoot = "stubs://classpath:contractsAtRuntime/",
+ stubsMode = StubRunnerProperties.StubsMode.LOCAL,
+ generateStubs = true)
+public class GoodbyeWorldTests {
+ // end::autoconfigure_stubrunner[]
+
+ @StubRunnerPort("http-server-dsl")
+ int port;
+
+ @Test
+ public void shouldGenerateStubsAtRuntime() {
+ // when:
+ String response = new RestTemplate().getForObject("http://localhost:" + this.port + "/goodbye", String.class);
+ // then:
+ assertThat(response)
+ .isEqualTo("Goodbye World!");
+ }
+
+}
diff --git a/standalone/dsl/http-client/src/test/java/com/example/loan/LoanApplicationServiceContextPathTests.java b/standalone/dsl/http-client/src/test/java/com/example/loan/LoanApplicationServiceContextPathTests.java
new file mode 100644
index 000000000..f30cac718
--- /dev/null
+++ b/standalone/dsl/http-client/src/test/java/com/example/loan/LoanApplicationServiceContextPathTests.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.loan;
+
+import com.example.loan.model.Client;
+import com.example.loan.model.LoanApplication;
+import com.example.loan.model.LoanApplicationResult;
+import com.example.loan.model.LoanApplicationStatus;
+import org.junit.jupiter.api.Test;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner;
+import org.springframework.cloud.contract.stubrunner.spring.StubRunnerProperties;
+
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+
+@SpringBootTest(webEnvironment = WebEnvironment.NONE, properties = "server.context-path=/app")
+@AutoConfigureStubRunner(ids = {
+ "com.example:http-server-dsl:0.0.1:stubs:6565" }, stubsMode = StubRunnerProperties.StubsMode.LOCAL)
+public class LoanApplicationServiceContextPathTests {
+
+ @Autowired
+ private LoanApplicationService service;
+
+ @Test
+ public void shouldSuccessfullyApplyForLoan() {
+ // given:
+ LoanApplication application = new LoanApplication(new Client("1234567890"),
+ 123.123);
+ // when:
+ LoanApplicationResult loanApplication = service.loanApplication(application);
+ // then:
+ assertThat(loanApplication.getLoanApplicationStatus())
+ .isEqualTo(LoanApplicationStatus.LOAN_APPLIED);
+ assertThat(loanApplication.getRejectionReason()).isNull();
+ }
+
+ @Test
+ public void shouldBeRejectedDueToAbnormalLoanAmount() {
+ // given:
+ LoanApplication application = new LoanApplication(new Client("1234567890"),
+ 99999);
+ // when:
+ LoanApplicationResult loanApplication = service.loanApplication(application);
+ // then:
+ assertThat(loanApplication.getLoanApplicationStatus())
+ .isEqualTo(LoanApplicationStatus.LOAN_APPLICATION_REJECTED);
+ assertThat(loanApplication.getRejectionReason()).isEqualTo("Amount too high");
+ }
+
+}
diff --git a/standalone/dsl/http-client/src/test/java/com/example/loan/LoanApplicationServiceTests.java b/standalone/dsl/http-client/src/test/java/com/example/loan/LoanApplicationServiceTests.java
new file mode 100644
index 000000000..2d419b6a0
--- /dev/null
+++ b/standalone/dsl/http-client/src/test/java/com/example/loan/LoanApplicationServiceTests.java
@@ -0,0 +1,228 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.loan;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.nio.file.Files;
+import java.time.Duration;
+
+import com.example.loan.model.Client;
+import com.example.loan.model.LoanApplication;
+import com.example.loan.model.LoanApplicationResult;
+import com.example.loan.model.LoanApplicationStatus;
+import com.jayway.jsonpath.DocumentContext;
+import com.jayway.jsonpath.JsonPath;
+import io.restassured.RestAssured;
+import io.restassured.response.ResponseOptions;
+import io.restassured.specification.RequestSpecification;
+import org.assertj.core.api.BDDAssertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.boot.web.client.RestTemplateBuilder;
+import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner;
+import org.springframework.cloud.contract.stubrunner.spring.StubRunnerPort;
+import org.springframework.cloud.contract.stubrunner.spring.StubRunnerProperties;
+import org.springframework.http.RequestEntity;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.client.RestTemplate;
+
+import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson;
+import static org.assertj.core.api.Assertions.assertThat;
+
+// tag::autoconfigure_stubrunner[]
+
+@SpringBootTest(webEnvironment = WebEnvironment.NONE)
+@AutoConfigureStubRunner(ids = {
+ "com.example:http-server-dsl:0.0.1:stubs"}, stubsMode = StubRunnerProperties.StubsMode.LOCAL)
+public class LoanApplicationServiceTests {
+
+ // end::autoconfigure_stubrunner[]
+
+ @StubRunnerPort("com.example:http-server-dsl")
+ private int stubPort;
+
+ @Autowired
+ private LoanApplicationService service;
+
+ @BeforeEach
+ public void setup() {
+ this.service.setPrefix("");
+ this.service.setPort(this.stubPort);
+ }
+
+ @Test
+ public void shouldSuccessfullyApplyForLoan() {
+ // given:
+ LoanApplication application = new LoanApplication(new Client("1234567890"),
+ 123.123);
+ // when:
+ LoanApplicationResult loanApplication = service.loanApplication(application);
+ // then:
+ assertThat(loanApplication.getLoanApplicationStatus())
+ .isEqualTo(LoanApplicationStatus.LOAN_APPLIED);
+ assertThat(loanApplication.getRejectionReason()).isNull();
+ }
+
+ // tag::client_tdd[]
+ @Test
+ public void shouldBeRejectedDueToAbnormalLoanAmount() {
+ // given:
+ LoanApplication application = new LoanApplication(new Client("1234567890"),
+ 99999);
+ // when:
+ LoanApplicationResult loanApplication = service.loanApplication(application);
+ // then:
+ assertThat(loanApplication.getLoanApplicationStatus())
+ .isEqualTo(LoanApplicationStatus.LOAN_APPLICATION_REJECTED);
+ assertThat(loanApplication.getRejectionReason()).isEqualTo("Amount too high");
+ }
+ // end::client_tdd[]
+
+ @Test
+ public void shouldSuccessfullyGetAllFrauds() {
+ // when:
+ int count = service.countAllFrauds();
+ // then:
+ assertThat(count).isGreaterThanOrEqualTo(200);
+ }
+
+ @Test
+ public void shouldSuccessfullyGetAllDrunks() {
+ // when:
+ int count = service.countDrunks();
+ // then:
+ assertThat(count).isEqualTo(100);
+ }
+
+ // metadata
+ @Test
+ public void shouldFailToSuccessfullyGetAllDrunksDueToTimeout() {
+ LoanApplicationService service = new LoanApplicationService(new RestTemplateBuilder().setReadTimeout(Duration.ofSeconds(1)));
+ service.setPort(this.stubPort);
+ // when:
+ BDDAssertions.thenThrownBy(service::countDrunks).hasMessageContaining("Read timed out");
+ }
+
+ @Test
+ public void shouldSuccessfullyGetCookies() {
+ // when:
+ String cookies = service.getCookies();
+ // then:
+ assertThat(cookies).isEqualTo("foo bar");
+ }
+
+ @Test
+ public void shouldSuccessfullyWorkWithMultipart() {
+ // given:
+ RequestSpecification request = RestAssured.given()
+ .baseUri("http://localhost:" + stubPort + "/")
+ .header("Content-Type", "multipart/form-data")
+ .multiPart("file1", "filename1", "content1".getBytes())
+ .multiPart("file2", "filename1", "content2".getBytes()).multiPart("test",
+ "filename1", "{\n \"status\": \"test\"\n}".getBytes(),
+ "application/json");
+
+ // when:
+ ResponseOptions response = RestAssured.given().spec(request).post("/tests");
+
+ // then:
+ assertThat(response.statusCode()).isEqualTo(200);
+ assertThat(response.header("Content-Type")).matches("application/json.*");
+ // and:
+ DocumentContext parsedJson = JsonPath.parse(response.getBody().asString());
+ assertThatJson(parsedJson).field("['status']").isEqualTo("ok");
+ }
+
+ @Test
+ public void shouldSuccessfullyWorkWithBinary() throws IOException {
+ // given:
+ File request = new File(LoanApplicationServiceTests.class
+ .getResource("/binary/request.pdf").getFile());
+ File response = new File(LoanApplicationServiceTests.class
+ .getResource("/binary/response.pdf").getFile());
+
+ // when:
+ ResponseEntity exchange = new RestTemplate()
+ .exchange(
+ RequestEntity.put(URI.create("http://localhost:" + stubPort + "/1"))
+ .header("Content-Type", "application/octet-stream")
+ .body(Files.readAllBytes(request.toPath())),
+ byte[].class);
+
+ // then:
+ assertThat(exchange.getStatusCodeValue()).isEqualTo(200);
+ assertThat(exchange.getHeaders().get("Content-Type").get(0))
+ .isEqualTo("application/octet-stream");
+ // and:
+ assertThat(exchange.getBody()).isEqualTo(Files.readAllBytes(response.toPath()));
+ }
+
+
+ @Test
+ public void shouldSuccessfullyApplyForLoanForYaml() {
+ this.service.setPrefix("yaml");
+ // given:
+ LoanApplication application = new LoanApplication(new Client("1234567890"),
+ 123.123);
+ // when:
+ LoanApplicationResult loanApplication = service.loanApplication(application);
+ // then:
+ assertThat(loanApplication.getLoanApplicationStatus())
+ .isEqualTo(LoanApplicationStatus.LOAN_APPLIED);
+ assertThat(loanApplication.getRejectionReason()).isNull();
+ }
+
+ @Test
+ public void shouldBeRejectedDueToAbnormalLoanAmountForYaml() {
+ this.service.setPrefix("yaml");
+ // given:
+ LoanApplication application = new LoanApplication(new Client("1234567890"),
+ 99999);
+ // when:
+ LoanApplicationResult loanApplication = service.loanApplication(application);
+ // then:
+ assertThat(loanApplication.getLoanApplicationStatus())
+ .isEqualTo(LoanApplicationStatus.LOAN_APPLICATION_REJECTED);
+ assertThat(loanApplication.getRejectionReason()).isEqualTo("Amount too high");
+ }
+
+ @Test
+ public void shouldSuccessfullyGetAllFraudsForYaml() {
+ this.service.setPrefix("yaml");
+ // when:
+ int count = service.countAllFrauds();
+ // then:
+ assertThat(count).isGreaterThanOrEqualTo(200);
+ }
+
+ // metadata
+ @Test
+ public void shouldFailToSuccessfullyGetAllDrunksDueToTimeoutForYaml() {
+ LoanApplicationService service = new LoanApplicationService(new RestTemplateBuilder().setReadTimeout(Duration.ofSeconds(1)));
+ service.setPort(this.stubPort);
+ service.setPrefix("yaml");
+ // when:
+ BDDAssertions.thenThrownBy(service::countAllFrauds).hasMessageContaining("Read timed out");
+ }
+
+}
\ No newline at end of file
diff --git a/standalone/dsl/http-client/src/test/java/com/example/loan/MessageConsumedTests.java b/standalone/dsl/http-client/src/test/java/com/example/loan/MessageConsumedTests.java
new file mode 100644
index 000000000..a581f3da1
--- /dev/null
+++ b/standalone/dsl/http-client/src/test/java/com/example/loan/MessageConsumedTests.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2016-2020 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.
+ */
+
+package com.example.loan;
+
+import org.junit.jupiter.api.Test;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.boot.test.context.TestConfiguration;
+import org.springframework.cloud.contract.stubrunner.StubTrigger;
+import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner;
+import org.springframework.cloud.contract.stubrunner.spring.StubRunnerProperties;
+import org.springframework.cloud.stream.binder.test.TestChannelBinderConfiguration;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * @author Marius Bogoevici
+ */
+@SpringBootTest(webEnvironment = WebEnvironment.NONE, properties = "spring.cloud.stream.bindings.input.destination=sensor-data", classes = {MessageConsumedTests.Config.class, Application.class})
+@AutoConfigureStubRunner(ids = "com.example:http-server-dsl:0.0.1", stubsMode = StubRunnerProperties.StubsMode.LOCAL)
+public class MessageConsumedTests {
+
+ @Autowired
+ StubTrigger stubTrigger;
+
+ @Autowired
+ Listener listener;
+
+ @Test
+ public void testMessageConsumed() throws Exception {
+ int count = this.listener.getCount();
+ stubTrigger.trigger("sensor1");
+ assertThat(this.listener.getCount()).isEqualTo(count + 1);
+ }
+
+ @TestConfiguration
+ @ImportAutoConfiguration(TestChannelBinderConfiguration.class)
+ static class Config {
+
+ }
+}
diff --git a/standalone/dsl/http-client/src/test/java/com/example/loan/TestControllerTests.java b/standalone/dsl/http-client/src/test/java/com/example/loan/TestControllerTests.java
new file mode 100644
index 000000000..01f0ff4b4
--- /dev/null
+++ b/standalone/dsl/http-client/src/test/java/com/example/loan/TestControllerTests.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.loan;
+
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+
+
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner;
+import org.springframework.cloud.contract.stubrunner.spring.StubRunnerPort;
+import org.springframework.cloud.contract.stubrunner.spring.StubRunnerProperties;
+import org.springframework.http.ResponseEntity;
+
+import org.springframework.web.client.RestTemplate;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+// tag::autoconfigure_stubrunner[]
+
+@SpringBootTest(webEnvironment = WebEnvironment.NONE)
+@AutoConfigureStubRunner(ids = {
+ "com.example:http-server-dsl:0.0.1:stubs:6565"}, stubsMode = StubRunnerProperties.StubsMode.LOCAL)
+@Disabled("TODO: Need to fix java parsing")
+public class TestControllerTests {
+ // end::autoconfigure_stubrunner[]
+
+ @StubRunnerPort("http-server-dsl")
+ int port;
+
+ @Test
+ public void should_work_with_java_dsl() {
+ // when:
+ ResponseEntity response = new RestTemplate()
+ .getForEntity("http://localhost:" + this.port + "/example", String.class);
+ // then:
+ assertThat(response.getStatusCodeValue()).isEqualTo(200);
+ }
+
+}
diff --git a/standalone/dsl/http-client/src/test/resources/application-gradle.yaml b/standalone/dsl/http-client/src/test/resources/application-gradle.yaml
new file mode 100644
index 000000000..3de9f8be9
--- /dev/null
+++ b/standalone/dsl/http-client/src/test/resources/application-gradle.yaml
@@ -0,0 +1,3 @@
+stubrunner:
+ stubs-mode: local
+ stubs.ids: 'com.example:http-server-dsl-gradle:+:stubs:6565'
diff --git a/standalone/dsl/http-client/src/test/resources/application-test-repo.yaml b/standalone/dsl/http-client/src/test/resources/application-test-repo.yaml
new file mode 100644
index 000000000..512cbc68e
--- /dev/null
+++ b/standalone/dsl/http-client/src/test/resources/application-test-repo.yaml
@@ -0,0 +1,3 @@
+stubrunner:
+ ids: 'com.example:http-server-dsl:+:stubs:8080'
+ repositoryRoot: https://repo.spring.io/libs-snapshot
diff --git a/standalone/dsl/http-client/src/test/resources/application.yaml b/standalone/dsl/http-client/src/test/resources/application.yaml
new file mode 100644
index 000000000..78a78e6fa
--- /dev/null
+++ b/standalone/dsl/http-client/src/test/resources/application.yaml
@@ -0,0 +1,5 @@
+server:
+ port: 6565
+logging:
+ level:
+ org.springframework.cloud.contract: debug
diff --git a/standalone/dsl/http-client/src/test/resources/binary/request.pdf b/standalone/dsl/http-client/src/test/resources/binary/request.pdf
new file mode 100644
index 000000000..69503635d
Binary files /dev/null and b/standalone/dsl/http-client/src/test/resources/binary/request.pdf differ
diff --git a/standalone/dsl/http-client/src/test/resources/binary/response.pdf b/standalone/dsl/http-client/src/test/resources/binary/response.pdf
new file mode 100644
index 000000000..c3b233056
Binary files /dev/null and b/standalone/dsl/http-client/src/test/resources/binary/response.pdf differ
diff --git a/standalone/dsl/http-client/src/test/resources/contractsAtRuntime/goodbyeWorld.groovy b/standalone/dsl/http-client/src/test/resources/contractsAtRuntime/goodbyeWorld.groovy
new file mode 100644
index 000000000..c432ed21e
--- /dev/null
+++ b/standalone/dsl/http-client/src/test/resources/contractsAtRuntime/goodbyeWorld.groovy
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+import org.springframework.cloud.contract.spec.Contract
+
+Contract.make {
+ request {
+ url("/goodbye")
+ method(GET())
+ }
+ response {
+ status(OK())
+ body("Goodbye World!")
+ }
+}
diff --git a/standalone/dsl/http-server/.gitignore b/standalone/dsl/http-server/.gitignore
new file mode 100644
index 000000000..b05ba7bd6
--- /dev/null
+++ b/standalone/dsl/http-server/.gitignore
@@ -0,0 +1,6 @@
+
+target/
+
+.gradle
+build/
+
diff --git a/standalone/dsl/http-server/.mvn/jvm.config b/standalone/dsl/http-server/.mvn/jvm.config
new file mode 100644
index 000000000..0e7dabeff
--- /dev/null
+++ b/standalone/dsl/http-server/.mvn/jvm.config
@@ -0,0 +1 @@
+-Xmx1024m -XX:CICompilerCount=1 -XX:TieredStopAtLevel=1 -Djava.security.egd=file:/dev/./urandom
\ No newline at end of file
diff --git a/standalone/dsl/http-server/.mvn/maven.config b/standalone/dsl/http-server/.mvn/maven.config
new file mode 100644
index 000000000..a68299056
--- /dev/null
+++ b/standalone/dsl/http-server/.mvn/maven.config
@@ -0,0 +1 @@
+-P spring
diff --git a/standalone/dsl/http-server/.mvn/wrapper/MavenWrapperDownloader.java b/standalone/dsl/http-server/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 000000000..b901097f2
--- /dev/null
+++ b/standalone/dsl/http-server/.mvn/wrapper/MavenWrapperDownloader.java
@@ -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();
+ }
+
+}
diff --git a/standalone/dsl/http-server/.mvn/wrapper/maven-wrapper.jar b/standalone/dsl/http-server/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 000000000..c1dd12f17
Binary files /dev/null and b/standalone/dsl/http-server/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/standalone/dsl/http-server/.mvn/wrapper/maven-wrapper.properties b/standalone/dsl/http-server/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 000000000..015dfe682
--- /dev/null
+++ b/standalone/dsl/http-server/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,18 @@
+# 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.
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.3/apache-maven-3.8.3-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar
diff --git a/standalone/dsl/http-server/README.adoc b/standalone/dsl/http-server/README.adoc
new file mode 100644
index 000000000..2fd3fbc40
--- /dev/null
+++ b/standalone/dsl/http-server/README.adoc
@@ -0,0 +1,20 @@
+= Http Server
+
+Run
+
+[source=groovy]
+--------
+./gradlew clean build publishToMavenLocal
+--------
+
+or
+
+--------
+./mvnw clean install
+--------
+
+To
+
+- build the app
+- generate and run Spring Cloud Contract Verifier tests
+- publish the fatJar and the stubs to Maven Local
\ No newline at end of file
diff --git a/standalone/dsl/http-server/build.gradle b/standalone/dsl/http-server/build.gradle
new file mode 100644
index 000000000..ee8ee3d41
--- /dev/null
+++ b/standalone/dsl/http-server/build.gradle
@@ -0,0 +1,95 @@
+plugins {
+ id "java"
+ id "org.springframework.boot"
+ id "io.spring.dependency-management"
+ id "org.springframework.cloud.contract"
+ id "maven-publish"
+}
+
+group = 'com.example'
+version = '0.0.1'
+
+// tag::deps_repos[]
+repositories {
+ mavenCentral()
+ mavenLocal()
+ maven { url "https://repo.spring.io/snapshot" }
+ maven { url "https://repo.spring.io/milestone" }
+}
+// end::deps_repos[]
+
+dependencyManagement {
+ imports {
+ mavenBom "org.springframework.cloud:spring-cloud-contract-dependencies:$verifierVersion"
+ mavenBom "org.springframework.cloud:spring-cloud-stream-dependencies:$springCloudStreamVersion"
+ }
+}
+
+contracts {
+ packageWithBaseClasses = 'com.example.fraud'
+// convertToYaml = true
+ contractsDslDir = file("src/test/resources/contracts")
+}
+
+dependencies {
+ implementation("org.springframework.boot:spring-boot-starter-web")
+ implementation("org.springframework.boot:spring-boot-starter-actuator")
+ implementation("org.springframework.cloud:spring-cloud-starter-stream-rabbit")
+
+ testImplementation 'org.springframework.cloud:spring-cloud-starter-contract-verifier'
+ testImplementation(group: 'org.springframework.cloud', name: 'spring-cloud-stream-test-binder')
+ testImplementation('org.springframework.boot:spring-boot-starter-test') {
+ exclude(group: 'org.junit.vintage', module: 'junit-vintage-engine')
+ }
+}
+
+contractTest {
+ systemProperty 'spring.profiles.active', 'gradle'
+ testLogging {
+ exceptionFormat = 'full'
+ }
+ afterSuite { desc, result ->
+ if (!desc.parent) {
+ println "Results: (${result.testCount} tests, ${result.successfulTestCount} successes, ${result.failedTestCount} failures, ${result.skippedTestCount} skipped)"
+ if (result.testCount == 0) {
+ throw new IllegalStateException("No tests were found. Failing the build")
+ }
+ }
+ }
+}
+
+publishing {
+ publications {
+ maven(MavenPublication) {
+ artifact bootJar
+ artifact verifierStubsJar
+
+ // https://github.com/spring-gradle-plugins/dependency-management-plugin/issues/273
+ versionMapping {
+ usage("java-api") {
+ fromResolutionOf("runtimeClasspath")
+ }
+ usage("java-runtime") {
+ fromResolutionResult()
+ }
+ }
+ }
+ }
+}
+
+clean.doFirst {
+ delete "~/.m2/repository/com/example/http-server-dsl-gradle"
+}
+
+task resolveDependencies {
+ doLast {
+ project.rootProject.allprojects.each { subProject ->
+ subProject.buildscript.configurations.each { configuration ->
+ configuration.resolve()
+ }
+ subProject.configurations.each { configuration ->
+ configuration.resolve()
+ }
+ }
+ }
+}
diff --git a/standalone/dsl/http-server/gradle.properties b/standalone/dsl/http-server/gradle.properties
new file mode 100644
index 000000000..7ae982c8f
--- /dev/null
+++ b/standalone/dsl/http-server/gradle.properties
@@ -0,0 +1,4 @@
+org.gradle.daemon=false
+verifierVersion=4.1.5-SNAPSHOT
+springCloudStreamVersion=4.1.4-SNAPSHOT
+bootVersion=3.2.7
\ No newline at end of file
diff --git a/standalone/dsl/http-server/gradle/wrapper/gradle-wrapper.jar b/standalone/dsl/http-server/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 000000000..7f93135c4
Binary files /dev/null and b/standalone/dsl/http-server/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/standalone/dsl/http-server/gradle/wrapper/gradle-wrapper.properties b/standalone/dsl/http-server/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 000000000..ac72c34e8
--- /dev/null
+++ b/standalone/dsl/http-server/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,7 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
+networkTimeout=10000
+validateDistributionUrl=true
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/standalone/dsl/http-server/gradlew b/standalone/dsl/http-server/gradlew
new file mode 100755
index 000000000..0adc8e1a5
--- /dev/null
+++ b/standalone/dsl/http-server/gradlew
@@ -0,0 +1,249 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original 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 POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
+done
+
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+ echo "$*"
+} >&2
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+} >&2
+
+# 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 ;; #(
+ MSYS* | 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
+ if ! command -v java >/dev/null 2>&1
+ then
+ 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
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC3045
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC3045
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+
+# 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"'
+
+# Collect all arguments for the java command;
+# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+# shell script including quotes and variable substitutions, so put them in
+# double quotes to make sure that they get re-expanded; and
+# * put everything else in single quotes, so that it's not re-expanded.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+ die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/standalone/dsl/http-server/gradlew.bat b/standalone/dsl/http-server/gradlew.bat
new file mode 100644
index 000000000..93e3f59f1
--- /dev/null
+++ b/standalone/dsl/http-server/gradlew.bat
@@ -0,0 +1,92 @@
+@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=.
+@rem This is normally unused
+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% equ 0 goto execute
+
+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 execute
+
+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
+
+: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 %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if %ERRORLEVEL% equ 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!
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/standalone/dsl/http-server/mvnw b/standalone/dsl/http-server/mvnw
new file mode 100755
index 000000000..5643201c7
--- /dev/null
+++ b/standalone/dsl/http-server/mvnw
@@ -0,0 +1,316 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# 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 /usr/local/etc/mavenrc ] ; then
+ . /usr/local/etc/mavenrc
+ fi
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ export JAVA_HOME="`/usr/libexec/java_home`"
+ else
+ export JAVA_HOME="/Library/Java/Home"
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=`java-config --jre-home`
+ fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+ ## resolve links - $0 may be a link to maven's home
+ PRG="$0"
+
+ # need this for relative symlinks
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG="`dirname "$PRG"`/$link"
+ fi
+ done
+
+ saveddir=`pwd`
+
+ M2_HOME=`dirname "$PRG"`/..
+
+ # make it fully qualified
+ M2_HOME=`cd "$M2_HOME" && pwd`
+
+ cd "$saveddir"
+ # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --unix "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME="`(cd "$M2_HOME"; pwd)`"
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="`which javac`"
+ if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=`which readlink`
+ if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+ if $darwin ; then
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+ else
+ javaExecutable="`readlink -f \"$javaExecutable\"`"
+ fi
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="`\\unset -f command; \\command -v java`"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=`cd "$wdir/.."; pwd`
+ fi
+ # end of workaround
+ done
+ echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ echo "$(tr -s '\n' ' ' < "$1")"
+ fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found .mvn/wrapper/maven-wrapper.jar"
+ fi
+else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+ fi
+ if [ -n "$MVNW_REPOURL" ]; then
+ jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+ else
+ jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+ fi
+ while IFS="=" read key value; do
+ case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
+ esac
+ done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Downloading from: $jarUrl"
+ fi
+ wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+ if $cygwin; then
+ wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
+ fi
+
+ if command -v wget > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found wget ... using wget"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ else
+ wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ fi
+ elif command -v curl > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found curl ... using curl"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl -o "$wrapperJarPath" "$jarUrl" -f
+ else
+ curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
+ fi
+
+ else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Falling back to using Java to download"
+ fi
+ javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaClass=`cygpath --path --windows "$javaClass"`
+ fi
+ if [ -e "$javaClass" ]; then
+ if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Compiling MavenWrapperDownloader.java ..."
+ fi
+ # Compiling the Java class
+ ("$JAVA_HOME/bin/javac" "$javaClass")
+ fi
+ if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ # Running the downloader
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Running MavenWrapperDownloader.java ..."
+ fi
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+if [ "$MVNW_VERBOSE" = true ]; then
+ echo $MAVEN_PROJECTBASEDIR
+fi
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --path --windows "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ $MAVEN_DEBUG_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.home=${M2_HOME}" \
+ "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/standalone/dsl/http-server/mvnw.cmd b/standalone/dsl/http-server/mvnw.cmd
new file mode 100644
index 000000000..8a15b7f31
--- /dev/null
+++ b/standalone/dsl/http-server/mvnw.cmd
@@ -0,0 +1,188 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM 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 "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
+if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Found %WRAPPER_JAR%
+ )
+) else (
+ if not "%MVNW_REPOURL%" == "" (
+ SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+ )
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %DOWNLOAD_URL%
+ )
+
+ powershell -Command "&{"^
+ "$webclient = new-object System.Net.WebClient;"^
+ "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+ "}"^
+ "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
+ "}"
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Finished downloading %WRAPPER_JAR%
+ )
+)
+@REM End of extension
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% ^
+ %JVM_CONFIG_MAVEN_PROPS% ^
+ %MAVEN_OPTS% ^
+ %MAVEN_DEBUG_OPTS% ^
+ -classpath %WRAPPER_JAR% ^
+ "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
+ %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
+if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%"=="on" pause
+
+if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
+
+cmd /C exit /B %ERROR_CODE%
diff --git a/standalone/dsl/http-server/pom.xml b/standalone/dsl/http-server/pom.xml
new file mode 100644
index 000000000..745278a1d
--- /dev/null
+++ b/standalone/dsl/http-server/pom.xml
@@ -0,0 +1,333 @@
+
+
+ 4.0.0
+
+ com.example
+ http-server-dsl
+ 0.0.1
+
+ Spring Cloud Contract Verifier Http Server Sample
+ Spring Cloud Contract Verifier Http Server Sample
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.2.7
+
+
+
+
+ UTF-8
+ 17
+ 4.1.5-SNAPSHOT
+ 4.1.4-SNAPSHOT
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.junit.vintage
+ junit-vintage-engine
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-stream-rabbit
+
+
+
+ org.springframework.cloud
+ spring-cloud-stream-test-binder
+ test
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-contract-verifier
+ test
+
+
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-contract-dependencies
+ ${spring-cloud-contract.version}
+ pom
+ import
+
+
+
+ org.springframework.cloud
+ spring-cloud-stream-dependencies
+ ${spring-cloud-stream.version}
+ pom
+ import
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ org.springframework.cloud
+ spring-cloud-contract-maven-plugin
+ ${spring-cloud-contract.version}
+ true
+
+ com.example.fraud
+
+
+
+
+
+ maven-deploy-plugin
+ 2.8.2
+
+ true
+
+
+
+ org.apache.maven.plugins
+ maven-clean-plugin
+ 3.0.0
+
+
+
+ build
+
+
+ target
+
+
+
+
+
+ maven-surefire-plugin
+
+ true
+
+
+
+ org.apache.maven.plugins
+ maven-antrun-plugin
+ 3.1.0
+
+
+ process-test-resources
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ run
+
+
+
+
+
+ ant-contrib
+ ant-contrib
+ 20020829
+
+
+
+
+
+
+
+
+ org.eclipse.m2e
+ lifecycle-mapping
+ 1.0.0
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-contract-maven-plugin
+
+
+ [${spring-cloud-contract.version},)
+
+
+ convert
+ generateTests
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
+
+
+ integration
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 1.6.0
+
+
+ gradle
+ test
+
+ ./gradlew
+
+ clean
+ build
+ publishToMavenLocal
+
+ -x
+ test
+
+ -x
+ contractTest
+
+ -PverifierVersion=${spring-cloud-contract.version}
+
+
+
+
+ exec
+
+
+
+
+
+
+
+
+ windows
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 1.6.0
+
+
+ gradle
+ test
+
+ gradlew.bat
+
+ clean
+ build
+ publishToMavenLocal
+
+ -x
+ test
+
+ -x
+ contractTest
+
+ -PverifierVersion=${spring-cloud-contract.version}
+
+
+
+
+ exec
+
+
+
+
+
+
+
+
+
diff --git a/standalone/dsl/http-server/settings.gradle b/standalone/dsl/http-server/settings.gradle
new file mode 100644
index 000000000..ec18a2944
--- /dev/null
+++ b/standalone/dsl/http-server/settings.gradle
@@ -0,0 +1,24 @@
+// tag::repos[]
+pluginManagement {
+ repositories {
+ mavenLocal()
+ maven { url "https://repo.spring.io/snapshot" }
+ maven { url "https://repo.spring.io/milestone" }
+ gradlePluginPortal()
+ }
+// end::repos[]
+ plugins {
+ id "org.springframework.boot" version "${bootVersion}"
+ id "io.spring.dependency-management" version "1.1.3"
+ }
+ resolutionStrategy {
+ eachPlugin {
+ // protects us in case the gradle-portal-plugin hasn't yet been published by Maven
+ if (requested.id.id == 'org.springframework.cloud.contract') {
+ useModule("org.springframework.cloud:spring-cloud-contract-gradle-plugin:${verifierVersion}")
+ }
+ }
+ }
+}
+
+rootProject.name = 'http-server-dsl-gradle'
diff --git a/standalone/dsl/http-server/src/main/java/com/example/fraud/Application.java b/standalone/dsl/http-server/src/main/java/com/example/fraud/Application.java
new file mode 100644
index 000000000..b4562bfce
--- /dev/null
+++ b/standalone/dsl/http-server/src/main/java/com/example/fraud/Application.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.fraud;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+}
diff --git a/standalone/dsl/http-server/src/main/java/com/example/fraud/FooController.java b/standalone/dsl/http-server/src/main/java/com/example/fraud/FooController.java
new file mode 100644
index 000000000..168967c6f
--- /dev/null
+++ b/standalone/dsl/http-server/src/main/java/com/example/fraud/FooController.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.fraud;
+
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author Marcin Grzejszczak
+ */
+@RestController
+class FooController {
+
+ @GetMapping("/foo")
+ void foo() {
+
+ }
+
+}
diff --git a/standalone/dsl/http-server/src/main/java/com/example/fraud/FraudDetectionController.java b/standalone/dsl/http-server/src/main/java/com/example/fraud/FraudDetectionController.java
new file mode 100644
index 000000000..bf84fc94b
--- /dev/null
+++ b/standalone/dsl/http-server/src/main/java/com/example/fraud/FraudDetectionController.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.fraud;
+
+import java.math.BigDecimal;
+
+import com.example.fraud.model.FraudCheck;
+import com.example.fraud.model.FraudCheckResult;
+import com.example.fraud.model.FraudCheckStatus;
+
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import static org.springframework.web.bind.annotation.RequestMethod.PUT;
+
+@RestController
+public class FraudDetectionController {
+
+ private static final String NO_REASON = null;
+
+ private static final String AMOUNT_TOO_HIGH = "Amount too high";
+
+ private static final BigDecimal MAX_AMOUNT = new BigDecimal("5000");
+
+ // tag::server_api[]
+ @RequestMapping(value = "/fraudcheck", method = PUT)
+ public FraudCheckResult fraudCheck(@RequestBody FraudCheck fraudCheck) {
+ // end::server_api[]
+ // tag::new_impl[]
+ if (amountGreaterThanThreshold(fraudCheck)) {
+ return new FraudCheckResult(FraudCheckStatus.FRAUD, AMOUNT_TOO_HIGH);
+ }
+ // end::new_impl[]
+ // tag::initial_impl[]
+ return new FraudCheckResult(FraudCheckStatus.OK, NO_REASON);
+ // end::initial_impl[]
+ }
+
+ @RequestMapping(value = "/yamlfraudcheck", method = PUT)
+ public FraudCheckResult yamlFraudCheck(@RequestBody FraudCheck fraudCheck) {
+ return fraudCheck(fraudCheck);
+ }
+
+ private boolean amountGreaterThanThreshold(FraudCheck fraudCheck) {
+ return MAX_AMOUNT.compareTo(fraudCheck.getLoanAmount()) < 0;
+ }
+
+}
diff --git a/standalone/dsl/http-server/src/main/java/com/example/fraud/FraudNameController.java b/standalone/dsl/http-server/src/main/java/com/example/fraud/FraudNameController.java
new file mode 100644
index 000000000..3b638e5b7
--- /dev/null
+++ b/standalone/dsl/http-server/src/main/java/com/example/fraud/FraudNameController.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.fraud;
+
+import org.springframework.stereotype.Component;
+import org.springframework.web.bind.annotation.CookieValue;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RestController;
+
+interface FraudVerifier {
+
+ boolean isFraudByName(String name);
+
+}
+
+/**
+ * @author Marcin Grzejszczak
+ */
+@RestController
+class FraudNameController {
+
+ private final FraudVerifier fraudVerifier;
+
+ FraudNameController(FraudVerifier fraudVerifier) {
+ this.fraudVerifier = fraudVerifier;
+ }
+
+ @PutMapping(value = "/frauds/name")
+ public NameResponse checkByName(@RequestBody NameRequest request) {
+ boolean fraud = this.fraudVerifier.isFraudByName(request.getName());
+ if (fraud) {
+ return new NameResponse("Sorry " + request.getName() + " but you're a fraud");
+ }
+ return new NameResponse(
+ "Don't worry " + request.getName() + " you're not a fraud");
+ }
+
+ @GetMapping(value = "/frauds/name")
+ public String checkByName(@CookieValue("name") String value,
+ @CookieValue("name2") String value2) {
+ return value + " " + value2;
+ }
+
+ @PutMapping(value = "/yamlfrauds/name")
+ public NameResponse yamlCheckByName(@RequestBody NameRequest request) {
+ return checkByName(request);
+ }
+
+ @GetMapping(value = "/yamlfrauds/name")
+ public String yamlCheckByName(@CookieValue("name") String value,
+ @CookieValue("name2") String value2) {
+ return checkByName(value, value2);
+ }
+
+}
+
+class NameRequest {
+
+ private String name;
+
+ public NameRequest(String name) {
+ this.name = name;
+ }
+
+ public NameRequest() {
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+}
+
+class NameResponse {
+
+ private String result;
+
+ public NameResponse(String result) {
+ this.result = result;
+ }
+
+ public NameResponse() {
+ }
+
+ public String getResult() {
+ return this.result;
+ }
+
+ public void setResult(String result) {
+ this.result = result;
+ }
+
+}
+
+@Component
+class DefaultFraudVerifier implements FraudVerifier {
+
+ @Override
+ public boolean isFraudByName(String name) {
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/standalone/dsl/http-server/src/main/java/com/example/fraud/FraudStatsController.java b/standalone/dsl/http-server/src/main/java/com/example/fraud/FraudStatsController.java
new file mode 100644
index 000000000..c8b7f11ca
--- /dev/null
+++ b/standalone/dsl/http-server/src/main/java/com/example/fraud/FraudStatsController.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.fraud;
+
+import org.springframework.stereotype.Component;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+enum FraudType {
+
+ DRUNKS, ALL
+
+}
+
+interface StatsProvider {
+
+ int count(FraudType fraudType);
+
+}
+
+@RestController
+public class FraudStatsController {
+
+ private final StatsProvider statsProvider;
+
+ public FraudStatsController(StatsProvider statsProvider) {
+ this.statsProvider = statsProvider;
+ }
+
+ @GetMapping(value = "/frauds")
+ public Response countAllFrauds() {
+ return new Response(this.statsProvider.count(FraudType.ALL));
+ }
+
+ @GetMapping(value = "/yamlfrauds")
+ public Response countAllYamlFrauds() {
+ return countAllFrauds();
+ }
+
+ @GetMapping(value = "/drunks")
+ public Response countAllDrunks() {
+ return new Response(this.statsProvider.count(FraudType.DRUNKS));
+ }
+
+ @GetMapping(value = "/yamldrunks")
+ public Response countAllYamlDrunks() {
+ return countAllDrunks();
+ }
+
+}
+
+class Response {
+
+ private int count;
+
+ public Response(int count) {
+ this.count = count;
+ }
+
+ public Response() {
+ }
+
+ public int getCount() {
+ return this.count;
+ }
+
+ public void setCount(int count) {
+ this.count = count;
+ }
+
+}
+
+@Component
+class DefaultStatsProvider implements StatsProvider {
+
+ @Override
+ public int count(FraudType fraudType) {
+ return 0;
+ }
+}
diff --git a/standalone/dsl/http-server/src/main/java/com/example/fraud/MessageSender.java b/standalone/dsl/http-server/src/main/java/com/example/fraud/MessageSender.java
new file mode 100644
index 000000000..9de0b3c5a
--- /dev/null
+++ b/standalone/dsl/http-server/src/main/java/com/example/fraud/MessageSender.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.fraud;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.nio.file.Files;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.springframework.cloud.stream.function.StreamBridge;
+import org.springframework.stereotype.Component;
+
+@Component
+class MessageSender {
+
+ private static final Logger log = LoggerFactory.getLogger(MessageSender.class);
+
+ private final StreamBridge streamBridge;
+
+ private final byte[] expectedOutput;
+
+ MessageSender(StreamBridge streamBridge) {
+ this.streamBridge = streamBridge;
+ this.expectedOutput = forFile("/contracts/messaging/output.pdf");
+ }
+
+ public void emit() {
+ log.info("Emitting the message");
+ this.streamBridge.send("sensor_data-out-0", "{\"id\":\"99\",\"temperature\":\"123.45\"}");
+ }
+
+ public void emitBytes() {
+ log.info("Emitting the message");
+ this.streamBridge.send("my_output-out-0", this.expectedOutput);
+ }
+
+ private byte[] forFile(String relative) {
+ URL resource = MessageSender.class.getResource(relative);
+ try {
+ return Files.readAllBytes(new File(resource.toURI()).toPath());
+ }
+ catch (IOException | URISyntaxException ex) {
+ throw new IllegalStateException(ex);
+ }
+ }
+}
diff --git a/standalone/dsl/http-server/src/main/java/com/example/fraud/MessagingConfiguration.java b/standalone/dsl/http-server/src/main/java/com/example/fraud/MessagingConfiguration.java
new file mode 100644
index 000000000..bfcc6f6e8
--- /dev/null
+++ b/standalone/dsl/http-server/src/main/java/com/example/fraud/MessagingConfiguration.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.fraud;
+
+import java.util.function.Supplier;
+
+import reactor.core.publisher.EmitterProcessor;
+import reactor.core.publisher.Flux;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+class MessagingConfiguration {
+
+ @Bean
+ EmitterProcessor sensorDataEmitter() {
+ return EmitterProcessor.create();
+ }
+
+ @Bean(name = "sensor_data")
+ Supplier> sensorData(EmitterProcessor processor) {
+ return () -> processor;
+ }
+}
diff --git a/standalone/dsl/http-server/src/main/java/com/example/fraud/TestController.java b/standalone/dsl/http-server/src/main/java/com/example/fraud/TestController.java
new file mode 100644
index 000000000..a52d073ee
--- /dev/null
+++ b/standalone/dsl/http-server/src/main/java/com/example/fraud/TestController.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.fraud;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.nio.file.Files;
+import java.util.Arrays;
+
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestPart;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+
+@RestController
+public class TestController {
+
+ private final byte[] request;
+
+ private final byte[] response;
+
+ public TestController() {
+ this.request = toByte(
+ TestController.class.getResource("/contracts/binary/request.pdf"));
+ this.response = toByte(
+ TestController.class.getResource("/contracts/binary/response.pdf"));
+ }
+
+ private byte[] toByte(URL url) {
+ try {
+ return Files.readAllBytes(new File(url.toURI()).toPath());
+ }
+ catch (URISyntaxException | IOException ex) {
+ throw new IllegalStateException(ex);
+ }
+ }
+
+ @PostMapping("/tests")
+ public Test createNew(@RequestPart MultipartFile file1,
+ @RequestPart MultipartFile file2, @RequestPart Test test) {
+ return new Test("ok");
+ }
+
+ @GetMapping("/example")
+ public void example() {
+ }
+
+ @PutMapping(value = "/1", consumes = MediaType.APPLICATION_OCTET_STREAM_VALUE, produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
+ public byte[] response(@RequestBody byte[] requestBody) {
+ if (!Arrays.equals(this.request, requestBody)) {
+ throw new IllegalStateException("Invalid request body");
+ }
+ return this.response;
+ }
+
+}
+
+class Test {
+
+ private String status;
+
+ public Test(String status) {
+ this.status = status;
+ }
+
+ public Test() {
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+}
diff --git a/standalone/dsl/http-server/src/main/java/com/example/fraud/model/FraudCheck.java b/standalone/dsl/http-server/src/main/java/com/example/fraud/model/FraudCheck.java
new file mode 100644
index 000000000..d0e348db2
--- /dev/null
+++ b/standalone/dsl/http-server/src/main/java/com/example/fraud/model/FraudCheck.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.fraud.model;
+
+import java.math.BigDecimal;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class FraudCheck {
+
+ @JsonProperty("client.id")
+ private String clientId;
+
+ private BigDecimal loanAmount;
+
+ public FraudCheck() {
+ }
+
+ public String getClientId() {
+ return clientId;
+ }
+
+ public void setClientId(String clientId) {
+ this.clientId = clientId;
+ }
+
+ public BigDecimal getLoanAmount() {
+ return loanAmount;
+ }
+
+ public void setLoanAmount(BigDecimal loanAmount) {
+ this.loanAmount = loanAmount;
+ }
+
+}
diff --git a/standalone/dsl/http-server/src/main/java/com/example/fraud/model/FraudCheckResult.java b/standalone/dsl/http-server/src/main/java/com/example/fraud/model/FraudCheckResult.java
new file mode 100644
index 000000000..c908038d0
--- /dev/null
+++ b/standalone/dsl/http-server/src/main/java/com/example/fraud/model/FraudCheckResult.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.fraud.model;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class FraudCheckResult {
+
+ private FraudCheckStatus fraudCheckStatus;
+
+ @JsonProperty("rejection.reason")
+ private String rejectionReason;
+
+ public FraudCheckResult() {
+ }
+
+ public FraudCheckResult(FraudCheckStatus fraudCheckStatus, String rejectionReason) {
+ this.fraudCheckStatus = fraudCheckStatus;
+ this.rejectionReason = rejectionReason;
+ }
+
+ public FraudCheckStatus getFraudCheckStatus() {
+ return fraudCheckStatus;
+ }
+
+ public void setFraudCheckStatus(FraudCheckStatus fraudCheckStatus) {
+ this.fraudCheckStatus = fraudCheckStatus;
+ }
+
+ public String getRejectionReason() {
+ return rejectionReason;
+ }
+
+ public void setRejectionReason(String rejectionReason) {
+ this.rejectionReason = rejectionReason;
+ }
+
+}
diff --git a/standalone/dsl/http-server/src/main/java/com/example/fraud/model/FraudCheckStatus.java b/standalone/dsl/http-server/src/main/java/com/example/fraud/model/FraudCheckStatus.java
new file mode 100644
index 000000000..a43b649f5
--- /dev/null
+++ b/standalone/dsl/http-server/src/main/java/com/example/fraud/model/FraudCheckStatus.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.fraud.model;
+
+public enum FraudCheckStatus {
+
+ OK, FRAUD
+
+}
diff --git a/standalone/dsl/http-server/src/main/resources/application.properties b/standalone/dsl/http-server/src/main/resources/application.properties
new file mode 100644
index 000000000..506b4f78c
--- /dev/null
+++ b/standalone/dsl/http-server/src/main/resources/application.properties
@@ -0,0 +1,5 @@
+spring.cloud.function.definition=my_output;sensor_data
+spring.cloud.stream.bindings.sensor_data-out-0.destination=sensor_data
+spring.cloud.stream.bindings.my_output-out-0.contentType=application/octet-stream
+spring.cloud.stream.bindings.my_output-out-0.destination=bytes_output
+server.port=0
diff --git a/standalone/dsl/http-server/src/test/java/com/example/fraud/BinaryBase.java b/standalone/dsl/http-server/src/test/java/com/example/fraud/BinaryBase.java
new file mode 100644
index 000000000..bfcd40f7c
--- /dev/null
+++ b/standalone/dsl/http-server/src/test/java/com/example/fraud/BinaryBase.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.fraud;
+
+import io.restassured.module.mockmvc.RestAssuredMockMvc;
+import org.junit.jupiter.api.BeforeEach;
+
+public class BinaryBase {
+
+ @BeforeEach
+ public void setUp() throws Exception {
+ RestAssuredMockMvc.standaloneSetup(new TestController());
+ }
+
+}
diff --git a/standalone/dsl/http-server/src/test/java/com/example/fraud/FraudBase.java b/standalone/dsl/http-server/src/test/java/com/example/fraud/FraudBase.java
new file mode 100644
index 000000000..3e462aa22
--- /dev/null
+++ b/standalone/dsl/http-server/src/test/java/com/example/fraud/FraudBase.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.fraud;
+
+import io.restassured.module.mockmvc.RestAssuredMockMvc;
+import org.junit.jupiter.api.BeforeEach;
+
+public class FraudBase {
+
+ @BeforeEach
+ public void setup() {
+ RestAssuredMockMvc.standaloneSetup(new FraudDetectionController(),
+ new FraudStatsController(stubbedStatsProvider()));
+ }
+
+ private StatsProvider stubbedStatsProvider() {
+ return fraudType -> {
+ switch (fraudType) {
+ case DRUNKS:
+ return 100;
+ case ALL:
+ return 200;
+ }
+ return 0;
+ };
+ }
+
+ public void assertThatRejectionReasonIsNull(Object rejectionReason) {
+ assert rejectionReason == null;
+ }
+
+}
diff --git a/standalone/dsl/http-server/src/test/java/com/example/fraud/FraudnameBase.java b/standalone/dsl/http-server/src/test/java/com/example/fraud/FraudnameBase.java
new file mode 100644
index 000000000..f38066f2b
--- /dev/null
+++ b/standalone/dsl/http-server/src/test/java/com/example/fraud/FraudnameBase.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.fraud;
+
+import io.restassured.module.mockmvc.RestAssuredMockMvc;
+import org.junit.jupiter.api.BeforeEach;
+
+public class FraudnameBase {
+
+ private static final String FRAUD_NAME = "fraud";
+
+ FraudVerifier fraudVerifier = FRAUD_NAME::equals;
+
+ @BeforeEach
+ public void setup() {
+ RestAssuredMockMvc.standaloneSetup(new FraudNameController(this.fraudVerifier));
+ }
+
+}
diff --git a/standalone/dsl/http-server/src/test/java/com/example/fraud/MessagingBase.java b/standalone/dsl/http-server/src/test/java/com/example/fraud/MessagingBase.java
new file mode 100644
index 000000000..aa08e66bf
--- /dev/null
+++ b/standalone/dsl/http-server/src/test/java/com/example/fraud/MessagingBase.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2016-2020 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.
+ */
+
+package com.example.fraud;
+
+import io.restassured.module.mockmvc.RestAssuredMockMvc;
+import org.junit.jupiter.api.BeforeEach;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.cloud.contract.verifier.messaging.boot.AutoConfigureMessageVerifier;
+import org.springframework.cloud.stream.binder.test.TestChannelBinderConfiguration;
+import org.springframework.context.annotation.Configuration;
+
+import org.springframework.web.context.WebApplicationContext;
+
+/**
+ * Base class for sensor autogenerated tests (used by Spring Cloud Contract).
+ *
+ * This bootstraps the Spring Boot application code.
+ *
+ * @author Marius Bogoevici
+ */
+
+@SpringBootTest(classes = {MessagingBase.Config.class, Application.class})
+@AutoConfigureMessageVerifier
+public abstract class MessagingBase {
+
+ @Autowired
+ MessageSender messageSender;
+
+ @Autowired
+ WebApplicationContext context;
+
+ @BeforeEach
+ public void setup() {
+ RestAssuredMockMvc.webAppContextSetup(this.context);
+ }
+
+ public void createSensorData() {
+ messageSender.emit();
+ }
+
+ public void createBinaryPayload() {
+ messageSender.emitBytes();
+ }
+
+ @Configuration
+ @ImportAutoConfiguration(TestChannelBinderConfiguration.class)
+ static class Config {
+
+ }
+
+}
diff --git a/standalone/dsl/http-server/src/test/java/com/example/fraud/MultipartBase.java b/standalone/dsl/http-server/src/test/java/com/example/fraud/MultipartBase.java
new file mode 100644
index 000000000..fa82da040
--- /dev/null
+++ b/standalone/dsl/http-server/src/test/java/com/example/fraud/MultipartBase.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.fraud;
+
+import io.restassured.module.mockmvc.RestAssuredMockMvc;
+import org.junit.jupiter.api.BeforeEach;
+
+public class MultipartBase {
+
+ @BeforeEach
+ public void setUp() throws Exception {
+ RestAssuredMockMvc.standaloneSetup(new TestController());
+ }
+
+}
diff --git a/standalone/dsl/http-server/src/test/java/com/example/fraud/TestBase.java b/standalone/dsl/http-server/src/test/java/com/example/fraud/TestBase.java
new file mode 100644
index 000000000..6a1c81d89
--- /dev/null
+++ b/standalone/dsl/http-server/src/test/java/com/example/fraud/TestBase.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.fraud;
+
+import io.restassured.module.mockmvc.RestAssuredMockMvc;
+import org.junit.jupiter.api.BeforeEach;
+
+public class TestBase {
+
+ @BeforeEach
+ public void setUp() throws Exception {
+ RestAssuredMockMvc.standaloneSetup(new TestController());
+ }
+
+}
diff --git a/standalone/dsl/http-server/src/test/java/com/example/fraud/YmlFraudBase.java b/standalone/dsl/http-server/src/test/java/com/example/fraud/YmlFraudBase.java
new file mode 100644
index 000000000..4e46c0783
--- /dev/null
+++ b/standalone/dsl/http-server/src/test/java/com/example/fraud/YmlFraudBase.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.fraud;
+
+import io.restassured.module.mockmvc.RestAssuredMockMvc;
+import org.junit.jupiter.api.BeforeEach;
+
+public class YmlFraudBase {
+
+ @BeforeEach
+ public void setup() {
+ RestAssuredMockMvc.standaloneSetup(new FraudDetectionController(),
+ new FraudStatsController(stubbedStatsProvider()));
+ }
+
+ private StatsProvider stubbedStatsProvider() {
+ return fraudType -> {
+ switch (fraudType) {
+ case DRUNKS:
+ return 100;
+ case ALL:
+ return 200;
+ }
+ return 0;
+ };
+ }
+
+ public void assertThatRejectionReasonIsNull(Object rejectionReason) {
+ assert rejectionReason == null;
+ }
+
+}
diff --git a/standalone/dsl/http-server/src/test/java/com/example/fraud/YmlFraudnameBase.java b/standalone/dsl/http-server/src/test/java/com/example/fraud/YmlFraudnameBase.java
new file mode 100644
index 000000000..abe32e3f0
--- /dev/null
+++ b/standalone/dsl/http-server/src/test/java/com/example/fraud/YmlFraudnameBase.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.fraud;
+
+import io.restassured.module.mockmvc.RestAssuredMockMvc;
+import org.junit.jupiter.api.BeforeEach;
+
+public class YmlFraudnameBase {
+
+ private static final String FRAUD_NAME = "fraud";
+
+ FraudVerifier fraudVerifier = FRAUD_NAME::equals;
+
+ @BeforeEach
+ public void setup() {
+ RestAssuredMockMvc.standaloneSetup(new FraudNameController(this.fraudVerifier));
+ }
+
+}
diff --git a/standalone/dsl/http-server/src/test/resources/contracts/binary/request.pdf b/standalone/dsl/http-server/src/test/resources/contracts/binary/request.pdf
new file mode 100644
index 000000000..69503635d
Binary files /dev/null and b/standalone/dsl/http-server/src/test/resources/contracts/binary/request.pdf differ
diff --git a/standalone/dsl/http-server/src/test/resources/contracts/binary/response.pdf b/standalone/dsl/http-server/src/test/resources/contracts/binary/response.pdf
new file mode 100644
index 000000000..c3b233056
Binary files /dev/null and b/standalone/dsl/http-server/src/test/resources/contracts/binary/response.pdf differ
diff --git a/standalone/dsl/http-server/src/test/resources/contracts/binary/shouldWorkWithBinaryPayload.groovy b/standalone/dsl/http-server/src/test/resources/contracts/binary/shouldWorkWithBinaryPayload.groovy
new file mode 100644
index 000000000..494ddd7cd
--- /dev/null
+++ b/standalone/dsl/http-server/src/test/resources/contracts/binary/shouldWorkWithBinaryPayload.groovy
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package contracts
+
+import org.springframework.cloud.contract.spec.Contract
+
+Contract.make {
+ request {
+ url("/1")
+ method(PUT())
+ headers {
+ contentType(applicationOctetStream())
+ }
+ body(fileAsBytes("request.pdf"))
+ }
+ response {
+ status 200
+ body(fileAsBytes("response.pdf"))
+ headers {
+ contentType(applicationOctetStream())
+ }
+ }
+}
diff --git a/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsFraud.groovy b/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsFraud.groovy
new file mode 100644
index 000000000..d056ad13f
--- /dev/null
+++ b/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsFraud.groovy
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package contracts
+
+org.springframework.cloud.contract.spec.Contract.make {
+ request { // (1)
+ method 'PUT' // (2)
+ url '/fraudcheck' // (3)
+ body([ // (4)
+ "client.id": $(regex('[0-9]{10}')),
+ loanAmount : 99999
+ ])
+ headers { // (5)
+ contentType('application/json')
+ }
+ }
+ response { // (6)
+ status OK() // (7)
+ body([ // (8)
+ fraudCheckStatus : "FRAUD",
+ "rejection.reason": "Amount too high"
+ ])
+ headers { // (9)
+ contentType('application/json')
+ }
+ }
+}
+
+/*
+From the Consumer perspective, when shooting a request in the integration test:
+
+(1) - If the consumer sends a request
+(2) - With the "PUT" method
+(3) - to the URL "/fraudcheck"
+(4) - with the JSON body that
+ * has a field `client.id` that matches a regular expression `[0-9]{10}`
+ * has a field `loanAmount` that is equal to `99999`
+(5) - with header `Content-Type` equal to `application/json`
+(6) - then the response will be sent with
+(7) - status equal `200`
+(8) - and JSON body equal to
+ { "fraudCheckStatus": "FRAUD", "rejectionReason": "Amount too high" }
+(9) - with header `Content-Type` equal to `application/json`
+
+From the Producer perspective, in the autogenerated producer-side test:
+
+(1) - A request will be sent to the producer
+(2) - With the "PUT" method
+(3) - to the URL "/fraudcheck"
+(4) - with the JSON body that
+ * has a field `client.id` that will have a generated value that matches a regular expression `[0-9]{10}`
+ * has a field `loanAmount` that is equal to `99999`
+(5) - with header `Content-Type` equal to `application/json`
+(6) - then the test will assert if the response has been sent with
+(7) - status equal `200`
+(8) - and JSON body equal to
+ { "fraudCheckStatus": "FRAUD", "rejectionReason": "Amount too high" }
+(9) - with header `Content-Type` matching `application/json.*`
+ */
diff --git a/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsNotFraud.groovy b/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsNotFraud.groovy
new file mode 100644
index 000000000..e84c69038
--- /dev/null
+++ b/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsNotFraud.groovy
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package contracts
+
+org.springframework.cloud.contract.spec.Contract.make {
+ request {
+ method 'PUT'
+ url '/fraudcheck'
+ body("""
+ {
+ "client.id":"${
+ value(consumer(regex('[0-9]{10}')), producer('1234567890'))
+ }",
+ "loanAmount":123.123
+ }
+ """
+ )
+ headers {
+ contentType("application/json")
+ }
+
+ }
+ response {
+ status OK()
+ body(
+ fraudCheckStatus: "OK",
+ "rejection.reason": $(consumer(null),
+ producer(execute('assertThatRejectionReasonIsNull($it)')))
+ )
+ headers {
+ contentType("application/json")
+ }
+ }
+
+}
diff --git a/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldReturnFraudStats.groovy b/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldReturnFraudStats.groovy
new file mode 100644
index 000000000..c84fe3ef5
--- /dev/null
+++ b/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldReturnFraudStats.groovy
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package contracts
+
+import org.springframework.cloud.contract.spec.Contract
+
+[
+ Contract.make {
+ request {
+ name "should count all frauds"
+ method GET()
+ url '/frauds'
+ }
+ response {
+ status OK()
+ body([
+ count: $(regex("[2-9][0-9][0-9]").asInteger())
+ ])
+ headers {
+ contentType("application/json")
+ }
+ }
+ },
+ // tag::metadata[]
+ Contract.make {
+ request {
+ method GET()
+ url '/drunks'
+ }
+ response {
+ status OK()
+ body([
+ count: 100
+ ])
+ headers {
+ contentType("application/json")
+ }
+ }
+ metadata([
+ wiremock: [
+ stubMapping: '''\
+ {
+ "response" : {
+ "fixedDelayMilliseconds": 2000
+ }
+ }
+ '''
+ ]
+ ])
+ }
+ // end::metadata[]
+]
diff --git a/standalone/dsl/http-server/src/test/resources/contracts/fraudname/shouldReturnACookie.groovy b/standalone/dsl/http-server/src/test/resources/contracts/fraudname/shouldReturnACookie.groovy
new file mode 100644
index 000000000..5861f0a1d
--- /dev/null
+++ b/standalone/dsl/http-server/src/test/resources/contracts/fraudname/shouldReturnACookie.groovy
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package contracts.fraudname
+
+org.springframework.cloud.contract.spec.Contract.make {
+ request {
+ method GET()
+ url '/frauds/name'
+ cookies {
+ cookie("name", "foo")
+ cookie(name2: "bar")
+ }
+ }
+ response {
+ status 200
+ body("foo bar")
+ }
+}
diff --git a/standalone/dsl/http-server/src/test/resources/contracts/fraudname/shouldReturnAFraudForTheName.groovy b/standalone/dsl/http-server/src/test/resources/contracts/fraudname/shouldReturnAFraudForTheName.groovy
new file mode 100644
index 000000000..d9b83251f
--- /dev/null
+++ b/standalone/dsl/http-server/src/test/resources/contracts/fraudname/shouldReturnAFraudForTheName.groovy
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package contracts.fraudname
+
+org.springframework.cloud.contract.spec.Contract.make {
+ // highest priority
+ priority(1)
+ request {
+ method PUT()
+ url '/frauds/name'
+ body([
+ name: "fraud"
+ ])
+ headers {
+ contentType("application/json")
+ }
+ }
+ response {
+ status OK()
+ body([
+ result: "Sorry ${fromRequest().body('$.name')} but you're a fraud"
+ ])
+ headers {
+ header(contentType(), "${fromRequest().header(contentType())}")
+ }
+ }
+}
diff --git a/standalone/dsl/http-server/src/test/resources/contracts/fraudname/shouldReturnNonFraudForTheName.groovy b/standalone/dsl/http-server/src/test/resources/contracts/fraudname/shouldReturnNonFraudForTheName.groovy
new file mode 100644
index 000000000..90467d12f
--- /dev/null
+++ b/standalone/dsl/http-server/src/test/resources/contracts/fraudname/shouldReturnNonFraudForTheName.groovy
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package contracts.fraudname
+
+org.springframework.cloud.contract.spec.Contract.make {
+ request {
+ method PUT()
+ url '/frauds/name'
+ body([
+ name: $(anyAlphaUnicode())
+ ])
+ headers {
+ contentType("application/json")
+ }
+ }
+ response {
+ status OK()
+ body([
+ result: "Don't worry ${fromRequest().body('$.name')} you're not a fraud"
+ ])
+ headers {
+ header(contentType(), "${fromRequest().header(contentType())}")
+ }
+ }
+}
diff --git a/standalone/dsl/http-server/src/test/resources/contracts/messaging/output.pdf b/standalone/dsl/http-server/src/test/resources/contracts/messaging/output.pdf
new file mode 100644
index 000000000..c3b233056
Binary files /dev/null and b/standalone/dsl/http-server/src/test/resources/contracts/messaging/output.pdf differ
diff --git a/standalone/dsl/http-server/src/test/resources/contracts/messaging/shouldProduceValidSensorData.groovy b/standalone/dsl/http-server/src/test/resources/contracts/messaging/shouldProduceValidSensorData.groovy
new file mode 100644
index 000000000..c9eb21945
--- /dev/null
+++ b/standalone/dsl/http-server/src/test/resources/contracts/messaging/shouldProduceValidSensorData.groovy
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package contracts
+
+org.springframework.cloud.contract.spec.Contract.make {
+ // Human readable description
+ description 'Should produce valid sensor data'
+ // Label by means of which the output message can be triggered
+ label 'sensor1'
+ // input to the contract
+ input {
+ // the contract will be triggered by a method
+ triggeredBy('createSensorData()')
+ }
+ // output message of the contract
+ outputMessage {
+ // destination to which the output message will be sent
+ sentTo 'sensor_data'
+ headers {
+ header('contentType': 'application/json')
+ }
+ // the body of the output message
+ body([
+ id : $(consumer(9), producer(regex("[0-9]+"))),
+ temperature: "123.45"
+ ])
+ }
+}
diff --git a/standalone/dsl/http-server/src/test/resources/contracts/messaging/shouldReturnOkWhenServiceIsHealthy.yml b/standalone/dsl/http-server/src/test/resources/contracts/messaging/shouldReturnOkWhenServiceIsHealthy.yml
new file mode 100644
index 000000000..6360b45b3
--- /dev/null
+++ b/standalone/dsl/http-server/src/test/resources/contracts/messaging/shouldReturnOkWhenServiceIsHealthy.yml
@@ -0,0 +1,6 @@
+description: Should return 200 for /foo
+request:
+ url: /foo
+ method: GET
+response:
+ status: 200
\ No newline at end of file
diff --git a/standalone/dsl/http-server/src/test/resources/contracts/messaging/shouldWorkWithInputOutputBinary.groovy b/standalone/dsl/http-server/src/test/resources/contracts/messaging/shouldWorkWithInputOutputBinary.groovy
new file mode 100644
index 000000000..decdfd910
--- /dev/null
+++ b/standalone/dsl/http-server/src/test/resources/contracts/messaging/shouldWorkWithInputOutputBinary.groovy
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package contracts
+
+import org.springframework.cloud.contract.spec.Contract
+
+Contract.make {
+ label("positive")
+ input {
+ triggeredBy("createBinaryPayload()")
+ }
+ outputMessage {
+ sentTo("bytes_output")
+ body(fileAsBytes("output.pdf"))
+ headers {
+ messagingContentType(applicationOctetStream())
+ }
+ }
+}
diff --git a/standalone/dsl/http-server/src/test/resources/contracts/multipart/shouldWorkForMultipartAsBytesWithContentType.groovy b/standalone/dsl/http-server/src/test/resources/contracts/multipart/shouldWorkForMultipartAsBytesWithContentType.groovy
new file mode 100644
index 000000000..1881dbb7e
--- /dev/null
+++ b/standalone/dsl/http-server/src/test/resources/contracts/multipart/shouldWorkForMultipartAsBytesWithContentType.groovy
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+import org.springframework.cloud.contract.spec.Contract
+
+Contract.make {
+ request {
+ method 'POST'
+ url '/tests'
+ multipart(
+ [
+ file1: named(
+ name: value(consumer(regex(nonEmpty())), producer('filename1')),
+ content: value(consumer(regex(nonEmpty())), producer('content1'))),
+ file2: named(
+ name: value(consumer(regex(nonEmpty())), producer('filename1')),
+ content: value(c(regex(nonEmpty())), producer('content2'))),
+ test : named(
+ name: value(consumer(regex(nonEmpty())), producer('filename1')),
+ content:
+ value(c(regex(nonEmpty())), producer(fileAsBytes("test.json"))),
+ contentType: value("application/json"))
+ ]
+ )
+
+ headers {
+ contentType('multipart/form-data')
+ }
+ }
+ response {
+ status 200
+ body([
+ status: 'ok'
+ ])
+ headers {
+ contentType('application/json')
+ }
+ }
+}
diff --git a/standalone/dsl/http-server/src/test/resources/contracts/multipart/shouldWorkForMultipartWithContentType.groovy b/standalone/dsl/http-server/src/test/resources/contracts/multipart/shouldWorkForMultipartWithContentType.groovy
new file mode 100644
index 000000000..7fa5e0581
--- /dev/null
+++ b/standalone/dsl/http-server/src/test/resources/contracts/multipart/shouldWorkForMultipartWithContentType.groovy
@@ -0,0 +1,35 @@
+import org.springframework.cloud.contract.spec.Contract
+
+Contract.make {
+ request {
+ method 'POST'
+ url '/tests'
+ multipart(
+ [
+ file1: named(
+ name: value(consumer(regex(nonEmpty())), producer('filename1')),
+ content: value(consumer(regex(nonEmpty())), producer('content1'))),
+ file2: named(
+ name: value(consumer(regex(nonEmpty())), producer('filename1')),
+ content: value(c(regex(nonEmpty())), producer('content2'))),
+ test : named(
+ name: value(consumer(regex(nonEmpty())), producer('filename1')),
+ content: value(c(regex(nonEmpty())), producer(file("test.json"))),
+ contentType: value("application/json"))
+ ]
+ )
+
+ headers {
+ contentType('multipart/form-data')
+ }
+ }
+ response {
+ status 200
+ body([
+ status: 'ok'
+ ])
+ headers {
+ contentType('application/json')
+ }
+ }
+}
diff --git a/standalone/dsl/http-server/src/test/resources/contracts/multipart/test.json b/standalone/dsl/http-server/src/test/resources/contracts/multipart/test.json
new file mode 100644
index 000000000..984c08fbd
--- /dev/null
+++ b/standalone/dsl/http-server/src/test/resources/contracts/multipart/test.json
@@ -0,0 +1,3 @@
+{
+ "status": "test"
+}
diff --git a/standalone/dsl/http-server/src/test/resources/contracts/test/MyHttpContract.java b/standalone/dsl/http-server/src/test/resources/contracts/test/MyHttpContract.java
new file mode 100644
index 000000000..3be89863a
--- /dev/null
+++ b/standalone/dsl/http-server/src/test/resources/contracts/test/MyHttpContract.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package test;
+
+import java.util.function.Supplier;
+
+import org.springframework.cloud.contract.spec.Contract;
+
+class MyHttpContract implements Supplier {
+ @Override
+ public Contract get() {
+ return Contract.make(c -> {
+ c.request(r -> {
+ r.method(r.GET());
+ r.url("/example");
+ });
+ c.response(r -> {
+ r.status(r.OK());
+ });
+ });
+ }
+}
diff --git a/standalone/dsl/http-server/src/test/resources/contracts/test/request.json b/standalone/dsl/http-server/src/test/resources/contracts/test/request.json
new file mode 100644
index 000000000..7cef5bbd0
--- /dev/null
+++ b/standalone/dsl/http-server/src/test/resources/contracts/test/request.json
@@ -0,0 +1 @@
+{ "hello" : "world" }
\ No newline at end of file
diff --git a/standalone/dsl/http-server/src/test/resources/contracts/yml/fraud/shouldMarkClientAsFraud.yml b/standalone/dsl/http-server/src/test/resources/contracts/yml/fraud/shouldMarkClientAsFraud.yml
new file mode 100644
index 000000000..eb0656569
--- /dev/null
+++ b/standalone/dsl/http-server/src/test/resources/contracts/yml/fraud/shouldMarkClientAsFraud.yml
@@ -0,0 +1,52 @@
+request: # (1)
+ method: PUT # (2)
+ url: /yamlfraudcheck # (3)
+ body: # (4)
+ "client.id": 1234567890
+ loanAmount: 99999
+ headers: # (5)
+ Content-Type: application/json
+ matchers:
+ body:
+ - path: $.['client.id'] # (6)
+ type: by_regex
+ value: "[0-9]{10}"
+response: # (7)
+ status: 200 # (8)
+ body: # (9)
+ fraudCheckStatus: "FRAUD"
+ "rejection.reason": "Amount too high"
+ headers: # (10)
+ Content-Type: application/json
+
+
+#From the Consumer perspective, when shooting a request in the integration test:
+#
+#(1) - If the consumer sends a request
+#(2) - With the "PUT" method
+#(3) - to the URL "/yamlfraudcheck"
+#(4) - with the JSON body that
+# * has a field `client.id`
+# * has a field `loanAmount` that is equal to `99999`
+#(5) - with header `Content-Type` equal to `application/json`
+#(6) - and a `client.id` json entry matches the regular expression `[0-9]{10}`
+#(7) - then the response will be sent with
+#(8) - status equal `200`
+#(9) - and JSON body equal to
+# { "fraudCheckStatus": "FRAUD", "rejectionReason": "Amount too high" }
+#(10) - with header `Content-Type` equal to `application/json`
+#
+#From the Producer perspective, in the autogenerated producer-side test:
+#
+#(1) - A request will be sent to the producer
+#(2) - With the "PUT" method
+#(3) - to the URL "/yamlfraudcheck"
+#(4) - with the JSON body that
+# * has a field `client.id` `1234567890`
+# * has a field `loanAmount` that is equal to `99999`
+#(5) - with header `Content-Type` equal to `application/json`
+#(7) - then the test will assert if the response has been sent with
+#(8) - status equal `200`
+#(9) - and JSON body equal to
+# { "fraudCheckStatus": "FRAUD", "rejectionReason": "Amount too high" }
+#(10) - with header `Content-Type` equal to `application/json`
\ No newline at end of file
diff --git a/standalone/dsl/http-server/src/test/resources/contracts/yml/fraud/shouldMarkClientAsNotFraud.yaml b/standalone/dsl/http-server/src/test/resources/contracts/yml/fraud/shouldMarkClientAsNotFraud.yaml
new file mode 100644
index 000000000..550322aa8
--- /dev/null
+++ b/standalone/dsl/http-server/src/test/resources/contracts/yml/fraud/shouldMarkClientAsNotFraud.yaml
@@ -0,0 +1,25 @@
+request:
+ method: PUT
+ url: /yamlfraudcheck
+ body:
+ "client.id": 1234567890
+ loanAmount: 123.123
+ headers:
+ Content-Type: application/json
+ matchers:
+ body:
+ - path: $.['client.id']
+ type: by_regex
+ value: "[0-9]{10}"
+response:
+ status: 200
+ body:
+ fraudCheckStatus: "OK"
+ "rejection.reason": null
+ headers:
+ Content-Type: application/json
+ matchers:
+ body:
+ - path: $.['rejection.reason']
+ type: by_command
+ value: assertThatRejectionReasonIsNull($it)
diff --git a/standalone/dsl/http-server/src/test/resources/contracts/yml/fraud/shouldReturnFraudStats.yml b/standalone/dsl/http-server/src/test/resources/contracts/yml/fraud/shouldReturnFraudStats.yml
new file mode 100644
index 000000000..e14f824f0
--- /dev/null
+++ b/standalone/dsl/http-server/src/test/resources/contracts/yml/fraud/shouldReturnFraudStats.yml
@@ -0,0 +1,31 @@
+---
+# tag::metadata[]
+name: "should count all frauds"
+request:
+ method: GET
+ url: /yamlfrauds
+response:
+ status: 200
+ body:
+ count: 200
+ headers:
+ Content-Type: application/json
+metadata:
+ wiremock:
+ stubMapping: >
+ {
+ "response" : {
+ "fixedDelayMilliseconds": 2000
+ }
+ }
+# end::metadata[]
+---
+request:
+ method: GET
+ url: /yamldrunks
+response:
+ status: 200
+ body:
+ count: 100
+ headers:
+ Content-Type: application/json
\ No newline at end of file
diff --git a/standalone/dsl/http-server/src/test/resources/contracts/yml/fraudname/shouldReturnAFraudForTheName.yml b/standalone/dsl/http-server/src/test/resources/contracts/yml/fraudname/shouldReturnAFraudForTheName.yml
new file mode 100644
index 000000000..5e06866b8
--- /dev/null
+++ b/standalone/dsl/http-server/src/test/resources/contracts/yml/fraudname/shouldReturnAFraudForTheName.yml
@@ -0,0 +1,15 @@
+# highest priority
+priority: 1
+request:
+ method: PUT
+ url: /yamlfrauds/name
+ body:
+ name: "fraud"
+ headers:
+ Content-Type: application/json
+response:
+ status: 200
+ body:
+ result: "Sorry {{{ jsonpath this '$.name' }}} but you're a fraud"
+ headers:
+ Content-Type: "{{{ request.headers.Content-Type.0 }}}"
\ No newline at end of file
diff --git a/standalone/dsl/http-server/src/test/resources/contracts/yml/fraudname/shouldReturnNonFraudForTheName.yml b/standalone/dsl/http-server/src/test/resources/contracts/yml/fraudname/shouldReturnNonFraudForTheName.yml
new file mode 100644
index 000000000..c0a8e14a0
--- /dev/null
+++ b/standalone/dsl/http-server/src/test/resources/contracts/yml/fraudname/shouldReturnNonFraudForTheName.yml
@@ -0,0 +1,18 @@
+request:
+ method: PUT
+ url: /yamlfrauds/name
+ body:
+ name: "non fraud"
+ headers:
+ Content-Type: application/json
+ matchers:
+ body:
+ - path: $.name
+ type: by_regex
+ predefined: only_alpha_unicode
+response:
+ status: 200
+ body:
+ result: "Don't worry {{{ jsonpath this '$.name' }}} you're not a fraud"
+ headers:
+ Content-Type: "{{{ request.headers.Content-Type.0 }}}"
\ No newline at end of file
diff --git a/standalone/restdocs/http-client/.gitignore b/standalone/restdocs/http-client/.gitignore
new file mode 100644
index 000000000..a275b7b86
--- /dev/null
+++ b/standalone/restdocs/http-client/.gitignore
@@ -0,0 +1,7 @@
+
+target/
+
+.gradle
+build/
+
+/.apt_generated/
diff --git a/standalone/restdocs/http-client/.mvn/jvm.config b/standalone/restdocs/http-client/.mvn/jvm.config
new file mode 100644
index 000000000..0e7dabeff
--- /dev/null
+++ b/standalone/restdocs/http-client/.mvn/jvm.config
@@ -0,0 +1 @@
+-Xmx1024m -XX:CICompilerCount=1 -XX:TieredStopAtLevel=1 -Djava.security.egd=file:/dev/./urandom
\ No newline at end of file
diff --git a/standalone/restdocs/http-client/.mvn/maven.config b/standalone/restdocs/http-client/.mvn/maven.config
new file mode 100644
index 000000000..a68299056
--- /dev/null
+++ b/standalone/restdocs/http-client/.mvn/maven.config
@@ -0,0 +1 @@
+-P spring
diff --git a/standalone/restdocs/http-client/.mvn/wrapper/MavenWrapperDownloader.java b/standalone/restdocs/http-client/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 000000000..b901097f2
--- /dev/null
+++ b/standalone/restdocs/http-client/.mvn/wrapper/MavenWrapperDownloader.java
@@ -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();
+ }
+
+}
diff --git a/standalone/restdocs/http-client/.mvn/wrapper/maven-wrapper.jar b/standalone/restdocs/http-client/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 000000000..c1dd12f17
Binary files /dev/null and b/standalone/restdocs/http-client/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/standalone/restdocs/http-client/.mvn/wrapper/maven-wrapper.properties b/standalone/restdocs/http-client/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 000000000..015dfe682
--- /dev/null
+++ b/standalone/restdocs/http-client/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,18 @@
+# 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.
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.3/apache-maven-3.8.3-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar
diff --git a/standalone/restdocs/http-client/README.adoc b/standalone/restdocs/http-client/README.adoc
new file mode 100644
index 000000000..cdcb0e4a5
--- /dev/null
+++ b/standalone/restdocs/http-client/README.adoc
@@ -0,0 +1,26 @@
+= Http Client
+
+== Prerequisites
+
+First you have to publish to Maven Local the stubs of the *http-server* module
+
+== How to run it?
+
+Run
+
+[source=groovy]
+--------
+./gradlew clean build
+--------
+
+or
+
+--------
+./mvnw clean package
+--------
+
+To
+
+- build the app
+- use spring-cloud-contract-stub-runner-spring[Stub Runner Spring] to download the stub of `Http Server`
+- run the tests against stubbed server
\ No newline at end of file
diff --git a/standalone/restdocs/http-client/build.gradle b/standalone/restdocs/http-client/build.gradle
new file mode 100644
index 000000000..9e4c68371
--- /dev/null
+++ b/standalone/restdocs/http-client/build.gradle
@@ -0,0 +1,75 @@
+buildscript {
+ repositories {
+ mavenCentral()
+ mavenLocal()
+ maven { url "https://repo.spring.io/snapshot" }
+ maven { url "https://repo.spring.io/milestone" }
+ }
+ dependencies {
+ classpath "org.springframework.boot:spring-boot-gradle-plugin:${findProperty('bootVersion') ?: bootVersion}"
+ }
+}
+
+group = 'com.example'
+version = '0.0.1'
+
+repositories {
+ mavenCentral()
+ mavenLocal()
+ maven { url "https://repo.spring.io/snapshot" }
+ maven { url "https://repo.spring.io/milestone" }
+}
+
+apply plugin: 'groovy'
+apply plugin: 'org.springframework.boot'
+apply plugin: 'io.spring.dependency-management'
+apply plugin: 'maven-publish'
+
+dependencyManagement {
+ imports {
+ mavenBom "org.springframework.cloud:spring-cloud-contract-dependencies:$verifierVersion"
+ mavenBom "org.springframework.cloud:spring-cloud-stream-dependencies:$springCloudStreamVersion"
+ }
+}
+
+dependencies {
+ implementation("org.springframework.boot:spring-boot-starter-web")
+ implementation("org.springframework.boot:spring-boot-starter-actuator")
+ implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-xml")
+
+ testImplementation 'org.springframework.cloud:spring-cloud-contract-wiremock'
+ testImplementation 'org.springframework.cloud:spring-cloud-starter-contract-stub-runner'
+ testImplementation('org.springframework.boot:spring-boot-starter-test') {
+ exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
+ }
+ testImplementation "com.example:http-server-restdocs:0.0.1:stubs"
+}
+
+test {
+ useJUnitPlatform()
+ systemProperty 'spring.profiles.active', 'gradle'
+ testLogging {
+ exceptionFormat = 'full'
+ }
+ afterSuite { desc, result ->
+ if (!desc.parent) {
+ println "Results: (${result.testCount} tests, ${result.successfulTestCount} successes, ${result.failedTestCount} failures, ${result.skippedTestCount} skipped)"
+ if (result.testCount == 0) {
+ throw new IllegalStateException("No tests were found. Failing the build")
+ }
+ }
+ }
+}
+
+task resolveDependencies {
+ doLast {
+ project.rootProject.allprojects.each { subProject ->
+ subProject.buildscript.configurations.each { configuration ->
+ configuration.resolve()
+ }
+ subProject.configurations.each { configuration ->
+ configuration.resolve()
+ }
+ }
+ }
+}
diff --git a/standalone/restdocs/http-client/gradle.properties b/standalone/restdocs/http-client/gradle.properties
new file mode 100644
index 000000000..7ae982c8f
--- /dev/null
+++ b/standalone/restdocs/http-client/gradle.properties
@@ -0,0 +1,4 @@
+org.gradle.daemon=false
+verifierVersion=4.1.5-SNAPSHOT
+springCloudStreamVersion=4.1.4-SNAPSHOT
+bootVersion=3.2.7
\ No newline at end of file
diff --git a/standalone/restdocs/http-client/gradle/wrapper/gradle-wrapper.jar b/standalone/restdocs/http-client/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 000000000..7f93135c4
Binary files /dev/null and b/standalone/restdocs/http-client/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/standalone/restdocs/http-client/gradle/wrapper/gradle-wrapper.properties b/standalone/restdocs/http-client/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 000000000..ac72c34e8
--- /dev/null
+++ b/standalone/restdocs/http-client/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,7 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
+networkTimeout=10000
+validateDistributionUrl=true
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/standalone/restdocs/http-client/gradlew b/standalone/restdocs/http-client/gradlew
new file mode 100755
index 000000000..0adc8e1a5
--- /dev/null
+++ b/standalone/restdocs/http-client/gradlew
@@ -0,0 +1,249 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original 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 POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
+done
+
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+ echo "$*"
+} >&2
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+} >&2
+
+# 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 ;; #(
+ MSYS* | 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
+ if ! command -v java >/dev/null 2>&1
+ then
+ 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
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC3045
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC3045
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+
+# 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"'
+
+# Collect all arguments for the java command;
+# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+# shell script including quotes and variable substitutions, so put them in
+# double quotes to make sure that they get re-expanded; and
+# * put everything else in single quotes, so that it's not re-expanded.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+ die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/standalone/restdocs/http-client/gradlew.bat b/standalone/restdocs/http-client/gradlew.bat
new file mode 100644
index 000000000..93e3f59f1
--- /dev/null
+++ b/standalone/restdocs/http-client/gradlew.bat
@@ -0,0 +1,92 @@
+@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=.
+@rem This is normally unused
+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% equ 0 goto execute
+
+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 execute
+
+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
+
+: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 %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if %ERRORLEVEL% equ 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!
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/standalone/restdocs/http-client/mvnw b/standalone/restdocs/http-client/mvnw
new file mode 100755
index 000000000..5643201c7
--- /dev/null
+++ b/standalone/restdocs/http-client/mvnw
@@ -0,0 +1,316 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# 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 /usr/local/etc/mavenrc ] ; then
+ . /usr/local/etc/mavenrc
+ fi
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ export JAVA_HOME="`/usr/libexec/java_home`"
+ else
+ export JAVA_HOME="/Library/Java/Home"
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=`java-config --jre-home`
+ fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+ ## resolve links - $0 may be a link to maven's home
+ PRG="$0"
+
+ # need this for relative symlinks
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG="`dirname "$PRG"`/$link"
+ fi
+ done
+
+ saveddir=`pwd`
+
+ M2_HOME=`dirname "$PRG"`/..
+
+ # make it fully qualified
+ M2_HOME=`cd "$M2_HOME" && pwd`
+
+ cd "$saveddir"
+ # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --unix "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME="`(cd "$M2_HOME"; pwd)`"
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="`which javac`"
+ if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=`which readlink`
+ if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+ if $darwin ; then
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+ else
+ javaExecutable="`readlink -f \"$javaExecutable\"`"
+ fi
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="`\\unset -f command; \\command -v java`"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=`cd "$wdir/.."; pwd`
+ fi
+ # end of workaround
+ done
+ echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ echo "$(tr -s '\n' ' ' < "$1")"
+ fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found .mvn/wrapper/maven-wrapper.jar"
+ fi
+else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+ fi
+ if [ -n "$MVNW_REPOURL" ]; then
+ jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+ else
+ jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+ fi
+ while IFS="=" read key value; do
+ case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
+ esac
+ done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Downloading from: $jarUrl"
+ fi
+ wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+ if $cygwin; then
+ wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
+ fi
+
+ if command -v wget > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found wget ... using wget"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ else
+ wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ fi
+ elif command -v curl > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found curl ... using curl"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl -o "$wrapperJarPath" "$jarUrl" -f
+ else
+ curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
+ fi
+
+ else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Falling back to using Java to download"
+ fi
+ javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaClass=`cygpath --path --windows "$javaClass"`
+ fi
+ if [ -e "$javaClass" ]; then
+ if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Compiling MavenWrapperDownloader.java ..."
+ fi
+ # Compiling the Java class
+ ("$JAVA_HOME/bin/javac" "$javaClass")
+ fi
+ if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ # Running the downloader
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Running MavenWrapperDownloader.java ..."
+ fi
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+if [ "$MVNW_VERBOSE" = true ]; then
+ echo $MAVEN_PROJECTBASEDIR
+fi
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --path --windows "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ $MAVEN_DEBUG_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.home=${M2_HOME}" \
+ "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/standalone/restdocs/http-client/mvnw.cmd b/standalone/restdocs/http-client/mvnw.cmd
new file mode 100644
index 000000000..8a15b7f31
--- /dev/null
+++ b/standalone/restdocs/http-client/mvnw.cmd
@@ -0,0 +1,188 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM 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 "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
+if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Found %WRAPPER_JAR%
+ )
+) else (
+ if not "%MVNW_REPOURL%" == "" (
+ SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+ )
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %DOWNLOAD_URL%
+ )
+
+ powershell -Command "&{"^
+ "$webclient = new-object System.Net.WebClient;"^
+ "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+ "}"^
+ "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
+ "}"
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Finished downloading %WRAPPER_JAR%
+ )
+)
+@REM End of extension
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% ^
+ %JVM_CONFIG_MAVEN_PROPS% ^
+ %MAVEN_OPTS% ^
+ %MAVEN_DEBUG_OPTS% ^
+ -classpath %WRAPPER_JAR% ^
+ "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
+ %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
+if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%"=="on" pause
+
+if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
+
+cmd /C exit /B %ERROR_CODE%
diff --git a/standalone/restdocs/http-client/pom.xml b/standalone/restdocs/http-client/pom.xml
new file mode 100644
index 000000000..e8d4ac5f3
--- /dev/null
+++ b/standalone/restdocs/http-client/pom.xml
@@ -0,0 +1,259 @@
+
+
+
+
+ 4.0.0
+
+ com.example
+ http-client-restdocs
+ 0.0.1
+
+ Spring Cloud Contract RestDocs Http Client Sample
+ Spring Cloud Contract RestDocs Http Client Sample
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.2.7
+
+
+
+
+ UTF-8
+ 17
+ 4.1.5-SNAPSHOT
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+ com.fasterxml.jackson.dataformat
+ jackson-dataformat-xml
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.junit.vintage
+ junit-vintage-engine
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-contract-wiremock
+ test
+
+
+ org.springframework.cloud
+ spring-cloud-contract-stub-runner
+ test
+
+
+
+ org.apache.httpcomponents.client5
+ httpclient5
+
+
+ org.slf4j
+ slf4j-api
+
+
+ compile
+
+
+
+ com.example
+ http-server-restdocs
+ stubs
+ 0.0.1
+ test
+
+
+ *
+ *
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-contract-dependencies
+ ${spring-cloud-contract.version}
+ pom
+ import
+
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ maven-deploy-plugin
+
+ true
+
+
+
+ maven-surefire-plugin
+
+ true
+
+
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
+
+ integration
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 1.6.0
+
+
+ gradle
+ test
+
+ ./gradlew
+
+ clean
+ build
+ publishToMavenLocal
+
+ -x
+ test
+
+ -PverifierVersion=${spring-cloud-contract.version}
+
+
+
+
+ exec
+
+
+
+
+
+
+
+
+ windows
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 1.6.0
+
+
+ gradle
+ test
+
+ ./gradlew
+
+ clean
+ build
+ publishToMavenLocal
+
+ -x
+ test
+
+ -PverifierVersion=${spring-cloud-contract.version}
+
+
+
+
+ exec
+
+
+
+
+
+
+
+
+
+
diff --git a/standalone/restdocs/http-client/settings.gradle b/standalone/restdocs/http-client/settings.gradle
new file mode 100644
index 000000000..877b12b9a
--- /dev/null
+++ b/standalone/restdocs/http-client/settings.gradle
@@ -0,0 +1 @@
+rootProject.name = 'http-client-restdocs-gradle'
diff --git a/standalone/restdocs/http-client/src/main/java/com/example/loan/Application.java b/standalone/restdocs/http-client/src/main/java/com/example/loan/Application.java
new file mode 100644
index 000000000..63645c66f
--- /dev/null
+++ b/standalone/restdocs/http-client/src/main/java/com/example/loan/Application.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.loan;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+
+@SpringBootApplication
+@EnableConfigurationProperties(ServiceConfiguration.class)
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+}
diff --git a/standalone/restdocs/http-client/src/main/java/com/example/loan/LoanApplicationService.java b/standalone/restdocs/http-client/src/main/java/com/example/loan/LoanApplicationService.java
new file mode 100644
index 000000000..0e2942296
--- /dev/null
+++ b/standalone/restdocs/http-client/src/main/java/com/example/loan/LoanApplicationService.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.loan;
+
+import com.example.loan.model.FraudCheckStatus;
+import com.example.loan.model.FraudServiceRequest;
+import com.example.loan.model.FraudServiceResponse;
+import com.example.loan.model.LoanApplication;
+import com.example.loan.model.LoanApplicationResult;
+import com.example.loan.model.LoanApplicationStatus;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestTemplate;
+
+@Service
+public class LoanApplicationService {
+
+ private static final String FRAUD_SERVICE_JSON_VERSION_1 = "application/vnd.fraud.v1+json";
+
+ private final RestTemplate restTemplate;
+
+ private final ServiceConfiguration serviceConfiguration;
+
+ public LoanApplicationService(ServiceConfiguration serviceConfiguration) {
+ this.restTemplate = new RestTemplate();
+ // tag::custom_request_factory[]
+ this.restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory());
+ // end::custom_request_factory[]
+ this.serviceConfiguration = serviceConfiguration;
+ }
+
+ public LoanApplicationResult loanApplication(LoanApplication loanApplication) {
+ FraudServiceRequest request = new FraudServiceRequest(loanApplication);
+
+ FraudServiceResponse response = sendRequestToFraudDetectionService(request);
+
+ return buildResponseFromFraudResult(response);
+ }
+
+ private FraudServiceResponse sendRequestToFraudDetectionService(
+ FraudServiceRequest request) {
+ HttpHeaders httpHeaders = new HttpHeaders();
+ httpHeaders.add(HttpHeaders.CONTENT_TYPE, FRAUD_SERVICE_JSON_VERSION_1);
+
+ // tag::client_call_server[]
+ ResponseEntity response = restTemplate.exchange(
+ "http://localhost:" + getPort() + "/fraudcheck", HttpMethod.PUT,
+ new HttpEntity<>(request, httpHeaders), FraudServiceResponse.class);
+ // end::client_call_server[]
+
+ return response.getBody();
+ }
+
+ private LoanApplicationResult buildResponseFromFraudResult(
+ FraudServiceResponse response) {
+ LoanApplicationStatus applicationStatus = null;
+ if (FraudCheckStatus.OK == response.getFraudCheckStatus()) {
+ applicationStatus = LoanApplicationStatus.LOAN_APPLIED;
+ }
+ else if (FraudCheckStatus.FRAUD == response.getFraudCheckStatus()) {
+ applicationStatus = LoanApplicationStatus.LOAN_APPLICATION_REJECTED;
+ }
+
+ return new LoanApplicationResult(applicationStatus,
+ response.getRejectionReason());
+ }
+
+ public int getPort() {
+ return this.serviceConfiguration.getPort();
+ }
+
+ public void setPort(int port) {
+ this.serviceConfiguration.setPort(port);
+ }
+
+}
+
+@ConfigurationProperties("service")
+class ServiceConfiguration {
+
+ private int port = 8080;
+
+ public int getPort() {
+ return port;
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
+}
diff --git a/standalone/restdocs/http-client/src/main/java/com/example/loan/model/Client.java b/standalone/restdocs/http-client/src/main/java/com/example/loan/model/Client.java
new file mode 100644
index 000000000..8fac47b2f
--- /dev/null
+++ b/standalone/restdocs/http-client/src/main/java/com/example/loan/model/Client.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.loan.model;
+
+public class Client {
+
+ private String pesel;
+
+ public Client() {
+ }
+
+ public Client(String pesel) {
+ this.pesel = pesel;
+ }
+
+ public String getPesel() {
+ return pesel;
+ }
+
+ public void setPesel(String pesel) {
+ this.pesel = pesel;
+ }
+
+}
diff --git a/standalone/restdocs/http-client/src/main/java/com/example/loan/model/FraudCheckStatus.java b/standalone/restdocs/http-client/src/main/java/com/example/loan/model/FraudCheckStatus.java
new file mode 100644
index 000000000..01f296911
--- /dev/null
+++ b/standalone/restdocs/http-client/src/main/java/com/example/loan/model/FraudCheckStatus.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.loan.model;
+
+public enum FraudCheckStatus {
+
+ OK, FRAUD
+
+}
diff --git a/standalone/restdocs/http-client/src/main/java/com/example/loan/model/FraudServiceRequest.java b/standalone/restdocs/http-client/src/main/java/com/example/loan/model/FraudServiceRequest.java
new file mode 100644
index 000000000..379d32e34
--- /dev/null
+++ b/standalone/restdocs/http-client/src/main/java/com/example/loan/model/FraudServiceRequest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.loan.model;
+
+import java.math.BigDecimal;
+
+public class FraudServiceRequest {
+
+ private String clientId;
+
+ private BigDecimal loanAmount;
+
+ public FraudServiceRequest() {
+ }
+
+ public FraudServiceRequest(LoanApplication loanApplication) {
+ this.clientId = loanApplication.getClient().getPesel();
+ this.loanAmount = loanApplication.getAmount();
+ }
+
+ public String getClientId() {
+ return clientId;
+ }
+
+ public void setClientId(String clientId) {
+ this.clientId = clientId;
+ }
+
+ public BigDecimal getLoanAmount() {
+ return loanAmount;
+ }
+
+ public void setLoanAmount(BigDecimal loanAmount) {
+ this.loanAmount = loanAmount;
+ }
+
+}
diff --git a/standalone/restdocs/http-client/src/main/java/com/example/loan/model/FraudServiceResponse.java b/standalone/restdocs/http-client/src/main/java/com/example/loan/model/FraudServiceResponse.java
new file mode 100644
index 000000000..c7d3aca9f
--- /dev/null
+++ b/standalone/restdocs/http-client/src/main/java/com/example/loan/model/FraudServiceResponse.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.loan.model;
+
+public class FraudServiceResponse {
+
+ private FraudCheckStatus fraudCheckStatus;
+
+ private String rejectionReason;
+
+ public FraudServiceResponse() {
+ }
+
+ public FraudCheckStatus getFraudCheckStatus() {
+ return fraudCheckStatus;
+ }
+
+ public void setFraudCheckStatus(FraudCheckStatus fraudCheckStatus) {
+ this.fraudCheckStatus = fraudCheckStatus;
+ }
+
+ public String getRejectionReason() {
+ return rejectionReason;
+ }
+
+ public void setRejectionReason(String rejectionReason) {
+ this.rejectionReason = rejectionReason;
+ }
+
+}
diff --git a/standalone/restdocs/http-client/src/main/java/com/example/loan/model/LoanApplication.java b/standalone/restdocs/http-client/src/main/java/com/example/loan/model/LoanApplication.java
new file mode 100644
index 000000000..e2f4aa251
--- /dev/null
+++ b/standalone/restdocs/http-client/src/main/java/com/example/loan/model/LoanApplication.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.loan.model;
+
+import java.math.BigDecimal;
+
+public class LoanApplication {
+
+ private Client client;
+
+ private BigDecimal amount;
+
+ private String loanApplicationId;
+
+ public LoanApplication() {
+ }
+
+ public LoanApplication(Client client, double amount) {
+ this.client = client;
+ this.amount = BigDecimal.valueOf(amount);
+ }
+
+ public Client getClient() {
+ return client;
+ }
+
+ public void setClient(Client client) {
+ this.client = client;
+ }
+
+ public BigDecimal getAmount() {
+ return amount;
+ }
+
+ public void setAmount(BigDecimal amount) {
+ this.amount = amount;
+ }
+
+ public String getLoanApplicationId() {
+ return loanApplicationId;
+ }
+
+ public void setLoanApplicationId(String loanApplicationId) {
+ this.loanApplicationId = loanApplicationId;
+ }
+
+}
diff --git a/standalone/restdocs/http-client/src/main/java/com/example/loan/model/LoanApplicationResult.java b/standalone/restdocs/http-client/src/main/java/com/example/loan/model/LoanApplicationResult.java
new file mode 100644
index 000000000..73501084b
--- /dev/null
+++ b/standalone/restdocs/http-client/src/main/java/com/example/loan/model/LoanApplicationResult.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.loan.model;
+
+public class LoanApplicationResult {
+
+ private LoanApplicationStatus loanApplicationStatus;
+
+ private String rejectionReason;
+
+ public LoanApplicationResult() {
+ }
+
+ public LoanApplicationResult(LoanApplicationStatus loanApplicationStatus,
+ String rejectionReason) {
+ this.loanApplicationStatus = loanApplicationStatus;
+ this.rejectionReason = rejectionReason;
+ }
+
+ public LoanApplicationStatus getLoanApplicationStatus() {
+ return loanApplicationStatus;
+ }
+
+ public void setLoanApplicationStatus(LoanApplicationStatus loanApplicationStatus) {
+ this.loanApplicationStatus = loanApplicationStatus;
+ }
+
+ public String getRejectionReason() {
+ return rejectionReason;
+ }
+
+ public void setRejectionReason(String rejectionReason) {
+ this.rejectionReason = rejectionReason;
+ }
+
+}
diff --git a/standalone/restdocs/http-client/src/main/java/com/example/loan/model/LoanApplicationStatus.java b/standalone/restdocs/http-client/src/main/java/com/example/loan/model/LoanApplicationStatus.java
new file mode 100644
index 000000000..5afde21af
--- /dev/null
+++ b/standalone/restdocs/http-client/src/main/java/com/example/loan/model/LoanApplicationStatus.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.loan.model;
+
+public enum LoanApplicationStatus {
+
+ LOAN_APPLIED, LOAN_APPLICATION_REJECTED
+
+}
diff --git a/standalone/restdocs/http-client/src/main/resources/application.yml b/standalone/restdocs/http-client/src/main/resources/application.yml
new file mode 100644
index 000000000..456f83e82
--- /dev/null
+++ b/standalone/restdocs/http-client/src/main/resources/application.yml
@@ -0,0 +1,6 @@
+server.port: 8097
+logging:
+ level:
+ org.springframework.cloud.contract.wiremock: debug
+ org.springframework.web.client: debug
+ com.github.tomakehurst.wiremock: trace
\ No newline at end of file
diff --git a/standalone/restdocs/http-client/src/test/java/com/example/loan/LoanApplicationServiceTests.java b/standalone/restdocs/http-client/src/test/java/com/example/loan/LoanApplicationServiceTests.java
new file mode 100644
index 000000000..bc2cdc677
--- /dev/null
+++ b/standalone/restdocs/http-client/src/test/java/com/example/loan/LoanApplicationServiceTests.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.loan;
+
+import java.nio.charset.Charset;
+
+import com.example.loan.model.Client;
+import com.example.loan.model.LoanApplication;
+import com.example.loan.model.LoanApplicationResult;
+import com.example.loan.model.LoanApplicationStatus;
+import com.github.tomakehurst.wiremock.WireMockServer;
+import com.github.tomakehurst.wiremock.stubbing.StubMapping;
+import org.junit.jupiter.api.Test;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock;
+import org.springframework.core.io.Resource;
+
+import org.springframework.util.StreamUtils;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+
+@SpringBootTest(properties = "service.port=${wiremock.server.port}")
+@AutoConfigureWireMock(port = 0)
+class LoanApplicationServiceTests {
+
+ @Autowired
+ private LoanApplicationService service;
+
+ @Value("classpath:META-INF/com.example/http-server-restdocs/0.0.1/mappings/standalone/shouldMarkClientAsFraud.json")
+ private Resource markClientAsFraud;
+
+ @Value("classpath:META-INF/com.example/http-server-restdocs/0.0.1/mappings/webapp/shouldMarkClientAsNotFraud.json")
+ private Resource markClientAsNotFraud;
+
+ @Autowired
+ private WireMockServer server;
+
+ @Test
+ void shouldSuccessfullyApplyForLoan() throws Exception {
+ server.addStubMapping(StubMapping.buildFrom(StreamUtils.copyToString(
+ markClientAsNotFraud.getInputStream(), Charset.forName("UTF-8"))));
+ // given:
+ LoanApplication application = new LoanApplication(new Client("1234567890"),
+ 123.123);
+ // when:
+ LoanApplicationResult loanApplication = service.loanApplication(application);
+ // then:
+ assertThat(loanApplication.getLoanApplicationStatus())
+ .isEqualTo(LoanApplicationStatus.LOAN_APPLIED);
+ assertThat(loanApplication.getRejectionReason()).isNull();
+ }
+
+ @Test
+ void shouldBeRejectedDueToAbnormalLoanAmount() throws Exception {
+ server.addStubMapping(StubMapping.buildFrom(StreamUtils.copyToString(
+ markClientAsFraud.getInputStream(), Charset.forName("UTF-8"))));
+ // given:
+ LoanApplication application = new LoanApplication(new Client("1234567890"),
+ 99999);
+ // when:
+ LoanApplicationResult loanApplication = service.loanApplication(application);
+ // then:
+ assertThat(loanApplication.getLoanApplicationStatus())
+ .isEqualTo(LoanApplicationStatus.LOAN_APPLICATION_REJECTED);
+ assertThat(loanApplication.getRejectionReason()).isEqualTo("Amount too high");
+ }
+
+}
diff --git a/standalone/restdocs/http-client/src/test/java/com/example/loan/LoanApplicationServiceusingStubRunnerTests.java b/standalone/restdocs/http-client/src/test/java/com/example/loan/LoanApplicationServiceusingStubRunnerTests.java
new file mode 100644
index 000000000..7398319c0
--- /dev/null
+++ b/standalone/restdocs/http-client/src/test/java/com/example/loan/LoanApplicationServiceusingStubRunnerTests.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.loan;
+
+import com.example.loan.model.Client;
+import com.example.loan.model.LoanApplication;
+import com.example.loan.model.LoanApplicationResult;
+import com.example.loan.model.LoanApplicationStatus;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner;
+
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+
+@SpringBootTest
+@AutoConfigureStubRunner(ids = "com.example:http-server-restdocs")
+class LoanApplicationServiceusingStubRunnerTests {
+
+ @Autowired
+ LoanApplicationService service;
+
+ @Value("${stubrunner.runningstubs.http-server-restdocs.port}")
+ int port;
+
+ @BeforeEach
+ public void setup() {
+ this.service.setPort(this.port);
+ }
+
+ @Test
+ void shouldSuccessfullyApplyForLoan() throws Exception {
+ // given
+ LoanApplication application = new LoanApplication(new Client("1234567890"),
+ 123.123);
+ // when:
+ LoanApplicationResult loanApplication = service.loanApplication(application);
+ // then:
+ assertThat(loanApplication.getLoanApplicationStatus())
+ .isEqualTo(LoanApplicationStatus.LOAN_APPLIED);
+ assertThat(loanApplication.getRejectionReason()).isNull();
+ }
+
+ @Test
+ void shouldBeRejectedDueToAbnormalLoanAmount() throws Exception {
+ // given:
+ LoanApplication application = new LoanApplication(new Client("1234567890"),
+ 99999);
+ // when:
+ LoanApplicationResult loanApplication = service.loanApplication(application);
+ // then:
+ assertThat(loanApplication.getLoanApplicationStatus())
+ .isEqualTo(LoanApplicationStatus.LOAN_APPLICATION_REJECTED);
+ assertThat(loanApplication.getRejectionReason()).isEqualTo("Amount too high");
+ }
+
+}
diff --git a/standalone/restdocs/http-client/src/test/java/com/example/loan/XmlServiceTests.java b/standalone/restdocs/http-client/src/test/java/com/example/loan/XmlServiceTests.java
new file mode 100644
index 000000000..cf57d978f
--- /dev/null
+++ b/standalone/restdocs/http-client/src/test/java/com/example/loan/XmlServiceTests.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.loan;
+
+import java.net.URI;
+import java.nio.charset.Charset;
+
+import com.github.tomakehurst.wiremock.WireMockServer;
+import com.github.tomakehurst.wiremock.stubbing.StubMapping;
+import org.assertj.core.api.BDDAssertions;
+import org.junit.jupiter.api.Test;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock;
+import org.springframework.core.io.Resource;
+import org.springframework.http.MediaType;
+import org.springframework.http.RequestEntity;
+import org.springframework.http.ResponseEntity;
+
+import org.springframework.util.StreamUtils;
+import org.springframework.web.client.RestTemplate;
+
+
+@SpringBootTest(properties = "service.port=${wiremock.server.port}")
+@AutoConfigureWireMock(port = 0)
+class XmlServiceTests {
+
+ @Value("classpath:META-INF/com.example/http-server-restdocs/0.0.1/mappings/should_return_empty_content.json")
+ private Resource empty;
+
+ @Value("classpath:META-INF/com.example/http-server-restdocs/0.0.1/mappings/should_return_full_content.json")
+ private Resource full;
+
+ @Autowired
+ private WireMockServer server;
+
+ @Test
+ void shouldSuccessfullyReturnFullResponse() throws Exception {
+ server.addStubMapping(StubMapping.buildFrom(StreamUtils
+ .copyToString(full.getInputStream(), Charset.forName("UTF-8"))));
+
+ ResponseEntity responseEntity = new RestTemplate()
+ .exchange(RequestEntity
+ .post(URI.create(
+ "http://localhost:" + server.port() + "/xmlfraud"))
+ .contentType(MediaType.valueOf("application/xml;charset=UTF-8"))
+ .body(new XmlRequestBody("foo")), XmlResponseBody.class);
+
+ BDDAssertions.then(responseEntity.getStatusCodeValue()).isEqualTo(200);
+ BDDAssertions.then(responseEntity.getBody().status).isEqualTo("FULL");
+ }
+
+ @Test
+ void shouldSuccessfullyReturnEmptyResponse() throws Exception {
+ server.addStubMapping(StubMapping.buildFrom(StreamUtils
+ .copyToString(empty.getInputStream(), Charset.forName("UTF-8"))));
+
+ ResponseEntity responseEntity = new RestTemplate()
+ .exchange(RequestEntity
+ .post(URI.create(
+ "http://localhost:" + server.port() + "/xmlfraud"))
+ .contentType(MediaType.valueOf("application/xml;charset=UTF-8"))
+ .body(new XmlRequestBody("")), XmlResponseBody.class);
+
+ BDDAssertions.then(responseEntity.getStatusCodeValue()).isEqualTo(200);
+ BDDAssertions.then(responseEntity.getBody().status).isEqualTo("EMPTY");
+ }
+
+}
+
+class XmlRequestBody {
+
+ public String name;
+
+ public XmlRequestBody(String name) {
+ this.name = name;
+ }
+
+}
+
+class XmlResponseBody {
+
+ public String status;
+
+ public XmlResponseBody(String status) {
+ this.status = status;
+ }
+
+ public XmlResponseBody() {
+ }
+
+}
diff --git a/standalone/restdocs/http-client/src/test/java/com/example/loan/XmlServiceUsingStubRunnerTests.java b/standalone/restdocs/http-client/src/test/java/com/example/loan/XmlServiceUsingStubRunnerTests.java
new file mode 100644
index 000000000..68212120c
--- /dev/null
+++ b/standalone/restdocs/http-client/src/test/java/com/example/loan/XmlServiceUsingStubRunnerTests.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.loan;
+
+import java.net.URI;
+
+import org.assertj.core.api.BDDAssertions;
+import org.junit.jupiter.api.Test;
+
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner;
+import org.springframework.http.MediaType;
+import org.springframework.http.RequestEntity;
+import org.springframework.http.ResponseEntity;
+
+import org.springframework.web.client.RestTemplate;
+
+
+@SpringBootTest
+@AutoConfigureStubRunner(ids = "com.example:http-server-restdocs")
+class XmlServiceUsingStubRunnerTests {
+
+ @Value("${stubrunner.runningstubs.http-server-restdocs.port}")
+ int port;
+
+ @Test
+ void shouldSuccessfullyReturnFullResponse() throws Exception {
+ ResponseEntity responseEntity = new RestTemplate()
+ .exchange(RequestEntity
+ .post(URI.create("http://localhost:" + this.port + "/xmlfraud"))
+ .contentType(MediaType.valueOf("application/xml;charset=UTF-8"))
+ .body(new XmlRequestBody("foo")), XmlResponseBody.class);
+
+ BDDAssertions.then(responseEntity.getStatusCodeValue()).isEqualTo(200);
+ BDDAssertions.then(responseEntity.getBody().status).isEqualTo("FULL");
+ }
+
+ @Test
+ void shouldSuccessfullyReturnEmptyResponse() throws Exception {
+ ResponseEntity responseEntity = new RestTemplate()
+ .exchange(RequestEntity
+ .post(URI.create("http://localhost:" + this.port + "/xmlfraud"))
+ .contentType(MediaType.valueOf("application/xml;charset=UTF-8"))
+ .body(new XmlRequestBody("")), XmlResponseBody.class);
+
+ BDDAssertions.then(responseEntity.getStatusCodeValue()).isEqualTo(200);
+ BDDAssertions.then(responseEntity.getBody().status).isEqualTo("EMPTY");
+ }
+
+}
diff --git a/standalone/restdocs/http-client/src/test/resources/application-gradle.yaml b/standalone/restdocs/http-client/src/test/resources/application-gradle.yaml
new file mode 100644
index 000000000..b1818d916
--- /dev/null
+++ b/standalone/restdocs/http-client/src/test/resources/application-gradle.yaml
@@ -0,0 +1,2 @@
+stubrunner:
+ stubs.ids: 'com.example:http-server-restdocs-gradle'
diff --git a/standalone/restdocs/http-server/.gitignore b/standalone/restdocs/http-server/.gitignore
new file mode 100644
index 000000000..b05ba7bd6
--- /dev/null
+++ b/standalone/restdocs/http-server/.gitignore
@@ -0,0 +1,6 @@
+
+target/
+
+.gradle
+build/
+
diff --git a/standalone/restdocs/http-server/.mvn/jvm.config b/standalone/restdocs/http-server/.mvn/jvm.config
new file mode 100644
index 000000000..0e7dabeff
--- /dev/null
+++ b/standalone/restdocs/http-server/.mvn/jvm.config
@@ -0,0 +1 @@
+-Xmx1024m -XX:CICompilerCount=1 -XX:TieredStopAtLevel=1 -Djava.security.egd=file:/dev/./urandom
\ No newline at end of file
diff --git a/standalone/restdocs/http-server/.mvn/maven.config b/standalone/restdocs/http-server/.mvn/maven.config
new file mode 100644
index 000000000..a68299056
--- /dev/null
+++ b/standalone/restdocs/http-server/.mvn/maven.config
@@ -0,0 +1 @@
+-P spring
diff --git a/standalone/restdocs/http-server/.mvn/wrapper/MavenWrapperDownloader.java b/standalone/restdocs/http-server/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 000000000..b901097f2
--- /dev/null
+++ b/standalone/restdocs/http-server/.mvn/wrapper/MavenWrapperDownloader.java
@@ -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();
+ }
+
+}
diff --git a/standalone/restdocs/http-server/.mvn/wrapper/maven-wrapper.jar b/standalone/restdocs/http-server/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 000000000..c1dd12f17
Binary files /dev/null and b/standalone/restdocs/http-server/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/standalone/restdocs/http-server/.mvn/wrapper/maven-wrapper.properties b/standalone/restdocs/http-server/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 000000000..015dfe682
--- /dev/null
+++ b/standalone/restdocs/http-server/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,18 @@
+# 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.
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.3/apache-maven-3.8.3-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar
diff --git a/standalone/restdocs/http-server/README.adoc b/standalone/restdocs/http-server/README.adoc
new file mode 100644
index 000000000..2fd3fbc40
--- /dev/null
+++ b/standalone/restdocs/http-server/README.adoc
@@ -0,0 +1,20 @@
+= Http Server
+
+Run
+
+[source=groovy]
+--------
+./gradlew clean build publishToMavenLocal
+--------
+
+or
+
+--------
+./mvnw clean install
+--------
+
+To
+
+- build the app
+- generate and run Spring Cloud Contract Verifier tests
+- publish the fatJar and the stubs to Maven Local
\ No newline at end of file
diff --git a/standalone/restdocs/http-server/build.gradle b/standalone/restdocs/http-server/build.gradle
new file mode 100644
index 000000000..5fde7e7a5
--- /dev/null
+++ b/standalone/restdocs/http-server/build.gradle
@@ -0,0 +1,128 @@
+plugins {
+ id "groovy"
+ id "org.springframework.boot"
+ id "io.spring.dependency-management"
+ id "org.springframework.cloud.contract"
+ id "maven-publish"
+}
+
+group = 'com.example'
+version = '0.0.1'
+
+repositories {
+ mavenCentral()
+ mavenLocal()
+ maven { url "https://repo.spring.io/snapshot" }
+ maven { url "https://repo.spring.io/milestone" }
+}
+
+dependencyManagement {
+ imports {
+ mavenBom "org.springframework.cloud:spring-cloud-contract-dependencies:${verifierVersion}"
+ }
+}
+
+dependencies {
+ implementation("org.springframework.boot:spring-boot-starter-web")
+ implementation("org.springframework.boot:spring-boot-starter-actuator")
+ implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-xml")
+
+ testImplementation('org.springframework.boot:spring-boot-starter-test')
+ testImplementation 'org.springframework.cloud:spring-cloud-starter-contract-stub-runner'
+ // tag::dependencies[]
+ testImplementation 'org.springframework.cloud:spring-cloud-starter-contract-verifier'
+ testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc'
+ // end::dependencies[]
+}
+
+contracts {
+ baseClassMappings {
+ baseClassMapping('.*standalone.*', 'com.example.fraud.FraudBaseWithStandaloneSetup')
+ baseClassMapping('.*webapp.*', 'com.example.fraud.FraudBaseWithWebAppSetup')
+ }
+}
+
+generateClientStubs.enabled = false
+
+test {
+ useJUnitPlatform()
+ systemProperty 'spring.profiles.active', 'gradle'
+ testLogging {
+ exceptionFormat = 'full'
+ }
+ afterSuite { desc, result ->
+ if (!desc.parent) {
+ println "Results: (${result.testCount} tests, ${result.successfulTestCount} successes, ${result.failedTestCount} failures, ${result.skippedTestCount} skipped)"
+ if (result.testCount == 0) {
+ throw new IllegalStateException("No tests were found. Failing the build")
+ }
+ }
+ }
+}
+
+task stubsJar(type: Jar, dependsOn: ['copySnippets', 'copySources', 'copyClasses']) {
+ archiveBaseName = project.name
+ archiveClassifier = 'stubs'
+ from project.file("${project.buildDir}/stubs")
+}
+
+task copySnippets(type: Copy, dependsOn: test) {
+ from "target/snippets/stubs"
+ into "${project.buildDir}/stubs/META-INF/${project.group}/${project.name}/${project.version}/mappings"
+}
+
+task copySources(type: Copy) {
+ from "src/main/java"
+ include '**/model/Fraud*.*'
+ into "${project.buildDir}/stubs/"
+}
+
+task copyClasses(type: Copy) {
+ from "${project.buildDir}/classes/main/"
+ include '**/model/Fraud*.*'
+ into "${project.buildDir}/stubs/"
+}
+
+
+project.tasks.named("verifierStubsJar").get().dependsOn('copySnippets', 'copySources', 'stubsJar') // TODO: We need to fix this
+project.tasks.named("copyContracts").get().dependsOn('stubsJar') // TODO: We need to fix this
+afterEvaluate {
+ project.tasks.matching { it.name.contains("publish") }.each { it.dependsOn('verifierStubsJar') } // TODO: We need to fix this
+}
+
+publishing {
+ publications {
+ maven(MavenPublication) {
+ artifact bootJar
+ artifact stubsJar
+
+ // https://github.com/spring-gradle-plugins/dependency-management-plugin/issues/273
+ versionMapping {
+ usage("java-api") {
+ fromResolutionOf("runtimeClasspath")
+ }
+ usage("java-runtime") {
+ fromResolutionResult()
+ }
+ }
+ }
+ }
+}
+
+clean.doFirst {
+ delete 'target/snippets/stubs'
+ delete "~/.m2/repository/com/example/http-server-restdocs-gradle"
+}
+
+task resolveDependencies {
+ doLast {
+ project.rootProject.allprojects.each { subProject ->
+ subProject.buildscript.configurations.each { configuration ->
+ configuration.resolve()
+ }
+ subProject.configurations.each { configuration ->
+ configuration.resolve()
+ }
+ }
+ }
+}
diff --git a/standalone/restdocs/http-server/gradle.properties b/standalone/restdocs/http-server/gradle.properties
new file mode 100644
index 000000000..1696bd82a
--- /dev/null
+++ b/standalone/restdocs/http-server/gradle.properties
@@ -0,0 +1,3 @@
+org.gradle.daemon=false
+verifierVersion=4.1.5-SNAPSHOT
+bootVersion=3.2.7
diff --git a/standalone/restdocs/http-server/gradle/wrapper/gradle-wrapper.jar b/standalone/restdocs/http-server/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 000000000..7f93135c4
Binary files /dev/null and b/standalone/restdocs/http-server/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/standalone/restdocs/http-server/gradle/wrapper/gradle-wrapper.properties b/standalone/restdocs/http-server/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 000000000..ac72c34e8
--- /dev/null
+++ b/standalone/restdocs/http-server/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,7 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
+networkTimeout=10000
+validateDistributionUrl=true
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/standalone/restdocs/http-server/gradlew b/standalone/restdocs/http-server/gradlew
new file mode 100755
index 000000000..0adc8e1a5
--- /dev/null
+++ b/standalone/restdocs/http-server/gradlew
@@ -0,0 +1,249 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original 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 POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
+done
+
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+ echo "$*"
+} >&2
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+} >&2
+
+# 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 ;; #(
+ MSYS* | 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
+ if ! command -v java >/dev/null 2>&1
+ then
+ 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
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC3045
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC3045
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+
+# 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"'
+
+# Collect all arguments for the java command;
+# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+# shell script including quotes and variable substitutions, so put them in
+# double quotes to make sure that they get re-expanded; and
+# * put everything else in single quotes, so that it's not re-expanded.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+ die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/standalone/restdocs/http-server/gradlew.bat b/standalone/restdocs/http-server/gradlew.bat
new file mode 100644
index 000000000..93e3f59f1
--- /dev/null
+++ b/standalone/restdocs/http-server/gradlew.bat
@@ -0,0 +1,92 @@
+@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=.
+@rem This is normally unused
+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% equ 0 goto execute
+
+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 execute
+
+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
+
+: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 %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if %ERRORLEVEL% equ 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!
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/standalone/restdocs/http-server/mvnw b/standalone/restdocs/http-server/mvnw
new file mode 100755
index 000000000..5643201c7
--- /dev/null
+++ b/standalone/restdocs/http-server/mvnw
@@ -0,0 +1,316 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# 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 /usr/local/etc/mavenrc ] ; then
+ . /usr/local/etc/mavenrc
+ fi
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ export JAVA_HOME="`/usr/libexec/java_home`"
+ else
+ export JAVA_HOME="/Library/Java/Home"
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=`java-config --jre-home`
+ fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+ ## resolve links - $0 may be a link to maven's home
+ PRG="$0"
+
+ # need this for relative symlinks
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG="`dirname "$PRG"`/$link"
+ fi
+ done
+
+ saveddir=`pwd`
+
+ M2_HOME=`dirname "$PRG"`/..
+
+ # make it fully qualified
+ M2_HOME=`cd "$M2_HOME" && pwd`
+
+ cd "$saveddir"
+ # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --unix "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME="`(cd "$M2_HOME"; pwd)`"
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="`which javac`"
+ if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=`which readlink`
+ if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+ if $darwin ; then
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+ else
+ javaExecutable="`readlink -f \"$javaExecutable\"`"
+ fi
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="`\\unset -f command; \\command -v java`"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=`cd "$wdir/.."; pwd`
+ fi
+ # end of workaround
+ done
+ echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ echo "$(tr -s '\n' ' ' < "$1")"
+ fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found .mvn/wrapper/maven-wrapper.jar"
+ fi
+else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+ fi
+ if [ -n "$MVNW_REPOURL" ]; then
+ jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+ else
+ jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+ fi
+ while IFS="=" read key value; do
+ case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
+ esac
+ done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Downloading from: $jarUrl"
+ fi
+ wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+ if $cygwin; then
+ wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
+ fi
+
+ if command -v wget > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found wget ... using wget"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ else
+ wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ fi
+ elif command -v curl > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found curl ... using curl"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl -o "$wrapperJarPath" "$jarUrl" -f
+ else
+ curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
+ fi
+
+ else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Falling back to using Java to download"
+ fi
+ javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaClass=`cygpath --path --windows "$javaClass"`
+ fi
+ if [ -e "$javaClass" ]; then
+ if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Compiling MavenWrapperDownloader.java ..."
+ fi
+ # Compiling the Java class
+ ("$JAVA_HOME/bin/javac" "$javaClass")
+ fi
+ if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ # Running the downloader
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Running MavenWrapperDownloader.java ..."
+ fi
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+if [ "$MVNW_VERBOSE" = true ]; then
+ echo $MAVEN_PROJECTBASEDIR
+fi
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --path --windows "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ $MAVEN_DEBUG_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.home=${M2_HOME}" \
+ "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/standalone/restdocs/http-server/mvnw.cmd b/standalone/restdocs/http-server/mvnw.cmd
new file mode 100644
index 000000000..8a15b7f31
--- /dev/null
+++ b/standalone/restdocs/http-server/mvnw.cmd
@@ -0,0 +1,188 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM 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 "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
+if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Found %WRAPPER_JAR%
+ )
+) else (
+ if not "%MVNW_REPOURL%" == "" (
+ SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+ )
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %DOWNLOAD_URL%
+ )
+
+ powershell -Command "&{"^
+ "$webclient = new-object System.Net.WebClient;"^
+ "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+ "}"^
+ "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
+ "}"
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Finished downloading %WRAPPER_JAR%
+ )
+)
+@REM End of extension
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% ^
+ %JVM_CONFIG_MAVEN_PROPS% ^
+ %MAVEN_OPTS% ^
+ %MAVEN_DEBUG_OPTS% ^
+ -classpath %WRAPPER_JAR% ^
+ "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
+ %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
+if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%"=="on" pause
+
+if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
+
+cmd /C exit /B %ERROR_CODE%
diff --git a/standalone/restdocs/http-server/pom.xml b/standalone/restdocs/http-server/pom.xml
new file mode 100644
index 000000000..44c34e3a0
--- /dev/null
+++ b/standalone/restdocs/http-server/pom.xml
@@ -0,0 +1,274 @@
+
+
+ 4.0.0
+
+ com.example
+ http-server-restdocs
+ 0.0.1
+
+ Spring Cloud Contract RestDocs Http Server Sample
+ Spring Cloud RestDocs Verifier Http Server Sample
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.2.7
+
+
+
+
+ UTF-8
+ 17
+ 4.1.5-SNAPSHOT
+ true
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+ com.fasterxml.jackson.dataformat
+ jackson-dataformat-xml
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-contract-stub-runner
+ test
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-contract-verifier
+ test
+
+
+ org.springframework.restdocs
+ spring-restdocs-mockmvc
+ true
+
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-contract-dependencies
+ ${spring-cloud-contract.version}
+ pom
+ import
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ maven-deploy-plugin
+
+ true
+
+
+
+ org.apache.maven.plugins
+ maven-clean-plugin
+
+
+
+ build
+
+
+ target
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-assembly-plugin
+
+
+ stub
+ prepare-package
+
+ single
+
+ false
+
+ true
+
+ ${basedir}/src/assembly/stub.xml
+
+
+
+
+
+
+ maven-surefire-plugin
+
+ true
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-contract-maven-plugin
+ ${spring-cloud-contract.version}
+ true
+
+
+
+ .*standalone.*
+ com.example.fraud.FraudBaseWithStandaloneSetup
+
+
+
+ .*webapp.*
+ com.example.fraud.FraudBaseWithWebAppSetup
+
+
+
+
+
+
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
+
+
+
+ windows
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 1.6.0
+
+
+ gradle
+ test
+
+ gradlew.bat
+
+ clean
+ build
+
+ install
+
+ -x
+ test
+
+ -x
+ contractTest
+
+ -PverifierVersion=${spring-cloud-contract.version}
+
+
+
+
+ exec
+
+
+
+
+
+
+
+
+
diff --git a/standalone/restdocs/http-server/settings.gradle b/standalone/restdocs/http-server/settings.gradle
new file mode 100644
index 000000000..8d6570b7b
--- /dev/null
+++ b/standalone/restdocs/http-server/settings.gradle
@@ -0,0 +1,22 @@
+pluginManagement {
+ repositories {
+ mavenLocal()
+ maven { url "https://repo.spring.io/snapshot" }
+ maven { url "https://repo.spring.io/milestone" }
+ gradlePluginPortal()
+ }
+ plugins {
+ id 'org.springframework.boot' version "${bootVersion}"
+ id "io.spring.dependency-management" version "1.1.3"
+ }
+ resolutionStrategy {
+ eachPlugin {
+ // protects us in case the gradle-portal-plugin hasn't yet been published by Maven
+ if (requested.id.id == 'org.springframework.cloud.contract') {
+ useModule("org.springframework.cloud:spring-cloud-contract-gradle-plugin:${verifierVersion}")
+ }
+ }
+ }
+}
+
+rootProject.name = 'http-server-restdocs-gradle'
diff --git a/standalone/restdocs/http-server/src/assembly/stub.xml b/standalone/restdocs/http-server/src/assembly/stub.xml
new file mode 100644
index 000000000..310a3af24
--- /dev/null
+++ b/standalone/restdocs/http-server/src/assembly/stub.xml
@@ -0,0 +1,51 @@
+
+ stubs
+
+ jar
+
+ false
+
+
+ src/main/java
+ /
+
+ **/model/Fraud*.*
+
+
+
+ ${project.build.directory}/classes
+ /
+
+ **/model/Fraud*.*
+
+
+
+ ${project.build.directory}/generated-snippets/stubs
+
+ META-INF/${project.groupId}/${project.artifactId}/${project.version}/mappings
+
+
+ **/*
+
+
+
+ ${project.build.directory}/snippets/stubs
+
+ META-INF/${project.groupId}/${project.artifactId}/${project.version}/mappings
+
+
+ **/*
+
+
+
+ ${project.build.directory}/stubs
+ /
+
+ **/*
+
+
+
+
diff --git a/standalone/restdocs/http-server/src/main/java/com/example/fraud/Application.java b/standalone/restdocs/http-server/src/main/java/com/example/fraud/Application.java
new file mode 100644
index 000000000..c998b507b
--- /dev/null
+++ b/standalone/restdocs/http-server/src/main/java/com/example/fraud/Application.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.fraud;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@EnableAutoConfiguration
+@ComponentScan
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+}
diff --git a/standalone/restdocs/http-server/src/main/java/com/example/fraud/FraudDetectionController.java b/standalone/restdocs/http-server/src/main/java/com/example/fraud/FraudDetectionController.java
new file mode 100644
index 000000000..1d5469e93
--- /dev/null
+++ b/standalone/restdocs/http-server/src/main/java/com/example/fraud/FraudDetectionController.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.fraud;
+
+import java.math.BigDecimal;
+
+import com.example.fraud.model.FraudCheck;
+import com.example.fraud.model.FraudCheckResult;
+import com.example.fraud.model.FraudCheckStatus;
+
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import static org.springframework.web.bind.annotation.RequestMethod.PUT;
+
+@RestController
+public class FraudDetectionController {
+
+ private static final String FRAUD_SERVICE_JSON_VERSION_1 = "application/vnd.fraud.v1+json";
+
+ private static final String NO_REASON = null;
+
+ private static final String AMOUNT_TOO_HIGH = "Amount too high";
+
+ private static final BigDecimal MAX_AMOUNT = new BigDecimal("5000");
+
+ // tag::server_api[]
+ @RequestMapping(value = "/fraudcheck", method = PUT, consumes = FRAUD_SERVICE_JSON_VERSION_1, produces = FRAUD_SERVICE_JSON_VERSION_1)
+ public FraudCheckResult fraudCheck(@RequestBody FraudCheck fraudCheck) {
+ // end::server_api[]
+ // tag::new_impl[]
+ if (amountGreaterThanThreshold(fraudCheck)) {
+ return new FraudCheckResult(FraudCheckStatus.FRAUD, AMOUNT_TOO_HIGH);
+ }
+ // end::new_impl[]
+ // tag::initial_impl[]
+ return new FraudCheckResult(FraudCheckStatus.OK, NO_REASON);
+ // end::initial_impl[]
+ }
+
+ private boolean amountGreaterThanThreshold(FraudCheck fraudCheck) {
+ return MAX_AMOUNT.compareTo(fraudCheck.getLoanAmount()) < 0;
+ }
+
+}
diff --git a/standalone/restdocs/http-server/src/main/java/com/example/fraud/FraudDetectionXmlController.java b/standalone/restdocs/http-server/src/main/java/com/example/fraud/FraudDetectionXmlController.java
new file mode 100644
index 000000000..7db345a02
--- /dev/null
+++ b/standalone/restdocs/http-server/src/main/java/com/example/fraud/FraudDetectionXmlController.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.fraud;
+
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Controller;
+import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import static org.springframework.web.bind.annotation.RequestMethod.POST;
+
+@Controller
+public class FraudDetectionXmlController {
+
+ @RequestMapping(value = "/xmlfraud", method = POST, consumes = MediaType.APPLICATION_XML_VALUE, produces = MediaType.APPLICATION_XML_VALUE)
+ @ResponseBody
+ public XmlResponseBody xmlResponseBody(@RequestBody XmlRequestBody xmlRequestBody) {
+ if (!StringUtils.hasText(xmlRequestBody.name)) {
+ return new XmlResponseBody("EMPTY");
+ }
+ return new XmlResponseBody("FULL");
+ }
+
+}
+
+class XmlRequestBody {
+
+ public String name;
+
+}
+
+class XmlResponseBody {
+
+ public String status;
+
+ public XmlResponseBody(String status) {
+ this.status = status;
+ }
+
+ public XmlResponseBody() {
+ }
+
+}
diff --git a/standalone/restdocs/http-server/src/main/java/com/example/fraud/model/FraudCheck.java b/standalone/restdocs/http-server/src/main/java/com/example/fraud/model/FraudCheck.java
new file mode 100644
index 000000000..4cf6ae3ea
--- /dev/null
+++ b/standalone/restdocs/http-server/src/main/java/com/example/fraud/model/FraudCheck.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.fraud.model;
+
+import java.math.BigDecimal;
+
+public class FraudCheck {
+
+ private String clientId;
+
+ private BigDecimal loanAmount;
+
+ public FraudCheck() {
+ }
+
+ public String getClientId() {
+ return clientId;
+ }
+
+ public void setClientId(String clientId) {
+ this.clientId = clientId;
+ }
+
+ public BigDecimal getLoanAmount() {
+ return loanAmount;
+ }
+
+ public void setLoanAmount(BigDecimal loanAmount) {
+ this.loanAmount = loanAmount;
+ }
+
+}
diff --git a/standalone/restdocs/http-server/src/main/java/com/example/fraud/model/FraudCheckResult.java b/standalone/restdocs/http-server/src/main/java/com/example/fraud/model/FraudCheckResult.java
new file mode 100644
index 000000000..95440c679
--- /dev/null
+++ b/standalone/restdocs/http-server/src/main/java/com/example/fraud/model/FraudCheckResult.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.fraud.model;
+
+public class FraudCheckResult {
+
+ private FraudCheckStatus fraudCheckStatus;
+
+ private String rejectionReason;
+
+ public FraudCheckResult() {
+ }
+
+ public FraudCheckResult(FraudCheckStatus fraudCheckStatus, String rejectionReason) {
+ this.fraudCheckStatus = fraudCheckStatus;
+ this.rejectionReason = rejectionReason;
+ }
+
+ public FraudCheckStatus getFraudCheckStatus() {
+ return fraudCheckStatus;
+ }
+
+ public void setFraudCheckStatus(FraudCheckStatus fraudCheckStatus) {
+ this.fraudCheckStatus = fraudCheckStatus;
+ }
+
+ public String getRejectionReason() {
+ return rejectionReason;
+ }
+
+ public void setRejectionReason(String rejectionReason) {
+ this.rejectionReason = rejectionReason;
+ }
+
+}
diff --git a/standalone/restdocs/http-server/src/main/java/com/example/fraud/model/FraudCheckStatus.java b/standalone/restdocs/http-server/src/main/java/com/example/fraud/model/FraudCheckStatus.java
new file mode 100644
index 000000000..a43b649f5
--- /dev/null
+++ b/standalone/restdocs/http-server/src/main/java/com/example/fraud/model/FraudCheckStatus.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.fraud.model;
+
+public enum FraudCheckStatus {
+
+ OK, FRAUD
+
+}
diff --git a/standalone/restdocs/http-server/src/main/resources/application.yml b/standalone/restdocs/http-server/src/main/resources/application.yml
new file mode 100644
index 000000000..e69de29bb
diff --git a/standalone/restdocs/http-server/src/test/java/com/example/fraud/FraudBaseWithStandaloneSetup.java b/standalone/restdocs/http-server/src/test/java/com/example/fraud/FraudBaseWithStandaloneSetup.java
new file mode 100644
index 000000000..5af34819b
--- /dev/null
+++ b/standalone/restdocs/http-server/src/test/java/com/example/fraud/FraudBaseWithStandaloneSetup.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+// tag::base_class[]
+package com.example.fraud;
+
+import io.restassured.module.mockmvc.RestAssuredMockMvc;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.TestInfo;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import org.springframework.restdocs.RestDocumentationContextProvider;
+import org.springframework.restdocs.RestDocumentationExtension;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+
+import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
+import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
+
+@ExtendWith(RestDocumentationExtension.class)
+public abstract class FraudBaseWithStandaloneSetup {
+
+ @BeforeEach
+ public void setup(TestInfo info, RestDocumentationContextProvider restDocumentation) {
+ RestAssuredMockMvc.standaloneSetup(MockMvcBuilders
+ .standaloneSetup(new FraudDetectionController())
+ .apply(documentationConfiguration(restDocumentation))
+ .alwaysDo(document(
+ getClass().getSimpleName() + "_" + info.getDisplayName())));
+ }
+
+}
+// end::base_class[]
diff --git a/standalone/restdocs/http-server/src/test/java/com/example/fraud/FraudBaseWithWebAppSetup.java b/standalone/restdocs/http-server/src/test/java/com/example/fraud/FraudBaseWithWebAppSetup.java
new file mode 100644
index 000000000..5a7e68a9b
--- /dev/null
+++ b/standalone/restdocs/http-server/src/test/java/com/example/fraud/FraudBaseWithWebAppSetup.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+// tag::base_class[]
+package com.example.fraud;
+
+import io.restassured.module.mockmvc.RestAssuredMockMvc;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.TestInfo;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.restdocs.RestDocumentationContextProvider;
+import org.springframework.restdocs.RestDocumentationExtension;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.web.context.WebApplicationContext;
+
+import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
+import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
+
+@ExtendWith(RestDocumentationExtension.class)
+@SpringBootTest(classes = Application.class)
+public abstract class FraudBaseWithWebAppSetup {
+
+ @Autowired
+ private WebApplicationContext context;
+
+ @BeforeEach
+ public void setup(TestInfo info, RestDocumentationContextProvider restDocumentation) {
+ RestAssuredMockMvc.mockMvc(MockMvcBuilders.webAppContextSetup(this.context)
+ .apply(documentationConfiguration(restDocumentation))
+ .alwaysDo(document(
+ getClass().getSimpleName() + "_" + info.getDisplayName()))
+ .build());
+ }
+
+ protected void assertThatRejectionReasonIsNull(Object rejectionReason) {
+ assert rejectionReason == null;
+ }
+
+}
+// end::base_class[]
diff --git a/standalone/restdocs/http-server/src/test/java/com/example/fraud/StubGeneratorTests.java b/standalone/restdocs/http-server/src/test/java/com/example/fraud/StubGeneratorTests.java
new file mode 100644
index 000000000..e159ec787
--- /dev/null
+++ b/standalone/restdocs/http-server/src/test/java/com/example/fraud/StubGeneratorTests.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.fraud;
+
+import java.math.BigDecimal;
+
+import com.example.fraud.model.FraudCheck;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.json.AutoConfigureJsonTesters;
+import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs;
+import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.json.JacksonTester;
+import org.springframework.http.MediaType;
+
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+
+import static org.springframework.cloud.contract.wiremock.restdocs.WireMockRestDocs.verify;
+import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
+
+@SpringBootTest(classes = Application.class)
+@AutoConfigureRestDocs(outputDir = "target/snippets")
+@AutoConfigureMockMvc
+@AutoConfigureJsonTesters
+public class StubGeneratorTests {
+
+ @Autowired
+ private MockMvc mockMvc;
+
+ private JacksonTester json;
+
+ @BeforeEach
+ public void setup() {
+ ObjectMapper objectMappper = new ObjectMapper();
+ // Possibly configure the mapper
+ JacksonTester.initFields(this, objectMappper);
+ }
+
+ @Test
+ public void shouldMarkClientAsFraud() throws Exception {
+ FraudCheck fraudCheck = new FraudCheck();
+ fraudCheck.setClientId("1234567890");
+ fraudCheck.setLoanAmount(BigDecimal.valueOf(99999.0));
+ mockMvc.perform(MockMvcRequestBuilders.put("/fraudcheck")
+ .contentType(MediaType.valueOf("application/vnd.fraud.v1+json"))
+ .content(json.write(fraudCheck).getJson()))
+ .andExpect(jsonPath("$.fraudCheckStatus").value("FRAUD"))
+ .andExpect(jsonPath("$.rejectionReason").value("Amount too high"))
+ .andDo(verify().jsonPath("$.clientId")
+ .jsonPath("$[?(@.loanAmount > 1000)]")
+ .contentType(MediaType.valueOf("application/vnd.fraud.v1+json")))
+ .andDo(document("markClientAsFraud"));
+ }
+
+ @Test
+ public void shouldMarkClientAsNotFraud() throws Exception {
+ FraudCheck fraudCheck = new FraudCheck();
+ fraudCheck.setClientId("1234567890");
+ fraudCheck.setLoanAmount(BigDecimal.valueOf(123.123));
+ mockMvc.perform(MockMvcRequestBuilders.put("/fraudcheck")
+ .contentType(MediaType.valueOf("application/vnd.fraud.v1+json"))
+ .content(json.write(fraudCheck).getJson()))
+ .andExpect(jsonPath("$.fraudCheckStatus").value("OK"))
+ .andExpect(jsonPath("$.rejectionReason").doesNotExist())
+ .andDo(verify().jsonPath("$.clientId")
+ .jsonPath("$[?(@.loanAmount <= 1000)]")
+ .contentType(MediaType.valueOf("application/vnd.fraud.v1+json")))
+ .andDo(document("markClientAsNotFraud"));
+ }
+
+}
diff --git a/standalone/restdocs/http-server/src/test/java/com/example/fraud/XmlStubGeneratorTests.java b/standalone/restdocs/http-server/src/test/java/com/example/fraud/XmlStubGeneratorTests.java
new file mode 100644
index 000000000..610573ee4
--- /dev/null
+++ b/standalone/restdocs/http-server/src/test/java/com/example/fraud/XmlStubGeneratorTests.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.fraud;
+
+import org.junit.jupiter.api.Test;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs;
+import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.http.MediaType;
+import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation;
+
+import org.springframework.test.web.servlet.MockMvc;
+
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+@SpringBootTest(classes = Application.class)
+@AutoConfigureRestDocs(outputDir = "target/snippets")
+@AutoConfigureMockMvc
+class XmlStubGeneratorTests {
+
+ @Autowired
+ private MockMvc mockMvc;
+
+ @Test
+ void should_return_full_content() throws Exception {
+ mockMvc.perform(post("/xmlfraud").contentType(MediaType.APPLICATION_XML)
+ .content("foo"))
+ .andExpect(status().is2xxSuccessful())
+ .andExpect(content().string(
+ "FULL"))
+ .andDo(MockMvcRestDocumentation.document("{methodName}"));
+ }
+
+ @Test
+ void should_return_empty_content() throws Exception {
+ mockMvc.perform(post("/xmlfraud").contentType(MediaType.APPLICATION_XML)
+ .content(""))
+ .andExpect(status().is2xxSuccessful())
+ .andExpect(content().string(
+ "EMPTY"))
+ .andDo(MockMvcRestDocumentation.document("{methodName}"));
+ }
+
+}
diff --git a/standalone/restdocs/http-server/src/test/resources/contracts/standalone/shouldMarkClientAsFraud.groovy b/standalone/restdocs/http-server/src/test/resources/contracts/standalone/shouldMarkClientAsFraud.groovy
new file mode 100644
index 000000000..ca4e32181
--- /dev/null
+++ b/standalone/restdocs/http-server/src/test/resources/contracts/standalone/shouldMarkClientAsFraud.groovy
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package contracts.standalone
+
+org.springframework.cloud.contract.spec.Contract.make {
+ request { // (1)
+ method 'PUT' // (2)
+ url '/fraudcheck' // (3)
+ body([ // (4)
+ clientId : $(c(regex('[0-9]{10}')), p("8532032713")),
+ loanAmount: 99999
+ ])
+ headers { // (5)
+ contentType('application/vnd.fraud.v1+json')
+ }
+ }
+ response { // (6)
+ status OK() // (7)
+ body([ // (8)
+ fraudCheckStatus: "FRAUD",
+ rejectionReason : "Amount too high"
+ ])
+ headers { // (9)
+ contentType('application/vnd.fraud.v1+json')
+ }
+ }
+}
+
+/*
+Since we don't want to force on the user to hardcode values of fields that are dynamic
+(timestamps, database ids etc.), one can parametrize those entries. If you wrap your field's
+ value in a `$(...)` or `value(...)` and provide a dynamic value of a field then
+ the concrete value will be generated for you. If you want to be really explicit about
+ which side gets which value you can do that by using the `value(consumer(...), producer(...))` notation.
+ That way what's present in the `consumer` section will end up in the produced stub. What's
+ there in the `producer` will end up in the autogenerated test. If you provide only the
+ regular expression side without the concrete value then Spring Cloud Contract will generate one for you.
+
+From the Consumer perspective, when shooting a request in the integration test:
+
+(1) - If the consumer sends a request
+(2) - With the "PUT" method
+(3) - to the URL "/fraudcheck"
+(4) - with the JSON body that
+ * has a field `clientId` that matches a regular expression `[0-9]{10}`
+ * has a field `loanAmount` that is equal to `99999`
+(5) - with header `Content-Type` equal to `application/vnd.fraud.v1+json`
+(6) - then the response will be sent with
+(7) - status equal `200`
+(8) - and JSON body equal to
+ { "fraudCheckStatus": "FRAUD", "rejectionReason": "Amount too high" }
+(9) - with header `Content-Type` equal to `application/vnd.fraud.v1+json`
+
+From the Producer perspective, in the autogenerated producer-side test:
+
+(1) - A request will be sent to the producer
+(2) - With the "PUT" method
+(3) - to the URL "/fraudcheck"
+(4) - with the JSON body that
+ * has a field `clientId` that will have a generated value that matches a regular expression `[0-9]{10}`
+ * has a field `loanAmount` that is equal to `99999`
+(5) - with header `Content-Type` equal to `application/vnd.fraud.v1+json`
+(6) - then the test will assert if the response has been sent with
+(7) - status equal `200`
+(8) - and JSON body equal to
+ { "fraudCheckStatus": "FRAUD", "rejectionReason": "Amount too high" }
+(9) - with header `Content-Type` matching `application/vnd.fraud.v1+json.*`
+ */
diff --git a/standalone/restdocs/http-server/src/test/resources/contracts/webapp/shouldMarkClientAsNotFraud.groovy b/standalone/restdocs/http-server/src/test/resources/contracts/webapp/shouldMarkClientAsNotFraud.groovy
new file mode 100644
index 000000000..ec4dc73cc
--- /dev/null
+++ b/standalone/restdocs/http-server/src/test/resources/contracts/webapp/shouldMarkClientAsNotFraud.groovy
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package contracts.webapp
+
+org.springframework.cloud.contract.spec.Contract.make {
+ request {
+ method 'PUT'
+ url '/fraudcheck'
+ body("""
+ {
+ "clientId":"${value(consumer(regex('[0-9]{10}')), producer('1234567890'))}",
+ "loanAmount":123.123
+ }
+ """
+ )
+ headers {
+ contentType("application/vnd.fraud.v1+json")
+ }
+
+ }
+ response {
+ status OK()
+ body(
+ fraudCheckStatus: "OK",
+ rejectionReason: $(consumer(null),
+ producer(execute('assertThatRejectionReasonIsNull($it)')))
+ )
+ headers {
+ contentType("application/vnd.fraud.v1+json")
+ }
+ }
+}
diff --git a/standalone/webclient/http-client/.gitignore b/standalone/webclient/http-client/.gitignore
new file mode 100644
index 000000000..a275b7b86
--- /dev/null
+++ b/standalone/webclient/http-client/.gitignore
@@ -0,0 +1,7 @@
+
+target/
+
+.gradle
+build/
+
+/.apt_generated/
diff --git a/standalone/webclient/http-client/.mvn/jvm.config b/standalone/webclient/http-client/.mvn/jvm.config
new file mode 100644
index 000000000..0e7dabeff
--- /dev/null
+++ b/standalone/webclient/http-client/.mvn/jvm.config
@@ -0,0 +1 @@
+-Xmx1024m -XX:CICompilerCount=1 -XX:TieredStopAtLevel=1 -Djava.security.egd=file:/dev/./urandom
\ No newline at end of file
diff --git a/standalone/webclient/http-client/.mvn/maven.config b/standalone/webclient/http-client/.mvn/maven.config
new file mode 100644
index 000000000..a68299056
--- /dev/null
+++ b/standalone/webclient/http-client/.mvn/maven.config
@@ -0,0 +1 @@
+-P spring
diff --git a/standalone/webclient/http-client/.mvn/wrapper/MavenWrapperDownloader.java b/standalone/webclient/http-client/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 000000000..b901097f2
--- /dev/null
+++ b/standalone/webclient/http-client/.mvn/wrapper/MavenWrapperDownloader.java
@@ -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();
+ }
+
+}
diff --git a/standalone/webclient/http-client/.mvn/wrapper/maven-wrapper.jar b/standalone/webclient/http-client/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 000000000..c1dd12f17
Binary files /dev/null and b/standalone/webclient/http-client/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/standalone/webclient/http-client/.mvn/wrapper/maven-wrapper.properties b/standalone/webclient/http-client/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 000000000..015dfe682
--- /dev/null
+++ b/standalone/webclient/http-client/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,18 @@
+# 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.
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.3/apache-maven-3.8.3-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar
diff --git a/standalone/webclient/http-client/README.adoc b/standalone/webclient/http-client/README.adoc
new file mode 100644
index 000000000..cdcb0e4a5
--- /dev/null
+++ b/standalone/webclient/http-client/README.adoc
@@ -0,0 +1,26 @@
+= Http Client
+
+== Prerequisites
+
+First you have to publish to Maven Local the stubs of the *http-server* module
+
+== How to run it?
+
+Run
+
+[source=groovy]
+--------
+./gradlew clean build
+--------
+
+or
+
+--------
+./mvnw clean package
+--------
+
+To
+
+- build the app
+- use spring-cloud-contract-stub-runner-spring[Stub Runner Spring] to download the stub of `Http Server`
+- run the tests against stubbed server
\ No newline at end of file
diff --git a/standalone/webclient/http-client/build.gradle b/standalone/webclient/http-client/build.gradle
new file mode 100644
index 000000000..95edc7e2c
--- /dev/null
+++ b/standalone/webclient/http-client/build.gradle
@@ -0,0 +1,64 @@
+plugins {
+ id "groovy"
+ id "org.springframework.boot"
+ id "io.spring.dependency-management"
+ id "maven-publish"
+}
+
+group = 'com.example'
+version = '0.0.1'
+
+repositories {
+ mavenCentral()
+ mavenLocal()
+ maven { url "https://repo.spring.io/snapshot" }
+ maven { url "https://repo.spring.io/milestone" }
+}
+
+dependencyManagement {
+ imports {
+ mavenBom "org.springframework.cloud:spring-cloud-contract-dependencies:${verifierVersion}"
+ }
+}
+
+dependencies {
+ implementation("org.springframework.boot:spring-boot-starter-web")
+ implementation("org.springframework.boot:spring-boot-starter-actuator")
+
+ testImplementation 'org.springframework.cloud:spring-cloud-contract-wiremock'
+ testImplementation 'org.springframework.cloud:spring-cloud-starter-contract-stub-runner'
+ testImplementation('org.springframework.boot:spring-boot-starter-test') {
+ exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
+ }
+ testImplementation "com.example:http-server-webclient:0.0.1:stubs"
+}
+
+test {
+ useJUnitPlatform()
+ include '**/*GradleTests*'
+ systemProperty 'spring.profiles.active', 'gradle'
+ testLogging {
+ exceptionFormat = 'full'
+ }
+ afterSuite { desc, result ->
+ if (!desc.parent) {
+ println "Results: (${result.testCount} tests, ${result.successfulTestCount} successes, ${result.failedTestCount} failures, ${result.skippedTestCount} skipped)"
+ if (result.testCount == 0) {
+ throw new IllegalStateException("No tests were found. Failing the build")
+ }
+ }
+ }
+}
+
+task resolveDependencies {
+ doLast {
+ project.rootProject.allprojects.each { subProject ->
+ subProject.buildscript.configurations.each { configuration ->
+ configuration.resolve()
+ }
+ subProject.configurations.each { configuration ->
+ configuration.resolve()
+ }
+ }
+ }
+}
diff --git a/standalone/webclient/http-client/gradle.properties b/standalone/webclient/http-client/gradle.properties
new file mode 100644
index 000000000..1696bd82a
--- /dev/null
+++ b/standalone/webclient/http-client/gradle.properties
@@ -0,0 +1,3 @@
+org.gradle.daemon=false
+verifierVersion=4.1.5-SNAPSHOT
+bootVersion=3.2.7
diff --git a/standalone/webclient/http-client/gradle/wrapper/gradle-wrapper.jar b/standalone/webclient/http-client/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 000000000..7f93135c4
Binary files /dev/null and b/standalone/webclient/http-client/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/standalone/webclient/http-client/gradle/wrapper/gradle-wrapper.properties b/standalone/webclient/http-client/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 000000000..ac72c34e8
--- /dev/null
+++ b/standalone/webclient/http-client/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,7 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
+networkTimeout=10000
+validateDistributionUrl=true
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/standalone/webclient/http-client/gradlew b/standalone/webclient/http-client/gradlew
new file mode 100755
index 000000000..0adc8e1a5
--- /dev/null
+++ b/standalone/webclient/http-client/gradlew
@@ -0,0 +1,249 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original 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 POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
+done
+
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+ echo "$*"
+} >&2
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+} >&2
+
+# 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 ;; #(
+ MSYS* | 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
+ if ! command -v java >/dev/null 2>&1
+ then
+ 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
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC3045
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC3045
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+
+# 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"'
+
+# Collect all arguments for the java command;
+# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+# shell script including quotes and variable substitutions, so put them in
+# double quotes to make sure that they get re-expanded; and
+# * put everything else in single quotes, so that it's not re-expanded.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+ die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/standalone/webclient/http-client/gradlew.bat b/standalone/webclient/http-client/gradlew.bat
new file mode 100644
index 000000000..93e3f59f1
--- /dev/null
+++ b/standalone/webclient/http-client/gradlew.bat
@@ -0,0 +1,92 @@
+@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=.
+@rem This is normally unused
+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% equ 0 goto execute
+
+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 execute
+
+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
+
+: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 %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if %ERRORLEVEL% equ 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!
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/standalone/webclient/http-client/mvnw b/standalone/webclient/http-client/mvnw
new file mode 100755
index 000000000..5643201c7
--- /dev/null
+++ b/standalone/webclient/http-client/mvnw
@@ -0,0 +1,316 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# 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 /usr/local/etc/mavenrc ] ; then
+ . /usr/local/etc/mavenrc
+ fi
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ export JAVA_HOME="`/usr/libexec/java_home`"
+ else
+ export JAVA_HOME="/Library/Java/Home"
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=`java-config --jre-home`
+ fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+ ## resolve links - $0 may be a link to maven's home
+ PRG="$0"
+
+ # need this for relative symlinks
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG="`dirname "$PRG"`/$link"
+ fi
+ done
+
+ saveddir=`pwd`
+
+ M2_HOME=`dirname "$PRG"`/..
+
+ # make it fully qualified
+ M2_HOME=`cd "$M2_HOME" && pwd`
+
+ cd "$saveddir"
+ # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --unix "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME="`(cd "$M2_HOME"; pwd)`"
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="`which javac`"
+ if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=`which readlink`
+ if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+ if $darwin ; then
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+ else
+ javaExecutable="`readlink -f \"$javaExecutable\"`"
+ fi
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="`\\unset -f command; \\command -v java`"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=`cd "$wdir/.."; pwd`
+ fi
+ # end of workaround
+ done
+ echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ echo "$(tr -s '\n' ' ' < "$1")"
+ fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found .mvn/wrapper/maven-wrapper.jar"
+ fi
+else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+ fi
+ if [ -n "$MVNW_REPOURL" ]; then
+ jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+ else
+ jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+ fi
+ while IFS="=" read key value; do
+ case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
+ esac
+ done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Downloading from: $jarUrl"
+ fi
+ wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+ if $cygwin; then
+ wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
+ fi
+
+ if command -v wget > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found wget ... using wget"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ else
+ wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ fi
+ elif command -v curl > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found curl ... using curl"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl -o "$wrapperJarPath" "$jarUrl" -f
+ else
+ curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
+ fi
+
+ else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Falling back to using Java to download"
+ fi
+ javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaClass=`cygpath --path --windows "$javaClass"`
+ fi
+ if [ -e "$javaClass" ]; then
+ if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Compiling MavenWrapperDownloader.java ..."
+ fi
+ # Compiling the Java class
+ ("$JAVA_HOME/bin/javac" "$javaClass")
+ fi
+ if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ # Running the downloader
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Running MavenWrapperDownloader.java ..."
+ fi
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+if [ "$MVNW_VERBOSE" = true ]; then
+ echo $MAVEN_PROJECTBASEDIR
+fi
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --path --windows "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ $MAVEN_DEBUG_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.home=${M2_HOME}" \
+ "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/standalone/webclient/http-client/mvnw.cmd b/standalone/webclient/http-client/mvnw.cmd
new file mode 100644
index 000000000..8a15b7f31
--- /dev/null
+++ b/standalone/webclient/http-client/mvnw.cmd
@@ -0,0 +1,188 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM 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 "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
+if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Found %WRAPPER_JAR%
+ )
+) else (
+ if not "%MVNW_REPOURL%" == "" (
+ SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+ )
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %DOWNLOAD_URL%
+ )
+
+ powershell -Command "&{"^
+ "$webclient = new-object System.Net.WebClient;"^
+ "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+ "}"^
+ "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
+ "}"
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Finished downloading %WRAPPER_JAR%
+ )
+)
+@REM End of extension
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% ^
+ %JVM_CONFIG_MAVEN_PROPS% ^
+ %MAVEN_OPTS% ^
+ %MAVEN_DEBUG_OPTS% ^
+ -classpath %WRAPPER_JAR% ^
+ "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
+ %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
+if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%"=="on" pause
+
+if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
+
+cmd /C exit /B %ERROR_CODE%
diff --git a/standalone/webclient/http-client/pom.xml b/standalone/webclient/http-client/pom.xml
new file mode 100644
index 000000000..06215e915
--- /dev/null
+++ b/standalone/webclient/http-client/pom.xml
@@ -0,0 +1,229 @@
+
+
+ 4.0.0
+
+ com.example
+ http-client-webclient
+ 0.0.1
+
+ Spring Cloud Contract RestDocs Http WebClient Sample
+ Spring Cloud Contract RestDocs Http WebClient Sample
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.2.7
+
+
+
+
+ UTF-8
+ 17
+ 4.1.5-SNAPSHOT
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.junit.vintage
+ junit-vintage-engine
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-contract-wiremock
+ test
+
+
+ org.springframework.cloud
+ spring-cloud-contract-stub-runner
+ test
+
+
+ com.example
+ http-server-webclient
+ stubs
+ 0.0.1
+ test
+
+
+ *
+ *
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-contract-dependencies
+ ${spring-cloud-contract.version}
+ pom
+ import
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+ **/*GradleTests.java
+
+ true
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ maven-deploy-plugin
+
+ true
+
+
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
+
+ integration
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 1.6.0
+
+
+ gradle
+ test
+
+ ./gradlew
+
+ clean
+ build
+ publishToMavenLocal
+
+ -x
+ test
+
+ -PverifierVersion=${spring-cloud-contract.version}
+
+
+
+
+ exec
+
+
+
+
+
+
+
+
+ windows
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 1.6.0
+
+
+ gradle
+ test
+
+ ./gradlew
+
+ clean
+ build
+ publishToMavenLocal
+
+ -x
+ test
+
+ -PverifierVersion=${spring-cloud-contract.version}
+
+
+
+
+ exec
+
+
+
+
+
+
+
+
+
+
diff --git a/standalone/webclient/http-client/settings.gradle b/standalone/webclient/http-client/settings.gradle
new file mode 100644
index 000000000..ff0d4920f
--- /dev/null
+++ b/standalone/webclient/http-client/settings.gradle
@@ -0,0 +1,14 @@
+pluginManagement {
+ repositories {
+ mavenLocal()
+ maven { url "https://repo.spring.io/snapshot" }
+ maven { url "https://repo.spring.io/milestone" }
+ gradlePluginPortal()
+ }
+ plugins {
+ id 'org.springframework.boot' version "${bootVersion}"
+ id "io.spring.dependency-management" version "1.1.3"
+ }
+}
+
+rootProject.name = 'http-client-webclient-gradle'
diff --git a/standalone/webclient/http-client/src/main/java/com/example/loan/Application.java b/standalone/webclient/http-client/src/main/java/com/example/loan/Application.java
new file mode 100644
index 000000000..63645c66f
--- /dev/null
+++ b/standalone/webclient/http-client/src/main/java/com/example/loan/Application.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.loan;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+
+@SpringBootApplication
+@EnableConfigurationProperties(ServiceConfiguration.class)
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+}
diff --git a/standalone/webclient/http-client/src/main/java/com/example/loan/LoanApplicationService.java b/standalone/webclient/http-client/src/main/java/com/example/loan/LoanApplicationService.java
new file mode 100644
index 000000000..0db17a8eb
--- /dev/null
+++ b/standalone/webclient/http-client/src/main/java/com/example/loan/LoanApplicationService.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.loan;
+
+import com.example.loan.model.FraudCheckStatus;
+import com.example.loan.model.FraudServiceRequest;
+import com.example.loan.model.FraudServiceResponse;
+import com.example.loan.model.LoanApplication;
+import com.example.loan.model.LoanApplicationResult;
+import com.example.loan.model.LoanApplicationStatus;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestTemplate;
+
+@Service
+public class LoanApplicationService {
+
+ private static final String FRAUD_SERVICE_JSON_VERSION_1 = "application/vnd.fraud.v1+json";
+
+ private final RestTemplate restTemplate;
+
+ private final ServiceConfiguration serviceConfiguration;
+
+ public LoanApplicationService(ServiceConfiguration serviceConfiguration) {
+ this.restTemplate = new RestTemplate();
+ this.serviceConfiguration = serviceConfiguration;
+ }
+
+ public LoanApplicationResult loanApplication(LoanApplication loanApplication) {
+ FraudServiceRequest request = new FraudServiceRequest(loanApplication);
+
+ FraudServiceResponse response = sendRequestToFraudDetectionService(request);
+
+ return buildResponseFromFraudResult(response);
+ }
+
+ private FraudServiceResponse sendRequestToFraudDetectionService(
+ FraudServiceRequest request) {
+ HttpHeaders httpHeaders = new HttpHeaders();
+ httpHeaders.add(HttpHeaders.CONTENT_TYPE, FRAUD_SERVICE_JSON_VERSION_1);
+
+ // tag::client_call_server[]
+ ResponseEntity response = this.restTemplate.exchange(
+ "http://localhost:" + getPort() + "/fraudcheck", HttpMethod.PUT,
+ new HttpEntity<>(request, httpHeaders), FraudServiceResponse.class);
+ // end::client_call_server[]
+
+ return response.getBody();
+ }
+
+ private LoanApplicationResult buildResponseFromFraudResult(
+ FraudServiceResponse response) {
+ LoanApplicationStatus applicationStatus = null;
+ if (FraudCheckStatus.OK == response.getFraudCheckStatus()) {
+ applicationStatus = LoanApplicationStatus.LOAN_APPLIED;
+ }
+ else if (FraudCheckStatus.FRAUD == response.getFraudCheckStatus()) {
+ applicationStatus = LoanApplicationStatus.LOAN_APPLICATION_REJECTED;
+ }
+
+ return new LoanApplicationResult(applicationStatus,
+ response.getRejectionReason());
+ }
+
+ public int getPort() {
+ return this.serviceConfiguration.getPort();
+ }
+
+ public void setPort(int port) {
+ this.serviceConfiguration.setPort(port);
+ }
+
+}
+
+@ConfigurationProperties("service")
+class ServiceConfiguration {
+
+ private int port = 8080;
+
+ public int getPort() {
+ return port;
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
+}
\ No newline at end of file
diff --git a/standalone/webclient/http-client/src/main/java/com/example/loan/model/Client.java b/standalone/webclient/http-client/src/main/java/com/example/loan/model/Client.java
new file mode 100644
index 000000000..2c2c8b8d8
--- /dev/null
+++ b/standalone/webclient/http-client/src/main/java/com/example/loan/model/Client.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.loan.model;
+
+public class Client {
+
+ private String pesel;
+
+ public Client() {
+ }
+
+ public Client(String pesel) {
+ this.pesel = pesel;
+ }
+
+ public String getPesel() {
+ return this.pesel;
+ }
+
+ public void setPesel(String pesel) {
+ this.pesel = pesel;
+ }
+
+}
diff --git a/standalone/webclient/http-client/src/main/java/com/example/loan/model/FraudCheckStatus.java b/standalone/webclient/http-client/src/main/java/com/example/loan/model/FraudCheckStatus.java
new file mode 100644
index 000000000..01f296911
--- /dev/null
+++ b/standalone/webclient/http-client/src/main/java/com/example/loan/model/FraudCheckStatus.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.loan.model;
+
+public enum FraudCheckStatus {
+
+ OK, FRAUD
+
+}
diff --git a/standalone/webclient/http-client/src/main/java/com/example/loan/model/FraudServiceRequest.java b/standalone/webclient/http-client/src/main/java/com/example/loan/model/FraudServiceRequest.java
new file mode 100644
index 000000000..e4e63590b
--- /dev/null
+++ b/standalone/webclient/http-client/src/main/java/com/example/loan/model/FraudServiceRequest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.loan.model;
+
+import java.math.BigDecimal;
+
+public class FraudServiceRequest {
+
+ private String clientId;
+
+ private BigDecimal loanAmount;
+
+ public FraudServiceRequest() {
+ }
+
+ public FraudServiceRequest(LoanApplication loanApplication) {
+ this.clientId = loanApplication.getClient().getPesel();
+ this.loanAmount = loanApplication.getAmount();
+ }
+
+ public String getClientId() {
+ return this.clientId;
+ }
+
+ public void setClientId(String clientId) {
+ this.clientId = clientId;
+ }
+
+ public BigDecimal getLoanAmount() {
+ return this.loanAmount;
+ }
+
+ public void setLoanAmount(BigDecimal loanAmount) {
+ this.loanAmount = loanAmount;
+ }
+
+}
diff --git a/standalone/webclient/http-client/src/main/java/com/example/loan/model/FraudServiceResponse.java b/standalone/webclient/http-client/src/main/java/com/example/loan/model/FraudServiceResponse.java
new file mode 100644
index 000000000..4ca6dfc62
--- /dev/null
+++ b/standalone/webclient/http-client/src/main/java/com/example/loan/model/FraudServiceResponse.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.loan.model;
+
+public class FraudServiceResponse {
+
+ private FraudCheckStatus fraudCheckStatus;
+
+ private String rejectionReason;
+
+ public FraudServiceResponse() {
+ }
+
+ public FraudCheckStatus getFraudCheckStatus() {
+ return this.fraudCheckStatus;
+ }
+
+ public void setFraudCheckStatus(FraudCheckStatus fraudCheckStatus) {
+ this.fraudCheckStatus = fraudCheckStatus;
+ }
+
+ public String getRejectionReason() {
+ return this.rejectionReason;
+ }
+
+ public void setRejectionReason(String rejectionReason) {
+ this.rejectionReason = rejectionReason;
+ }
+
+}
diff --git a/standalone/webclient/http-client/src/main/java/com/example/loan/model/LoanApplication.java b/standalone/webclient/http-client/src/main/java/com/example/loan/model/LoanApplication.java
new file mode 100644
index 000000000..54ae63b0f
--- /dev/null
+++ b/standalone/webclient/http-client/src/main/java/com/example/loan/model/LoanApplication.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.loan.model;
+
+import java.math.BigDecimal;
+
+public class LoanApplication {
+
+ private Client client;
+
+ private BigDecimal amount;
+
+ private String loanApplicationId;
+
+ public LoanApplication() {
+ }
+
+ public LoanApplication(Client client, double amount) {
+ this.client = client;
+ this.amount = BigDecimal.valueOf(amount);
+ }
+
+ public Client getClient() {
+ return this.client;
+ }
+
+ public void setClient(Client client) {
+ this.client = client;
+ }
+
+ public BigDecimal getAmount() {
+ return this.amount;
+ }
+
+ public void setAmount(BigDecimal amount) {
+ this.amount = amount;
+ }
+
+ public String getLoanApplicationId() {
+ return this.loanApplicationId;
+ }
+
+ public void setLoanApplicationId(String loanApplicationId) {
+ this.loanApplicationId = loanApplicationId;
+ }
+
+}
diff --git a/standalone/webclient/http-client/src/main/java/com/example/loan/model/LoanApplicationResult.java b/standalone/webclient/http-client/src/main/java/com/example/loan/model/LoanApplicationResult.java
new file mode 100644
index 000000000..0850c0af0
--- /dev/null
+++ b/standalone/webclient/http-client/src/main/java/com/example/loan/model/LoanApplicationResult.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.loan.model;
+
+public class LoanApplicationResult {
+
+ private LoanApplicationStatus loanApplicationStatus;
+
+ private String rejectionReason;
+
+ public LoanApplicationResult() {
+ }
+
+ public LoanApplicationResult(LoanApplicationStatus loanApplicationStatus,
+ String rejectionReason) {
+ this.loanApplicationStatus = loanApplicationStatus;
+ this.rejectionReason = rejectionReason;
+ }
+
+ public LoanApplicationStatus getLoanApplicationStatus() {
+ return this.loanApplicationStatus;
+ }
+
+ public void setLoanApplicationStatus(LoanApplicationStatus loanApplicationStatus) {
+ this.loanApplicationStatus = loanApplicationStatus;
+ }
+
+ public String getRejectionReason() {
+ return this.rejectionReason;
+ }
+
+ public void setRejectionReason(String rejectionReason) {
+ this.rejectionReason = rejectionReason;
+ }
+
+}
diff --git a/standalone/webclient/http-client/src/main/java/com/example/loan/model/LoanApplicationStatus.java b/standalone/webclient/http-client/src/main/java/com/example/loan/model/LoanApplicationStatus.java
new file mode 100644
index 000000000..5afde21af
--- /dev/null
+++ b/standalone/webclient/http-client/src/main/java/com/example/loan/model/LoanApplicationStatus.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.loan.model;
+
+public enum LoanApplicationStatus {
+
+ LOAN_APPLIED, LOAN_APPLICATION_REJECTED
+
+}
diff --git a/standalone/webclient/http-client/src/main/resources/application.yml b/standalone/webclient/http-client/src/main/resources/application.yml
new file mode 100644
index 000000000..056c802c7
--- /dev/null
+++ b/standalone/webclient/http-client/src/main/resources/application.yml
@@ -0,0 +1,5 @@
+server.port: 8097
+logging:
+ level:
+ org.springframework.web.client: debug
+ com.github.tomakehurst.wiremock: trace
\ No newline at end of file
diff --git a/standalone/webclient/http-client/src/test/java/com/example/loan/LoanApplicationServiceTests.java b/standalone/webclient/http-client/src/test/java/com/example/loan/LoanApplicationServiceTests.java
new file mode 100644
index 000000000..ebd91253a
--- /dev/null
+++ b/standalone/webclient/http-client/src/test/java/com/example/loan/LoanApplicationServiceTests.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.loan;
+
+import java.nio.charset.Charset;
+
+import com.example.loan.model.Client;
+import com.example.loan.model.LoanApplication;
+import com.example.loan.model.LoanApplicationResult;
+import com.example.loan.model.LoanApplicationStatus;
+import com.github.tomakehurst.wiremock.WireMockServer;
+import com.github.tomakehurst.wiremock.stubbing.StubMapping;
+import org.junit.jupiter.api.Test;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock;
+import org.springframework.core.io.Resource;
+
+import org.springframework.util.StreamUtils;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+
+@SpringBootTest(properties = "service.port=${wiremock.server.port}")
+@AutoConfigureWireMock(port = 0)
+public class LoanApplicationServiceTests {
+
+ @Autowired
+ private LoanApplicationService service;
+
+ @Value("classpath:META-INF/com.example/http-server-webclient/0.0.1/mappings/markClientAsFraud.json")
+ private Resource markClientAsFraud;
+
+ @Value("classpath:META-INF/com.example/http-server-webclient/0.0.1/mappings/markClientAsNotFraud.json")
+ private Resource markClientAsNotFraud;
+
+ @Autowired
+ private WireMockServer server;
+
+ @Test
+ public void shouldSuccessfullyApplyForLoan() throws Exception {
+ this.server.addStubMapping(StubMapping.buildFrom(StreamUtils.copyToString(
+ this.markClientAsNotFraud.getInputStream(), Charset.forName("UTF-8"))));
+ // given:
+ LoanApplication application = new LoanApplication(new Client("1234567890"),
+ 123.123);
+ // when:
+ LoanApplicationResult loanApplication = this.service.loanApplication(application);
+ // then:
+ assertThat(loanApplication.getLoanApplicationStatus())
+ .isEqualTo(LoanApplicationStatus.LOAN_APPLIED);
+ assertThat(loanApplication.getRejectionReason()).isNull();
+ }
+
+ @Test
+ public void shouldBeRejectedDueToAbnormalLoanAmount() throws Exception {
+ this.server.addStubMapping(StubMapping.buildFrom(StreamUtils.copyToString(
+ this.markClientAsFraud.getInputStream(), Charset.forName("UTF-8"))));
+ // given:
+ LoanApplication application = new LoanApplication(new Client("1234567890"),
+ 99999);
+ // when:
+ LoanApplicationResult loanApplication = this.service.loanApplication(application);
+ // then:
+ assertThat(loanApplication.getLoanApplicationStatus())
+ .isEqualTo(LoanApplicationStatus.LOAN_APPLICATION_REJECTED);
+ assertThat(loanApplication.getRejectionReason()).isEqualTo("Amount too high");
+ }
+
+}
diff --git a/standalone/webclient/http-client/src/test/java/com/example/loan/LoanApplicationServiceusingStubRunnerGradleTests.java b/standalone/webclient/http-client/src/test/java/com/example/loan/LoanApplicationServiceusingStubRunnerGradleTests.java
new file mode 100644
index 000000000..e75bbbae9
--- /dev/null
+++ b/standalone/webclient/http-client/src/test/java/com/example/loan/LoanApplicationServiceusingStubRunnerGradleTests.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.loan;
+
+import com.example.loan.model.Client;
+import com.example.loan.model.LoanApplication;
+import com.example.loan.model.LoanApplicationResult;
+import com.example.loan.model.LoanApplicationStatus;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner;
+
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+
+@SpringBootTest
+@AutoConfigureStubRunner(ids = "com.example:http-server-webclient")
+public class LoanApplicationServiceusingStubRunnerGradleTests {
+
+ @Autowired
+ LoanApplicationService service;
+
+ @Value("${stubrunner.runningstubs.http-server-webclient.port}")
+ int port;
+
+ @BeforeEach
+ public void setup() {
+ this.service.setPort(this.port);
+ }
+
+ @Test
+ public void shouldSuccessfullyApplyForLoan() throws Exception {
+ // given
+ LoanApplication application = new LoanApplication(new Client("1234567890"),
+ 123.123);
+ // when:
+ LoanApplicationResult loanApplication = this.service.loanApplication(application);
+ // then:
+ assertThat(loanApplication.getLoanApplicationStatus())
+ .isEqualTo(LoanApplicationStatus.LOAN_APPLIED);
+ assertThat(loanApplication.getRejectionReason()).isNull();
+ }
+
+ @Test
+ public void shouldBeRejectedDueToAbnormalLoanAmount() throws Exception {
+ // given:
+ LoanApplication application = new LoanApplication(new Client("1234567890"),
+ 99999);
+ // when:
+ LoanApplicationResult loanApplication = this.service.loanApplication(application);
+ // then:
+ assertThat(loanApplication.getLoanApplicationStatus())
+ .isEqualTo(LoanApplicationStatus.LOAN_APPLICATION_REJECTED);
+ assertThat(loanApplication.getRejectionReason()).isEqualTo("Amount too high");
+ }
+
+}
diff --git a/standalone/webclient/http-client/src/test/java/com/example/loan/LoanApplicationServiceusingStubRunnerTests.java b/standalone/webclient/http-client/src/test/java/com/example/loan/LoanApplicationServiceusingStubRunnerTests.java
new file mode 100644
index 000000000..e1c1c13ec
--- /dev/null
+++ b/standalone/webclient/http-client/src/test/java/com/example/loan/LoanApplicationServiceusingStubRunnerTests.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.loan;
+
+import com.example.loan.model.Client;
+import com.example.loan.model.LoanApplication;
+import com.example.loan.model.LoanApplicationResult;
+import com.example.loan.model.LoanApplicationStatus;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner;
+
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+
+@SpringBootTest
+@AutoConfigureStubRunner(ids = "com.example:http-server-webclient")
+public class LoanApplicationServiceusingStubRunnerTests {
+
+ @Autowired
+ LoanApplicationService service;
+
+ @Value("${stubrunner.runningstubs.http-server-webclient.port}")
+ int port;
+
+ @BeforeEach
+ public void setup() {
+ this.service.setPort(this.port);
+ }
+
+ @Test
+ public void shouldSuccessfullyApplyForLoan() throws Exception {
+ // given
+ LoanApplication application = new LoanApplication(new Client("1234567890"),
+ 123.123);
+ // when:
+ LoanApplicationResult loanApplication = this.service.loanApplication(application);
+ // then:
+ assertThat(loanApplication.getLoanApplicationStatus())
+ .isEqualTo(LoanApplicationStatus.LOAN_APPLIED);
+ assertThat(loanApplication.getRejectionReason()).isNull();
+ }
+
+ @Test
+ public void shouldBeRejectedDueToAbnormalLoanAmount() throws Exception {
+ // given:
+ LoanApplication application = new LoanApplication(new Client("1234567890"),
+ 99999);
+ // when:
+ LoanApplicationResult loanApplication = this.service.loanApplication(application);
+ // then:
+ assertThat(loanApplication.getLoanApplicationStatus())
+ .isEqualTo(LoanApplicationStatus.LOAN_APPLICATION_REJECTED);
+ assertThat(loanApplication.getRejectionReason()).isEqualTo("Amount too high");
+ }
+
+}
diff --git a/standalone/webclient/http-client/src/test/resources/application-gradle.yaml b/standalone/webclient/http-client/src/test/resources/application-gradle.yaml
new file mode 100644
index 000000000..085483afa
--- /dev/null
+++ b/standalone/webclient/http-client/src/test/resources/application-gradle.yaml
@@ -0,0 +1,2 @@
+stubrunner:
+ stubs.ids: 'com.example:http-server-webclient'
diff --git a/standalone/webclient/http-server/.gitignore b/standalone/webclient/http-server/.gitignore
new file mode 100644
index 000000000..b05ba7bd6
--- /dev/null
+++ b/standalone/webclient/http-server/.gitignore
@@ -0,0 +1,6 @@
+
+target/
+
+.gradle
+build/
+
diff --git a/standalone/webclient/http-server/.mvn/jvm.config b/standalone/webclient/http-server/.mvn/jvm.config
new file mode 100644
index 000000000..0e7dabeff
--- /dev/null
+++ b/standalone/webclient/http-server/.mvn/jvm.config
@@ -0,0 +1 @@
+-Xmx1024m -XX:CICompilerCount=1 -XX:TieredStopAtLevel=1 -Djava.security.egd=file:/dev/./urandom
\ No newline at end of file
diff --git a/standalone/webclient/http-server/.mvn/maven.config b/standalone/webclient/http-server/.mvn/maven.config
new file mode 100644
index 000000000..a68299056
--- /dev/null
+++ b/standalone/webclient/http-server/.mvn/maven.config
@@ -0,0 +1 @@
+-P spring
diff --git a/standalone/webclient/http-server/.mvn/wrapper/MavenWrapperDownloader.java b/standalone/webclient/http-server/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 000000000..b901097f2
--- /dev/null
+++ b/standalone/webclient/http-server/.mvn/wrapper/MavenWrapperDownloader.java
@@ -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();
+ }
+
+}
diff --git a/standalone/webclient/http-server/.mvn/wrapper/maven-wrapper.jar b/standalone/webclient/http-server/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 000000000..c1dd12f17
Binary files /dev/null and b/standalone/webclient/http-server/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/standalone/webclient/http-server/.mvn/wrapper/maven-wrapper.properties b/standalone/webclient/http-server/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 000000000..015dfe682
--- /dev/null
+++ b/standalone/webclient/http-server/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,18 @@
+# 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.
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.3/apache-maven-3.8.3-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar
diff --git a/standalone/webclient/http-server/README.adoc b/standalone/webclient/http-server/README.adoc
new file mode 100644
index 000000000..2fd3fbc40
--- /dev/null
+++ b/standalone/webclient/http-server/README.adoc
@@ -0,0 +1,20 @@
+= Http Server
+
+Run
+
+[source=groovy]
+--------
+./gradlew clean build publishToMavenLocal
+--------
+
+or
+
+--------
+./mvnw clean install
+--------
+
+To
+
+- build the app
+- generate and run Spring Cloud Contract Verifier tests
+- publish the fatJar and the stubs to Maven Local
\ No newline at end of file
diff --git a/standalone/webclient/http-server/build.gradle b/standalone/webclient/http-server/build.gradle
new file mode 100644
index 000000000..7a7626589
--- /dev/null
+++ b/standalone/webclient/http-server/build.gradle
@@ -0,0 +1,128 @@
+plugins {
+ id "groovy"
+ id "org.springframework.boot"
+ id "io.spring.dependency-management"
+ id "maven-publish"
+ /**
+ * While the SCC Gradle plugin is not strictly necessary for this project.
+ * It is included to ensure that if the contractDslDir does not exist, then
+ * the plugin reports "NO-SOURCE" for associated tasks, rather than resulting
+ * in an error for the end user.
+ */
+ id "org.springframework.cloud.contract"
+}
+
+group = 'com.example'
+version = '0.0.1'
+
+repositories {
+ mavenCentral()
+ mavenLocal()
+ maven { url "https://repo.spring.io/snapshot" }
+ maven { url "https://repo.spring.io/milestone" }
+}
+
+dependencyManagement {
+ imports {
+ mavenBom "org.springframework.cloud:spring-cloud-contract-dependencies:${verifierVersion}"
+ }
+}
+
+dependencies {
+ implementation("org.springframework.boot:spring-boot-starter-webflux")
+ implementation("org.springframework.boot:spring-boot-starter-actuator")
+
+ testImplementation('org.springframework.boot:spring-boot-starter-test') {
+ exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
+ }
+ testImplementation 'org.springframework.restdocs:spring-restdocs-webtestclient'
+ testImplementation 'org.springframework.cloud:spring-cloud-contract-wiremock'
+}
+
+contracts {
+ failOnNoContracts = false
+}
+
+generateClientStubs.enabled = false
+
+test {
+ useJUnitPlatform()
+ systemProperty 'spring.profiles.active', 'gradle'
+ testLogging {
+ exceptionFormat = 'full'
+ }
+ afterSuite { desc, result ->
+ if (!desc.parent) {
+ println "Results: (${result.testCount} tests, ${result.successfulTestCount} successes, ${result.failedTestCount} failures, ${result.skippedTestCount} skipped)"
+ if (result.testCount == 0) {
+ throw new IllegalStateException("No tests were found. Failing the build")
+ }
+ }
+ }
+}
+
+task stubsJar(type: Jar, dependsOn: ['copySnippets', 'copySources', 'copyClasses']) {
+ archiveBaseName = project.name
+ archiveClassifier = 'stubs'
+ from project.file("${project.buildDir}/stubs")
+}
+
+task copySnippets(type: Copy, dependsOn: test) {
+ from "target/snippets/stubs"
+ into "${project.buildDir}/stubs/META-INF/${project.group}/${project.name}/${project.version}/mappings"
+}
+
+task copySources(type: Copy) {
+ from "src/main/java"
+ include '**/model/Fraud*.*'
+ into "${project.buildDir}/stubs/"
+}
+
+task copyClasses(type: Copy) {
+ from "${project.buildDir}/classes/main/"
+ include '**/model/Fraud*.*'
+ into "${project.buildDir}/stubs/"
+}
+
+project.tasks.named("verifierStubsJar").get().dependsOn('copySnippets', 'copySources', 'stubsJar') // TODO: We need to fix this
+project.tasks.named("copyContracts").get().dependsOn('stubsJar') // TODO: We need to fix this
+afterEvaluate {
+ project.tasks.matching { it.name.contains("publish") }.each { it.dependsOn('verifierStubsJar') } // TODO: We need to fix this
+}
+
+publishing {
+ publications {
+ maven(MavenPublication) {
+ artifact bootJar
+ artifact stubsJar
+
+ // https://github.com/spring-gradle-plugins/dependency-management-plugin/issues/273
+ versionMapping {
+ usage("java-api") {
+ fromResolutionOf("runtimeClasspath")
+ }
+ usage("java-runtime") {
+ fromResolutionResult()
+ }
+ }
+ }
+ }
+}
+
+clean.doFirst {
+ delete 'target/snippets/stubs'
+ delete "~/.m2/repository/com/example/http-server-webclient-gradle"
+}
+
+task resolveDependencies {
+ doLast {
+ project.rootProject.allprojects.each { subProject ->
+ subProject.buildscript.configurations.each { configuration ->
+ configuration.resolve()
+ }
+ subProject.configurations.each { configuration ->
+ configuration.resolve()
+ }
+ }
+ }
+}
diff --git a/standalone/webclient/http-server/gradle.properties b/standalone/webclient/http-server/gradle.properties
new file mode 100644
index 000000000..1baaf2d82
--- /dev/null
+++ b/standalone/webclient/http-server/gradle.properties
@@ -0,0 +1,3 @@
+org.gradle.daemon=false
+verifierVersion=4.1.5-SNAPSHOT
+bootVersion=3.2.7
\ No newline at end of file
diff --git a/standalone/webclient/http-server/gradle/wrapper/gradle-wrapper.jar b/standalone/webclient/http-server/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 000000000..7f93135c4
Binary files /dev/null and b/standalone/webclient/http-server/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/standalone/webclient/http-server/gradle/wrapper/gradle-wrapper.properties b/standalone/webclient/http-server/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 000000000..ac72c34e8
--- /dev/null
+++ b/standalone/webclient/http-server/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,7 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
+networkTimeout=10000
+validateDistributionUrl=true
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/standalone/webclient/http-server/gradlew b/standalone/webclient/http-server/gradlew
new file mode 100755
index 000000000..0adc8e1a5
--- /dev/null
+++ b/standalone/webclient/http-server/gradlew
@@ -0,0 +1,249 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original 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 POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
+done
+
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+ echo "$*"
+} >&2
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+} >&2
+
+# 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 ;; #(
+ MSYS* | 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
+ if ! command -v java >/dev/null 2>&1
+ then
+ 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
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC3045
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC3045
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+
+# 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"'
+
+# Collect all arguments for the java command;
+# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+# shell script including quotes and variable substitutions, so put them in
+# double quotes to make sure that they get re-expanded; and
+# * put everything else in single quotes, so that it's not re-expanded.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+ die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/standalone/webclient/http-server/gradlew.bat b/standalone/webclient/http-server/gradlew.bat
new file mode 100644
index 000000000..93e3f59f1
--- /dev/null
+++ b/standalone/webclient/http-server/gradlew.bat
@@ -0,0 +1,92 @@
+@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=.
+@rem This is normally unused
+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% equ 0 goto execute
+
+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 execute
+
+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
+
+: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 %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if %ERRORLEVEL% equ 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!
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/standalone/webclient/http-server/mvnw b/standalone/webclient/http-server/mvnw
new file mode 100755
index 000000000..5643201c7
--- /dev/null
+++ b/standalone/webclient/http-server/mvnw
@@ -0,0 +1,316 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# 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 /usr/local/etc/mavenrc ] ; then
+ . /usr/local/etc/mavenrc
+ fi
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ export JAVA_HOME="`/usr/libexec/java_home`"
+ else
+ export JAVA_HOME="/Library/Java/Home"
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=`java-config --jre-home`
+ fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+ ## resolve links - $0 may be a link to maven's home
+ PRG="$0"
+
+ # need this for relative symlinks
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG="`dirname "$PRG"`/$link"
+ fi
+ done
+
+ saveddir=`pwd`
+
+ M2_HOME=`dirname "$PRG"`/..
+
+ # make it fully qualified
+ M2_HOME=`cd "$M2_HOME" && pwd`
+
+ cd "$saveddir"
+ # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --unix "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME="`(cd "$M2_HOME"; pwd)`"
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="`which javac`"
+ if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=`which readlink`
+ if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+ if $darwin ; then
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+ else
+ javaExecutable="`readlink -f \"$javaExecutable\"`"
+ fi
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="`\\unset -f command; \\command -v java`"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=`cd "$wdir/.."; pwd`
+ fi
+ # end of workaround
+ done
+ echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ echo "$(tr -s '\n' ' ' < "$1")"
+ fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found .mvn/wrapper/maven-wrapper.jar"
+ fi
+else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+ fi
+ if [ -n "$MVNW_REPOURL" ]; then
+ jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+ else
+ jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+ fi
+ while IFS="=" read key value; do
+ case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
+ esac
+ done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Downloading from: $jarUrl"
+ fi
+ wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+ if $cygwin; then
+ wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
+ fi
+
+ if command -v wget > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found wget ... using wget"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ else
+ wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ fi
+ elif command -v curl > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found curl ... using curl"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl -o "$wrapperJarPath" "$jarUrl" -f
+ else
+ curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
+ fi
+
+ else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Falling back to using Java to download"
+ fi
+ javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaClass=`cygpath --path --windows "$javaClass"`
+ fi
+ if [ -e "$javaClass" ]; then
+ if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Compiling MavenWrapperDownloader.java ..."
+ fi
+ # Compiling the Java class
+ ("$JAVA_HOME/bin/javac" "$javaClass")
+ fi
+ if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ # Running the downloader
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Running MavenWrapperDownloader.java ..."
+ fi
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+if [ "$MVNW_VERBOSE" = true ]; then
+ echo $MAVEN_PROJECTBASEDIR
+fi
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --path --windows "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ $MAVEN_DEBUG_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.home=${M2_HOME}" \
+ "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/standalone/webclient/http-server/mvnw.cmd b/standalone/webclient/http-server/mvnw.cmd
new file mode 100644
index 000000000..8a15b7f31
--- /dev/null
+++ b/standalone/webclient/http-server/mvnw.cmd
@@ -0,0 +1,188 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM 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 "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
+if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Found %WRAPPER_JAR%
+ )
+) else (
+ if not "%MVNW_REPOURL%" == "" (
+ SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+ )
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %DOWNLOAD_URL%
+ )
+
+ powershell -Command "&{"^
+ "$webclient = new-object System.Net.WebClient;"^
+ "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+ "}"^
+ "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
+ "}"
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Finished downloading %WRAPPER_JAR%
+ )
+)
+@REM End of extension
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% ^
+ %JVM_CONFIG_MAVEN_PROPS% ^
+ %MAVEN_OPTS% ^
+ %MAVEN_DEBUG_OPTS% ^
+ -classpath %WRAPPER_JAR% ^
+ "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
+ %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
+if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%"=="on" pause
+
+if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
+
+cmd /C exit /B %ERROR_CODE%
diff --git a/standalone/webclient/http-server/pom.xml b/standalone/webclient/http-server/pom.xml
new file mode 100644
index 000000000..3388c1bee
--- /dev/null
+++ b/standalone/webclient/http-server/pom.xml
@@ -0,0 +1,241 @@
+
+
+ 4.0.0
+
+ com.example
+ http-server-webclient
+ 0.0.1
+
+ Spring Cloud Contract RestDocs Http Server Sample
+ Spring Cloud RestDocs Verifier Http Server Sample
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.2.7
+
+
+
+
+ UTF-8
+ 17
+ 4.1.5-SNAPSHOT
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-webflux
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.junit.vintage
+ junit-vintage-engine
+
+
+
+
+
+ org.springframework.restdocs
+ spring-restdocs-webtestclient
+ test
+
+
+ org.springframework.cloud
+ spring-cloud-contract-wiremock
+ test
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-contract-dependencies
+ ${spring-cloud-contract.version}
+ pom
+ import
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ maven-deploy-plugin
+
+ true
+
+
+
+ org.apache.maven.plugins
+ maven-clean-plugin
+
+
+
+ build
+
+
+ target
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-assembly-plugin
+
+
+ stub
+ prepare-package
+
+ single
+
+ false
+
+ true
+
+ ${basedir}/src/assembly/stub.xml
+
+
+
+
+
+
+ maven-surefire-plugin
+
+ true
+
+
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
+
+
+ windows
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 1.6.0
+
+
+ gradle
+ test
+
+ gradlew.bat
+
+ clean
+ build
+
+ install
+
+ -x
+ test
+
+ -x
+ contractTest
+
+ -PverifierVersion=${spring-cloud-contract.version}
+
+
+
+
+ exec
+
+
+
+
+
+
+
+
+
diff --git a/standalone/webclient/http-server/settings.gradle b/standalone/webclient/http-server/settings.gradle
new file mode 100644
index 000000000..e3747344a
--- /dev/null
+++ b/standalone/webclient/http-server/settings.gradle
@@ -0,0 +1,22 @@
+pluginManagement {
+ repositories {
+ mavenLocal()
+ maven { url "https://repo.spring.io/snapshot" }
+ maven { url "https://repo.spring.io/milestone" }
+ gradlePluginPortal()
+ }
+ plugins {
+ id 'org.springframework.boot' version "${bootVersion}"
+ id "io.spring.dependency-management" version "1.1.3"
+ }
+ resolutionStrategy {
+ eachPlugin {
+ // protects us in case the gradle-portal-plugin hasn't yet been published by Maven
+ if (requested.id.id == 'org.springframework.cloud.contract') {
+ useModule("org.springframework.cloud:spring-cloud-contract-gradle-plugin:${verifierVersion}")
+ }
+ }
+ }
+}
+
+rootProject.name = 'http-server-webclient-gradle'
diff --git a/standalone/webclient/http-server/src/assembly/stub.xml b/standalone/webclient/http-server/src/assembly/stub.xml
new file mode 100644
index 000000000..13bdf69ce
--- /dev/null
+++ b/standalone/webclient/http-server/src/assembly/stub.xml
@@ -0,0 +1,35 @@
+
+ stubs
+
+ jar
+
+ false
+
+
+ src/main/java
+ /
+
+ **/model/Fraud*.*
+
+
+
+ ${project.build.directory}/classes
+ /
+
+ **/model/Fraud*.*
+
+
+
+ ${project.build.directory}/snippets/stubs
+
+ META-INF/${project.groupId}/${project.artifactId}/${project.version}/mappings
+
+
+ **/*
+
+
+
+
diff --git a/standalone/webclient/http-server/src/main/java/com/example/fraud/Application.java b/standalone/webclient/http-server/src/main/java/com/example/fraud/Application.java
new file mode 100644
index 000000000..c998b507b
--- /dev/null
+++ b/standalone/webclient/http-server/src/main/java/com/example/fraud/Application.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.fraud;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@EnableAutoConfiguration
+@ComponentScan
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+}
diff --git a/standalone/webclient/http-server/src/main/java/com/example/fraud/FraudDetectionController.java b/standalone/webclient/http-server/src/main/java/com/example/fraud/FraudDetectionController.java
new file mode 100644
index 000000000..1d5469e93
--- /dev/null
+++ b/standalone/webclient/http-server/src/main/java/com/example/fraud/FraudDetectionController.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.fraud;
+
+import java.math.BigDecimal;
+
+import com.example.fraud.model.FraudCheck;
+import com.example.fraud.model.FraudCheckResult;
+import com.example.fraud.model.FraudCheckStatus;
+
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import static org.springframework.web.bind.annotation.RequestMethod.PUT;
+
+@RestController
+public class FraudDetectionController {
+
+ private static final String FRAUD_SERVICE_JSON_VERSION_1 = "application/vnd.fraud.v1+json";
+
+ private static final String NO_REASON = null;
+
+ private static final String AMOUNT_TOO_HIGH = "Amount too high";
+
+ private static final BigDecimal MAX_AMOUNT = new BigDecimal("5000");
+
+ // tag::server_api[]
+ @RequestMapping(value = "/fraudcheck", method = PUT, consumes = FRAUD_SERVICE_JSON_VERSION_1, produces = FRAUD_SERVICE_JSON_VERSION_1)
+ public FraudCheckResult fraudCheck(@RequestBody FraudCheck fraudCheck) {
+ // end::server_api[]
+ // tag::new_impl[]
+ if (amountGreaterThanThreshold(fraudCheck)) {
+ return new FraudCheckResult(FraudCheckStatus.FRAUD, AMOUNT_TOO_HIGH);
+ }
+ // end::new_impl[]
+ // tag::initial_impl[]
+ return new FraudCheckResult(FraudCheckStatus.OK, NO_REASON);
+ // end::initial_impl[]
+ }
+
+ private boolean amountGreaterThanThreshold(FraudCheck fraudCheck) {
+ return MAX_AMOUNT.compareTo(fraudCheck.getLoanAmount()) < 0;
+ }
+
+}
diff --git a/standalone/webclient/http-server/src/main/java/com/example/fraud/model/FraudCheck.java b/standalone/webclient/http-server/src/main/java/com/example/fraud/model/FraudCheck.java
new file mode 100644
index 000000000..4cf6ae3ea
--- /dev/null
+++ b/standalone/webclient/http-server/src/main/java/com/example/fraud/model/FraudCheck.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.fraud.model;
+
+import java.math.BigDecimal;
+
+public class FraudCheck {
+
+ private String clientId;
+
+ private BigDecimal loanAmount;
+
+ public FraudCheck() {
+ }
+
+ public String getClientId() {
+ return clientId;
+ }
+
+ public void setClientId(String clientId) {
+ this.clientId = clientId;
+ }
+
+ public BigDecimal getLoanAmount() {
+ return loanAmount;
+ }
+
+ public void setLoanAmount(BigDecimal loanAmount) {
+ this.loanAmount = loanAmount;
+ }
+
+}
diff --git a/standalone/webclient/http-server/src/main/java/com/example/fraud/model/FraudCheckResult.java b/standalone/webclient/http-server/src/main/java/com/example/fraud/model/FraudCheckResult.java
new file mode 100644
index 000000000..95440c679
--- /dev/null
+++ b/standalone/webclient/http-server/src/main/java/com/example/fraud/model/FraudCheckResult.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.fraud.model;
+
+public class FraudCheckResult {
+
+ private FraudCheckStatus fraudCheckStatus;
+
+ private String rejectionReason;
+
+ public FraudCheckResult() {
+ }
+
+ public FraudCheckResult(FraudCheckStatus fraudCheckStatus, String rejectionReason) {
+ this.fraudCheckStatus = fraudCheckStatus;
+ this.rejectionReason = rejectionReason;
+ }
+
+ public FraudCheckStatus getFraudCheckStatus() {
+ return fraudCheckStatus;
+ }
+
+ public void setFraudCheckStatus(FraudCheckStatus fraudCheckStatus) {
+ this.fraudCheckStatus = fraudCheckStatus;
+ }
+
+ public String getRejectionReason() {
+ return rejectionReason;
+ }
+
+ public void setRejectionReason(String rejectionReason) {
+ this.rejectionReason = rejectionReason;
+ }
+
+}
diff --git a/standalone/webclient/http-server/src/main/java/com/example/fraud/model/FraudCheckStatus.java b/standalone/webclient/http-server/src/main/java/com/example/fraud/model/FraudCheckStatus.java
new file mode 100644
index 000000000..a43b649f5
--- /dev/null
+++ b/standalone/webclient/http-server/src/main/java/com/example/fraud/model/FraudCheckStatus.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.fraud.model;
+
+public enum FraudCheckStatus {
+
+ OK, FRAUD
+
+}
diff --git a/standalone/webclient/http-server/src/main/resources/application.yml b/standalone/webclient/http-server/src/main/resources/application.yml
new file mode 100644
index 000000000..1c421cf2b
--- /dev/null
+++ b/standalone/webclient/http-server/src/main/resources/application.yml
@@ -0,0 +1 @@
+server.port=0
\ No newline at end of file
diff --git a/standalone/webclient/http-server/src/test/java/com/example/fraud/StubGeneratorTests.java b/standalone/webclient/http-server/src/test/java/com/example/fraud/StubGeneratorTests.java
new file mode 100644
index 000000000..42e8074aa
--- /dev/null
+++ b/standalone/webclient/http-server/src/test/java/com/example/fraud/StubGeneratorTests.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2013-2020 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.
+ */
+
+package com.example.fraud;
+
+import java.math.BigDecimal;
+
+import com.example.fraud.model.FraudCheck;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.json.AutoConfigureJsonTesters;
+import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs;
+import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.json.JacksonTester;
+import org.springframework.http.MediaType;
+import org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation;
+import org.springframework.test.web.reactive.server.WebTestClient;
+import org.springframework.web.reactive.function.BodyInserters;
+
+import static org.springframework.cloud.contract.wiremock.restdocs.WireMockWebTestClient.verify;
+
+
+@SpringBootTest(classes = Application.class)
+@AutoConfigureRestDocs(outputDir = "target/snippets")
+@AutoConfigureWebTestClient
+@AutoConfigureJsonTesters
+public class StubGeneratorTests {
+
+ @Autowired
+ private WebTestClient client;
+
+ private JacksonTester json;
+
+ @BeforeEach
+ public void setup() {
+ ObjectMapper objectMappper = new ObjectMapper();
+ // Possibly configure the mapper
+ JacksonTester.initFields(this, objectMappper);
+ }
+
+ @Test
+ public void shouldMarkClientAsFraud() throws Exception {
+ FraudCheck fraudCheck = new FraudCheck();
+ fraudCheck.setClientId("1234567890");
+ fraudCheck.setLoanAmount(BigDecimal.valueOf(99999.0));
+ client.put().uri("/fraudcheck")
+ .contentType(MediaType.valueOf("application/vnd.fraud.v1+json"))
+ .body(BodyInserters.fromObject(json.write(fraudCheck).getJson()))
+ .exchange().expectBody().jsonPath("$.fraudCheckStatus").isEqualTo("FRAUD")
+ .jsonPath("$.rejectionReason").isEqualTo("Amount too high")
+ .consumeWith(verify().jsonPath("$.clientId")
+ .jsonPath("$[?(@.loanAmount > 1000)]")
+ .contentType(MediaType.valueOf("application/vnd.fraud.v1+json")))
+ .consumeWith(
+ WebTestClientRestDocumentation.document("markClientAsFraud"));
+ }
+
+ @Test
+ public void shouldMarkClientAsNotFraud() throws Exception {
+ FraudCheck fraudCheck = new FraudCheck();
+ fraudCheck.setClientId("1234567890");
+ fraudCheck.setLoanAmount(BigDecimal.valueOf(123.123));
+ client.put().uri("/fraudcheck")
+ .contentType(MediaType.valueOf("application/vnd.fraud.v1+json"))
+ .body(BodyInserters.fromObject(json.write(fraudCheck).getJson()))
+ .exchange().expectBody().jsonPath("$.fraudCheckStatus").isEqualTo("OK")
+ .jsonPath("$.rejectionReason").doesNotExist()
+ .consumeWith(verify().jsonPath("$.clientId")
+ .jsonPath("$[?(@.loanAmount <= 1000)]")
+ .contentType(MediaType.valueOf("application/vnd.fraud.v1+json")))
+ .consumeWith(
+ WebTestClientRestDocumentation.document("markClientAsNotFraud"));
+ }
+
+}