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")); + } + +}