diff --git a/samples/standalone/kotlin/http-client/.gitignore b/samples/standalone/kotlin/http-client/.gitignore new file mode 100644 index 0000000000..b05ba7bd6d --- /dev/null +++ b/samples/standalone/kotlin/http-client/.gitignore @@ -0,0 +1,6 @@ + +target/ + +.gradle +build/ + diff --git a/samples/standalone/kotlin/http-client/.mvn/jvm.config b/samples/standalone/kotlin/http-client/.mvn/jvm.config new file mode 100644 index 0000000000..894bef17a5 --- /dev/null +++ b/samples/standalone/kotlin/http-client/.mvn/jvm.config @@ -0,0 +1 @@ +-Xmx1024m -XX:MaxPermSize=256m -Djava.awt.headless=true \ No newline at end of file diff --git a/samples/standalone/kotlin/http-client/.mvn/maven.config b/samples/standalone/kotlin/http-client/.mvn/maven.config new file mode 100644 index 0000000000..affad39a42 --- /dev/null +++ b/samples/standalone/kotlin/http-client/.mvn/maven.config @@ -0,0 +1 @@ +-T2 \ No newline at end of file diff --git a/samples/standalone/kotlin/http-client/.mvn/wrapper/MavenWrapperDownloader.java b/samples/standalone/kotlin/http-client/.mvn/wrapper/MavenWrapperDownloader.java new file mode 100755 index 0000000000..959fea7b14 --- /dev/null +++ b/samples/standalone/kotlin/http-client/.mvn/wrapper/MavenWrapperDownloader.java @@ -0,0 +1,117 @@ + +/* +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. +*/ + +import java.util.Properties; + +public class MavenWrapperDownloader { + + /** + * 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/0.4.0/maven-wrapper-0.4.0.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 direcrory '" + + 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 { + 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/samples/standalone/kotlin/http-client/.mvn/wrapper/maven-wrapper.jar b/samples/standalone/kotlin/http-client/.mvn/wrapper/maven-wrapper.jar new file mode 100755 index 0000000000..08ebbb67f0 Binary files /dev/null and b/samples/standalone/kotlin/http-client/.mvn/wrapper/maven-wrapper.jar differ diff --git a/samples/standalone/kotlin/http-client/.mvn/wrapper/maven-wrapper.properties b/samples/standalone/kotlin/http-client/.mvn/wrapper/maven-wrapper.properties new file mode 100755 index 0000000000..a5fcc11920 --- /dev/null +++ b/samples/standalone/kotlin/http-client/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.5.2/apache-maven-3.5.2-bin.zip \ No newline at end of file diff --git a/samples/standalone/kotlin/http-client/README.adoc b/samples/standalone/kotlin/http-client/README.adoc new file mode 100644 index 0000000000..cdcb0e4a56 --- /dev/null +++ b/samples/standalone/kotlin/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/samples/standalone/kotlin/http-client/build.gradle.kts b/samples/standalone/kotlin/http-client/build.gradle.kts new file mode 100644 index 0000000000..5a4e9c4e8d --- /dev/null +++ b/samples/standalone/kotlin/http-client/build.gradle.kts @@ -0,0 +1,76 @@ +import org.gradle.api.tasks.testing.logging.TestExceptionFormat +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +plugins { + id("org.springframework.boot") version "2.2.0.BUILD-SNAPSHOT" + id("io.spring.dependency-management") version "1.0.7.RELEASE" + kotlin("jvm") version "1.3.41" + kotlin("plugin.spring") version "1.3.41" +} + +group = "com.example" +version = "0.0.1-SNAPSHOT" +java.sourceCompatibility = JavaVersion.VERSION_1_8 + +// tag::deps_repos[] +repositories { + mavenCentral() + mavenLocal() + maven { url = uri("https://repo.spring.io/release") } + maven { url = uri("https://repo.spring.io/milestone") } + maven { url = uri("https://repo.spring.io/snapshot") } +} +// end::deps_repos[] + +// tag::dep_mgmt[] +dependencyManagement { + + val BOM_VERSION: String by project + + imports { + mavenBom("org.springframework.cloud:spring-cloud-dependencies:$BOM_VERSION") + } +} +// end::dep_mgmt[] + +// tag::deps[] +dependencies { + implementation("org.springframework.boot:spring-boot-starter-web") + implementation("com.fasterxml.jackson.module:jackson-module-kotlin") + implementation("org.springframework.boot:spring-boot-starter-actuator") + implementation("org.jetbrains.kotlin:kotlin-reflect") + implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") + testImplementation("org.springframework.cloud:spring-cloud-starter-contract-stub-runner") + // for easier testing of multipart + 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") + exclude(group = "junit", module = "junit") + } +} +// end::deps[] + +tasks.withType { + useJUnitPlatform() + systemProperty("spring.profiles.active", "gradle") + testLogging { + exceptionFormat = TestExceptionFormat.FULL + } + afterSuite(KotlinClosure2({ desc: TestDescriptor, result: TestResult -> + if (desc.parent == null) { + if (result.testCount == 0L) { + throw IllegalStateException("No tests were found. Failing the build") + } + else { + println("Results: (${result.testCount} tests, ${result.successfulTestCount} successes, ${result.failedTestCount} failures, ${result.skippedTestCount} skipped)") + } + } else { /* Nothing to do here */ } + })) +} + +tasks.withType { + kotlinOptions { + freeCompilerArgs = listOf("-Xjsr305=strict") + jvmTarget = "1.8" + } +} diff --git a/samples/standalone/kotlin/http-client/gradle.properties b/samples/standalone/kotlin/http-client/gradle.properties new file mode 100644 index 0000000000..535ecb91d1 --- /dev/null +++ b/samples/standalone/kotlin/http-client/gradle.properties @@ -0,0 +1,2 @@ +org.gradle.daemon=false +BOM_VERSION=Hoxton.BUILD-SNAPSHOT diff --git a/samples/standalone/kotlin/http-client/gradle/wrapper/gradle-wrapper.jar b/samples/standalone/kotlin/http-client/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000..87b738cbd0 Binary files /dev/null and b/samples/standalone/kotlin/http-client/gradle/wrapper/gradle-wrapper.jar differ diff --git a/samples/standalone/kotlin/http-client/gradle/wrapper/gradle-wrapper.properties b/samples/standalone/kotlin/http-client/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000..b0acbdcd73 --- /dev/null +++ b/samples/standalone/kotlin/http-client/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-5.5-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/samples/standalone/kotlin/http-client/gradlew b/samples/standalone/kotlin/http-client/gradlew new file mode 100755 index 0000000000..af6708ff22 --- /dev/null +++ b/samples/standalone/kotlin/http-client/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/samples/standalone/kotlin/http-client/gradlew.bat b/samples/standalone/kotlin/http-client/gradlew.bat new file mode 100644 index 0000000000..0f8d5937c4 --- /dev/null +++ b/samples/standalone/kotlin/http-client/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem 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" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/samples/standalone/kotlin/http-client/mvnw b/samples/standalone/kotlin/http-client/mvnw new file mode 100755 index 0000000000..1d5ace7fc1 --- /dev/null +++ b/samples/standalone/kotlin/http-client/mvnw @@ -0,0 +1,286 @@ +#!/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 + # 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)`" + # TODO classpath? +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`which java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +########################################################################################## +# 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 + jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.0/maven-wrapper-0.4.0.jar" + 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 command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + wget "$jarUrl" -O "$wrapperJarPath" + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + curl -o "$wrapperJarPath" "$jarUrl" + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + 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 + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/samples/standalone/kotlin/http-client/mvnw.cmd b/samples/standalone/kotlin/http-client/mvnw.cmd new file mode 100755 index 0000000000..080c510d2b --- /dev/null +++ b/samples/standalone/kotlin/http-client/mvnw.cmd @@ -0,0 +1,161 @@ +@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 set title of command window +title %0 +@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" +if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.0/maven-wrapper-0.4.0.jar" +FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + echo Found %WRAPPER_JAR% +) else ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')" + echo Finished downloading %WRAPPER_JAR% +) +@REM End of extension + +%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%" == "on" pause + +if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% + +exit /B %ERROR_CODE% diff --git a/samples/standalone/kotlin/http-client/pom.xml b/samples/standalone/kotlin/http-client/pom.xml new file mode 100644 index 0000000000..b865bfadaf --- /dev/null +++ b/samples/standalone/kotlin/http-client/pom.xml @@ -0,0 +1,295 @@ + + + 4.0.0 + + com.example + http-client-kotlin + 0.0.1-SNAPSHOT + + Spring Cloud Contract Verifier Http Client Kotlin Sample + Spring Cloud Contract Verifier Http Client Kotlin Sample + + + org.springframework.boot + spring-boot-starter-parent + 2.2.0.M5 + + + + + UTF-8 + 1.8 + Hoxton.BUILD-SNAPSHOT + 1.3.41 + + + + + org.springframework.boot + spring-boot-starter-web + + + com.fasterxml.jackson.module + jackson-module-kotlin + + + org.jetbrains.kotlin + kotlin-reflect + ${kotlin.version} + + + org.jetbrains.kotlin + kotlin-stdlib-jdk8 + ${kotlin.version} + + + org.springframework.boot + spring-boot-starter-actuator + + + org.apache.httpcomponents + httpclient + + + + + org.springframework.cloud + spring-cloud-starter-contract-stub-runner + test + + + + + + org.springframework.cloud + spring-cloud-starter-contract-verifier + test + + + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud-release.version} + pom + import + + + + + + + ${project.basedir}/src/main/kotlin + ${project.basedir}/src/test/kotlin + + + org.springframework.boot + spring-boot-maven-plugin + + + org.jetbrains.kotlin + kotlin-maven-plugin + + + -Xjsr305=strict + + + spring + + 1.8 + + + + org.jetbrains.kotlin + kotlin-maven-allopen + ${kotlin.version} + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + + + default-compile + none + + + + default-testCompile + none + + + java-compile + compile + + compile + + + + java-test-compile + test-compile + + testCompile + + + + + + 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-releases + Spring Releases + https://repo.spring.io/release + + false + + + + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/snapshot + + true + + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + false + + + + spring-releases + Spring Releases + https://repo.spring.io/release + + false + + + + + + + integration + + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + + gradle + test + + ./gradlew + + clean + build + publishToMavenLocal + + -PverifierVersion=${spring-cloud-contract.version} + + + + + exec + + + + + + + + + windows + + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + + gradle + test + + gradlew.bat + + clean + build + publishToMavenLocal + + -PverifierVersion=${spring-cloud-contract.version} + + + + + exec + + + + + + + + + + diff --git a/samples/standalone/kotlin/http-client/settings.gradle.kts b/samples/standalone/kotlin/http-client/settings.gradle.kts new file mode 100644 index 0000000000..c2f731718d --- /dev/null +++ b/samples/standalone/kotlin/http-client/settings.gradle.kts @@ -0,0 +1,18 @@ +pluginManagement { + repositories { + mavenCentral() + mavenLocal() + maven { url = uri("https://repo.spring.io/release") } + maven { url = uri("https://repo.spring.io/milestone") } + maven { url = uri("https://repo.spring.io/snapshot") } + gradlePluginPortal() + } + resolutionStrategy { + eachPlugin { + if (requested.id.id == "org.springframework.boot") { + useModule("org.springframework.boot:spring-boot-gradle-plugin:${requested.version}") + } + } + } +} +rootProject.name = "http-client-kotlin-gradle" diff --git a/samples/standalone/kotlin/http-client/src/main/kotlin/com/example/loan/Application.kt b/samples/standalone/kotlin/http-client/src/main/kotlin/com/example/loan/Application.kt new file mode 100644 index 0000000000..96ca0a92a3 --- /dev/null +++ b/samples/standalone/kotlin/http-client/src/main/kotlin/com/example/loan/Application.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2013-2019 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.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class Application + +fun main(args: Array) { + runApplication(*args) +} \ No newline at end of file diff --git a/samples/standalone/kotlin/http-client/src/main/kotlin/com/example/loan/LoanApplicationService.kt b/samples/standalone/kotlin/http-client/src/main/kotlin/com/example/loan/LoanApplicationService.kt new file mode 100644 index 0000000000..1cb694bb33 --- /dev/null +++ b/samples/standalone/kotlin/http-client/src/main/kotlin/com/example/loan/LoanApplicationService.kt @@ -0,0 +1,106 @@ +/* + * Copyright 2013-2019 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.stereotype.Service +import org.springframework.web.client.RestTemplate + +@Service +class LoanApplicationService { + + private var port = 6565 + private val restTemplate: RestTemplate + + @Autowired + constructor(builder: RestTemplateBuilder) : this(builder.build()) + + constructor(restTemplate: RestTemplate) { + this.restTemplate = restTemplate + } + + fun loanApplication(loanApplication: LoanApplication): LoanApplicationResult? { + val request = FraudServiceRequest(loanApplication) + val response = sendRequestToFraudDetectionService(request) + return buildResponseFromFraudResult(response) + } + + private fun sendRequestToFraudDetectionService(request: FraudServiceRequest): FraudServiceResponse? { + val httpHeaders = HttpHeaders() + httpHeaders.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + + // tag::client_call_server[] + val response = restTemplate.exchange("http://localhost:$port/fraudcheck", + HttpMethod.PUT, HttpEntity(request, httpHeaders), FraudServiceResponse::class.java) + // end::client_call_server[] + + return response.body + } + + private fun buildResponseFromFraudResult(response: FraudServiceResponse?): LoanApplicationResult? { + return response?.let { + val applicationStatus = when(response.fraudCheckStatus) { + FraudCheckStatus.OK -> LoanApplicationStatus.LOAN_APPLIED + FraudCheckStatus.FRAUD -> LoanApplicationStatus.LOAN_APPLICATION_REJECTED + } + LoanApplicationResult(applicationStatus, response.rejectionReason) + } + } + + fun countAllFrauds(): Int? { + val httpHeaders = HttpHeaders() + httpHeaders.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + val response = restTemplate.exchange("http://localhost:$port/frauds", + HttpMethod.GET, HttpEntity(httpHeaders), Response::class.java) + return response.body?.count + } + + fun countDrunks(): Int? { + val httpHeaders = HttpHeaders() + httpHeaders.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + val response = restTemplate.exchange("http://localhost:$port/drunks", + HttpMethod.GET, HttpEntity(httpHeaders), Response::class.java) + return response.body?.count + } + + fun getCookies(): String? { + val httpHeaders = HttpHeaders() + httpHeaders.add("Cookie", "name=foo") + httpHeaders.add("Cookie", "name2=bar") + val response = restTemplate.exchange("http://localhost:$port/frauds/name", + HttpMethod.GET, HttpEntity(httpHeaders), String::class.java) + return response.body + } + + fun setPort(port: Int) { + this.port = port + } + +} diff --git a/samples/standalone/kotlin/http-client/src/main/kotlin/com/example/loan/model/Client.kt b/samples/standalone/kotlin/http-client/src/main/kotlin/com/example/loan/model/Client.kt new file mode 100644 index 0000000000..57ec827e94 --- /dev/null +++ b/samples/standalone/kotlin/http-client/src/main/kotlin/com/example/loan/model/Client.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2013-2019 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 + +data class Client(val pesel: String) \ No newline at end of file diff --git a/samples/standalone/kotlin/http-client/src/main/kotlin/com/example/loan/model/FraudCheckStatus.kt b/samples/standalone/kotlin/http-client/src/main/kotlin/com/example/loan/model/FraudCheckStatus.kt new file mode 100644 index 0000000000..a07f2323a5 --- /dev/null +++ b/samples/standalone/kotlin/http-client/src/main/kotlin/com/example/loan/model/FraudCheckStatus.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2013-2019 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 + +enum class FraudCheckStatus { + OK, + FRAUD, + ; +} diff --git a/samples/standalone/kotlin/http-client/src/main/kotlin/com/example/loan/model/FraudServiceRequest.kt b/samples/standalone/kotlin/http-client/src/main/kotlin/com/example/loan/model/FraudServiceRequest.kt new file mode 100644 index 0000000000..4641306c9e --- /dev/null +++ b/samples/standalone/kotlin/http-client/src/main/kotlin/com/example/loan/model/FraudServiceRequest.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2013-2019 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 + +data class FraudServiceRequest(@JsonProperty("client.id") val clientId: String, val loanAmount: Double) { + + constructor(loanApplication: LoanApplication): this(loanApplication.client.pesel, loanApplication.amount) + +} diff --git a/samples/standalone/kotlin/http-client/src/main/kotlin/com/example/loan/model/FraudServiceResponse.kt b/samples/standalone/kotlin/http-client/src/main/kotlin/com/example/loan/model/FraudServiceResponse.kt new file mode 100644 index 0000000000..fb6b4f320d --- /dev/null +++ b/samples/standalone/kotlin/http-client/src/main/kotlin/com/example/loan/model/FraudServiceResponse.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2013-2019 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 + +data class FraudServiceResponse(val fraudCheckStatus: FraudCheckStatus, + @JsonProperty("rejection.reason") val rejectionReason: String?) \ No newline at end of file diff --git a/samples/standalone/kotlin/http-client/src/main/kotlin/com/example/loan/model/LoanApplication.kt b/samples/standalone/kotlin/http-client/src/main/kotlin/com/example/loan/model/LoanApplication.kt new file mode 100644 index 0000000000..11146a9c8f --- /dev/null +++ b/samples/standalone/kotlin/http-client/src/main/kotlin/com/example/loan/model/LoanApplication.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2013-2019 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 + +data class LoanApplication(val client: Client, val amount: Double) { + + var loanApplicationId: String? = null + +} diff --git a/samples/standalone/kotlin/http-client/src/main/kotlin/com/example/loan/model/LoanApplicationResult.kt b/samples/standalone/kotlin/http-client/src/main/kotlin/com/example/loan/model/LoanApplicationResult.kt new file mode 100644 index 0000000000..1a77332cfe --- /dev/null +++ b/samples/standalone/kotlin/http-client/src/main/kotlin/com/example/loan/model/LoanApplicationResult.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2013-2019 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 + +data class LoanApplicationResult(val loanApplicationStatus: LoanApplicationStatus, + val rejectionReason: String?) \ No newline at end of file diff --git a/samples/standalone/kotlin/http-client/src/main/kotlin/com/example/loan/model/LoanApplicationStatus.kt b/samples/standalone/kotlin/http-client/src/main/kotlin/com/example/loan/model/LoanApplicationStatus.kt new file mode 100644 index 0000000000..0e8655e982 --- /dev/null +++ b/samples/standalone/kotlin/http-client/src/main/kotlin/com/example/loan/model/LoanApplicationStatus.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2013-2019 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 + +enum class LoanApplicationStatus { + LOAN_APPLIED, + LOAN_APPLICATION_REJECTED, + ; +} diff --git a/samples/standalone/kotlin/http-client/src/main/kotlin/com/example/loan/model/Response.kt b/samples/standalone/kotlin/http-client/src/main/kotlin/com/example/loan/model/Response.kt new file mode 100644 index 0000000000..eda9b096ef --- /dev/null +++ b/samples/standalone/kotlin/http-client/src/main/kotlin/com/example/loan/model/Response.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2013-2019 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 + +data class Response(val count: Int) \ No newline at end of file diff --git a/samples/standalone/kotlin/http-client/src/main/resources/application.yml b/samples/standalone/kotlin/http-client/src/main/resources/application.yml new file mode 100644 index 0000000000..4b7fe13158 --- /dev/null +++ b/samples/standalone/kotlin/http-client/src/main/resources/application.yml @@ -0,0 +1 @@ +server.port: 8090 \ No newline at end of file diff --git a/samples/standalone/kotlin/http-client/src/test/kotlin/com/example/loan/GoodbyeWorldTests.kt b/samples/standalone/kotlin/http-client/src/test/kotlin/com/example/loan/GoodbyeWorldTests.kt new file mode 100644 index 0000000000..f6941bcb1e --- /dev/null +++ b/samples/standalone/kotlin/http-client/src/test/kotlin/com/example/loan/GoodbyeWorldTests.kt @@ -0,0 +1,53 @@ +/* + * Copyright 2013-2019 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.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +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.test.context.junit.jupiter.SpringExtension +import org.springframework.web.client.RestTemplate +import org.springframework.web.client.getForObject + +// tag::autoconfigure_stubrunner[] +@ExtendWith(SpringExtension::class) +@SpringBootTest(webEnvironment = WebEnvironment.NONE) +@AutoConfigureStubRunner(ids = ["com.example:http-server-kotlin"], + repositoryRoot = "stubs://classpath:contractsAtRuntime/", + stubsMode = StubRunnerProperties.StubsMode.LOCAL, + generateStubs = true) +class GoodbyeWorldTests { +// end::autoconfigure_stubrunner[] + + @StubRunnerPort("http-server-kotlin") + var port: Int? = null + + @Test + fun shouldGenerateStubsAtRuntime() { + // when: + val response: String = RestTemplate().getForObject("http://localhost:" + this.port + "/goodbye", String::class) + // then: + assertThat(response).isEqualTo("Goodbye World!") + } + +} diff --git a/samples/standalone/kotlin/http-client/src/test/kotlin/com/example/loan/LoanApplicationServiceContextPathTests.kt b/samples/standalone/kotlin/http-client/src/test/kotlin/com/example/loan/LoanApplicationServiceContextPathTests.kt new file mode 100644 index 0000000000..78c34c13b4 --- /dev/null +++ b/samples/standalone/kotlin/http-client/src/test/kotlin/com/example/loan/LoanApplicationServiceContextPathTests.kt @@ -0,0 +1,66 @@ +/* + * Copyright 2013-2019 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.LoanApplicationStatus +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +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 org.springframework.test.context.junit.jupiter.SpringExtension + +@ExtendWith(SpringExtension::class) +@SpringBootTest(webEnvironment = WebEnvironment.NONE, properties = ["server.context-path=/app"]) +@AutoConfigureStubRunner(ids = ["com.example:http-server-kotlin:+:stubs:6565"], + stubsMode = StubRunnerProperties.StubsMode.LOCAL) +class LoanApplicationServiceContextPathTests { + + @Autowired + lateinit var service: LoanApplicationService + + @Test + fun shouldSuccessfullyApplyForLoan() { + // given: + val application = LoanApplication(Client("1234567890"), 123.123) + // when: + val loanApplication = service.loanApplication(application) + // then: + assertThat(loanApplication?.loanApplicationStatus) + .isEqualTo(LoanApplicationStatus.LOAN_APPLIED) + assertThat(loanApplication?.rejectionReason).isNull() + } + + @Test + fun shouldBeRejectedDueToAbnormalLoanAmount() { + // given: + val application = LoanApplication(Client("1234567890"), 99999.0) + // when: + val loanApplication = service.loanApplication(application) + // then: + assertThat(loanApplication?.loanApplicationStatus) + .isEqualTo(LoanApplicationStatus.LOAN_APPLICATION_REJECTED) + assertThat(loanApplication?.rejectionReason).isEqualTo("Amount too high") + } + +} diff --git a/samples/standalone/kotlin/http-client/src/test/kotlin/com/example/loan/LoanApplicationServiceTests.kt b/samples/standalone/kotlin/http-client/src/test/kotlin/com/example/loan/LoanApplicationServiceTests.kt new file mode 100644 index 0000000000..227b1b8da9 --- /dev/null +++ b/samples/standalone/kotlin/http-client/src/test/kotlin/com/example/loan/LoanApplicationServiceTests.kt @@ -0,0 +1,148 @@ +/* + * Copyright 2013-2019 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.net.URI +import java.nio.file.Files + +import com.example.loan.model.Client +import com.example.loan.model.LoanApplication +import com.example.loan.model.LoanApplicationStatus +import com.jayway.jsonpath.JsonPath +import com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson +import io.restassured.RestAssured +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +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 org.springframework.http.RequestEntity +import org.springframework.http.ResponseEntity +import org.springframework.test.context.junit.jupiter.SpringExtension +import org.springframework.web.client.RestTemplate + +// tag::autoconfigure_stubrunner[] +@ExtendWith(SpringExtension::class) +@SpringBootTest(webEnvironment = WebEnvironment.NONE) +@AutoConfigureStubRunner(ids = ["com.example:http-server-kotlin:+:stubs:6565"], + stubsMode = StubRunnerProperties.StubsMode.LOCAL) +class LoanApplicationServiceTests { +// end::autoconfigure_stubrunner[] + + @Autowired + lateinit var service: LoanApplicationService + + @Test + fun shouldSuccessfullyApplyForLoan() { + // given: + val application = LoanApplication(Client("1234567890"), 123.123) + // when: + val loanApplication = service.loanApplication(application) + // then: + assertThat(loanApplication?.loanApplicationStatus).isEqualTo(LoanApplicationStatus.LOAN_APPLIED) + assertThat(loanApplication?.rejectionReason).isNull() + } + + // tag::client_tdd[] + @Test + fun shouldBeRejectedDueToAbnormalLoanAmount() { + // given: + val application = LoanApplication(Client("1234567890"), 99999.0) + // when: + val loanApplication = service.loanApplication(application) + // then: + assertThat(loanApplication?.loanApplicationStatus) + .isEqualTo(LoanApplicationStatus.LOAN_APPLICATION_REJECTED) + assertThat(loanApplication?.rejectionReason).isEqualTo("Amount too high") + } + // end::client_tdd[] + + @Test + fun shouldSuccessfullyGetAllFrauds() { + // when: + val count = service.countAllFrauds() + // then: + assertThat(count).isGreaterThanOrEqualTo(200) + } + + @Test + fun shouldSuccessfullyGetAllDrunks() { + // when: + val count = service.countDrunks() + // then: + assertThat(count).isEqualTo(100) + } + + @Test + @Suppress("UsePropertyAccessSyntax") + fun shouldSuccessfullyGetCookies() { + // when: + val cookies = service.getCookies() + // then: + assertThat(cookies).isEqualTo("foo bar") + } + + @Test + fun shouldSuccessfullyWorkWithMultipart() { + // given: + val request = RestAssured.given() + .baseUri("http://localhost:6565/") + .header("Content-Type", "multipart/form-data") + .multiPart("file1", "filename1", "content1".toByteArray()) + .multiPart("file2", "filename1", "content2".toByteArray()) + .multiPart("test", "filename1", "{\n \"status\": \"test\"\n}".toByteArray(), + "application/json") + + // when: + val response = RestAssured.given().spec(request).post("/tests") + + // then: + assertThat(response.statusCode).isEqualTo(200) + assertThat(response.header("Content-Type")).matches("application/json.*") + // and: + val parsedJson = JsonPath.parse(response.body.asString()) + assertThatJson(parsedJson).field("['status']").isEqualTo("ok") + } + + @Test + fun shouldSuccessfullyWorkWithBinary() { + // given: + val request = File(javaClass.getResource("/binary/request.pdf").file) + val response = File(javaClass.getResource("/binary/response.pdf").file) + + + // when: + val exchange: ResponseEntity = RestTemplate().exchange( + RequestEntity.put(URI.create("http://localhost:6565/1")) + .header("Content-Type", "application/octet-stream") + .body(Files.readAllBytes(request.toPath())), + ByteArray::class.java) + + // then: + assertThat(exchange.statusCodeValue).isEqualTo(200) + assertThat(exchange.headers["Content-Type"]?.get(0)) + .isEqualTo("application/octet-stream") + // and: + assertThat(exchange.body).isEqualTo(Files.readAllBytes(response.toPath())) + } + +} diff --git a/samples/standalone/kotlin/http-client/src/test/resources/application-gradle.yaml b/samples/standalone/kotlin/http-client/src/test/resources/application-gradle.yaml new file mode 100644 index 0000000000..16c52af94d --- /dev/null +++ b/samples/standalone/kotlin/http-client/src/test/resources/application-gradle.yaml @@ -0,0 +1,3 @@ +stubrunner: + stubs-mode: local + stubs.ids: 'com.example:http-server-kotlin-gradle:+:stubs:6569' diff --git a/samples/standalone/kotlin/http-client/src/test/resources/application.yaml b/samples/standalone/kotlin/http-client/src/test/resources/application.yaml new file mode 100644 index 0000000000..1f9fed43b3 --- /dev/null +++ b/samples/standalone/kotlin/http-client/src/test/resources/application.yaml @@ -0,0 +1,2 @@ +server: + port: 6569 diff --git a/samples/standalone/kotlin/http-client/src/test/resources/binary/request.pdf b/samples/standalone/kotlin/http-client/src/test/resources/binary/request.pdf new file mode 100644 index 0000000000..69503635d8 Binary files /dev/null and b/samples/standalone/kotlin/http-client/src/test/resources/binary/request.pdf differ diff --git a/samples/standalone/kotlin/http-client/src/test/resources/binary/response.pdf b/samples/standalone/kotlin/http-client/src/test/resources/binary/response.pdf new file mode 100644 index 0000000000..c3b233056b Binary files /dev/null and b/samples/standalone/kotlin/http-client/src/test/resources/binary/response.pdf differ diff --git a/samples/standalone/kotlin/http-client/src/test/resources/contractsAtRuntime/goodbyeWorld.kts b/samples/standalone/kotlin/http-client/src/test/resources/contractsAtRuntime/goodbyeWorld.kts new file mode 100644 index 0000000000..41def4dc90 --- /dev/null +++ b/samples/standalone/kotlin/http-client/src/test/resources/contractsAtRuntime/goodbyeWorld.kts @@ -0,0 +1,30 @@ +/* + * Copyright 2013-2019 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.ContractDsl.Companion.contract +import org.springframework.cloud.contract.spec.internal.HttpMethods +import org.springframework.cloud.contract.spec.internal.HttpStatus + +contract { + request { + url = url("/goodbye") + method = method(HttpMethods.HttpMethod.GET) + } + response { + status = code(HttpStatus.OK()) + body = body("Goodbye World!") + } +} diff --git a/samples/standalone/kotlin/http-server/.gitignore b/samples/standalone/kotlin/http-server/.gitignore new file mode 100644 index 0000000000..b05ba7bd6d --- /dev/null +++ b/samples/standalone/kotlin/http-server/.gitignore @@ -0,0 +1,6 @@ + +target/ + +.gradle +build/ + diff --git a/samples/standalone/kotlin/http-server/README.adoc b/samples/standalone/kotlin/http-server/README.adoc new file mode 100644 index 0000000000..2fd3fbc40d --- /dev/null +++ b/samples/standalone/kotlin/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/samples/standalone/kotlin/http-server/build.gradle.kts b/samples/standalone/kotlin/http-server/build.gradle.kts new file mode 100644 index 0000000000..917b52c48d --- /dev/null +++ b/samples/standalone/kotlin/http-server/build.gradle.kts @@ -0,0 +1,94 @@ +import org.gradle.api.tasks.testing.logging.TestExceptionFormat +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +plugins { + id("org.springframework.boot") version "2.2.0.M5" + id("io.spring.dependency-management") version "1.0.7.RELEASE" + id("spring-cloud-contract") version "2.2.0.BUILD-SNAPSHOT" + id("maven-publish") + kotlin("jvm") version "1.3.41" + kotlin("plugin.spring") version "1.3.41" +} + +group = "com.example" +version = "0.0.1-SNAPSHOT" +java.sourceCompatibility = JavaVersion.VERSION_1_8 + +// tag::deps_repos[] +repositories { + mavenCentral() + mavenLocal() + maven { url = uri("https://repo.spring.io/release") } + maven { url = uri("https://repo.spring.io/milestone") } + maven { url = uri("https://repo.spring.io/snapshot") } +} +// end::deps_repos[] + +// tag::dep_mgmt[] +dependencyManagement { + + val BOM_VERSION: String by project + + imports { + mavenBom("org.springframework.cloud:spring-cloud-dependencies:$BOM_VERSION") + } +} +// end::dep_mgmt[] + +// tag::deps[] +dependencies { + implementation("org.springframework.boot:spring-boot-starter-web") + implementation("com.fasterxml.jackson.module:jackson-module-kotlin") + implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") + implementation("org.jetbrains.kotlin:kotlin-reflect") + testImplementation("org.springframework.cloud:spring-cloud-contract-gradle-plugin") + testImplementation("org.springframework.cloud:spring-cloud-starter-contract-verifier") + testImplementation("io.rest-assured:rest-assured") + testImplementation("io.rest-assured:spring-mock-mvc") + testImplementation("io.rest-assured:spring-web-test-client") { + exclude(group = "org.springframework", module = "spring-context") + exclude(group = "org.springframework", module = "spring-webflux") + } + testImplementation("org.springframework.boot:spring-boot-starter-test") { + exclude(group = "org.junit.vintage", module = "junit-vintage-engine") + exclude(group = "junit", module = "junit") + } +} +// end::deps[] + +// tag::contract_dsl[] +contracts { + packageWithBaseClasses = "com.example.fraud" +} +// end::contract_dsl[] + +tasks.withType { + doFirst { + delete("~/.m2/repository/com/example/http-server-kotlin-gradle") + } +} + +tasks.withType { + useJUnitPlatform() + systemProperty("spring.profiles.active", "gradle") + testLogging { + exceptionFormat = TestExceptionFormat.FULL + } + afterSuite(KotlinClosure2({ desc: TestDescriptor, result: TestResult -> + if (desc.parent == null) { + if (result.testCount == 0L) { + throw IllegalStateException("No tests were found. Failing the build") + } + else { + println("Results: (${result.testCount} tests, ${result.successfulTestCount} successes, ${result.failedTestCount} failures, ${result.skippedTestCount} skipped)") + } + } else { /* Nothing to do here */ } + })) +} + +tasks.withType { + kotlinOptions { + freeCompilerArgs = listOf("-Xjsr305=strict") + jvmTarget = "1.8" + } +} diff --git a/samples/standalone/kotlin/http-server/gradle.properties b/samples/standalone/kotlin/http-server/gradle.properties new file mode 100644 index 0000000000..535ecb91d1 --- /dev/null +++ b/samples/standalone/kotlin/http-server/gradle.properties @@ -0,0 +1,2 @@ +org.gradle.daemon=false +BOM_VERSION=Hoxton.BUILD-SNAPSHOT diff --git a/samples/standalone/kotlin/http-server/gradle/wrapper/gradle-wrapper.jar b/samples/standalone/kotlin/http-server/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000..87b738cbd0 Binary files /dev/null and b/samples/standalone/kotlin/http-server/gradle/wrapper/gradle-wrapper.jar differ diff --git a/samples/standalone/kotlin/http-server/gradle/wrapper/gradle-wrapper.properties b/samples/standalone/kotlin/http-server/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000..b0acbdcd73 --- /dev/null +++ b/samples/standalone/kotlin/http-server/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-5.5-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/samples/standalone/kotlin/http-server/gradlew b/samples/standalone/kotlin/http-server/gradlew new file mode 100755 index 0000000000..af6708ff22 --- /dev/null +++ b/samples/standalone/kotlin/http-server/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/samples/standalone/kotlin/http-server/gradlew.bat b/samples/standalone/kotlin/http-server/gradlew.bat new file mode 100644 index 0000000000..0f8d5937c4 --- /dev/null +++ b/samples/standalone/kotlin/http-server/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem 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" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/samples/standalone/kotlin/http-server/mvnw b/samples/standalone/kotlin/http-server/mvnw new file mode 100755 index 0000000000..1d5ace7fc1 --- /dev/null +++ b/samples/standalone/kotlin/http-server/mvnw @@ -0,0 +1,286 @@ +#!/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 + # 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)`" + # TODO classpath? +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`which java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +########################################################################################## +# 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 + jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.0/maven-wrapper-0.4.0.jar" + 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 command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + wget "$jarUrl" -O "$wrapperJarPath" + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + curl -o "$wrapperJarPath" "$jarUrl" + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + 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 + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/samples/standalone/kotlin/http-server/mvnw.cmd b/samples/standalone/kotlin/http-server/mvnw.cmd new file mode 100755 index 0000000000..080c510d2b --- /dev/null +++ b/samples/standalone/kotlin/http-server/mvnw.cmd @@ -0,0 +1,161 @@ +@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 set title of command window +title %0 +@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" +if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.0/maven-wrapper-0.4.0.jar" +FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + echo Found %WRAPPER_JAR% +) else ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')" + echo Finished downloading %WRAPPER_JAR% +) +@REM End of extension + +%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%" == "on" pause + +if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% + +exit /B %ERROR_CODE% diff --git a/samples/standalone/kotlin/http-server/pom.xml b/samples/standalone/kotlin/http-server/pom.xml new file mode 100644 index 0000000000..1a42bc5ace --- /dev/null +++ b/samples/standalone/kotlin/http-server/pom.xml @@ -0,0 +1,362 @@ + + + 4.0.0 + + com.example + http-server-kotlin + 0.0.1-SNAPSHOT + + Spring Cloud Contract Verifier Http Server Kotlin Sample + Spring Cloud Contract Verifier Http Server Kotlin Sample + + + org.springframework.boot + spring-boot-starter-parent + 2.2.0.M5 + + + + + UTF-8 + 1.8 + 2.2.0.BUILD-SNAPSHOT + Hoxton.BUILD-SNAPSHOT + 3.2.0 + 1.3.41 + + + + + org.jetbrains.kotlin + kotlin-stdlib-jdk8 + ${kotlin.version} + + + org.jetbrains.kotlin + kotlin-reflect + ${kotlin.version} + + + org.springframework.boot + spring-boot-starter-web + + + com.fasterxml.jackson.module + jackson-module-kotlin + + + + + org.springframework.cloud + spring-cloud-starter-contract-verifier + test + + + + io.rest-assured + spring-mock-mvc + ${rest-assured.version} + test + + + spring-web + org.springframework + + + spring-webmvc + org.springframework + + + spring-test + org.springframework + + + + + io.rest-assured + spring-web-test-client + ${rest-assured.version} + test + + + spring-context + org.springframework + + + spring-webflux + org.springframework + + + + + io.rest-assured + rest-assured + ${rest-assured.version} + test + + + + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud-release.version} + pom + import + + + + + + + ${project.basedir}/src/main/kotlin + ${project.basedir}/src/test/kotlin + + + org.springframework.boot + spring-boot-maven-plugin + + + org.jetbrains.kotlin + kotlin-maven-plugin + ${kotlin.version} + + + -Xjsr305=strict + + 1.8 + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + + + default-compile + none + + + + default-testCompile + none + + + java-compile + compile + + compile + + + + java-test-compile + test-compile + + testCompile + + + + + + + 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.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-releases + Spring Releases + https://repo.spring.io/release + + false + + + + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/snapshot + + true + + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + false + + + + spring-releases + Spring Releases + https://repo.spring.io/release + + false + + + + + + + + integration + + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + + gradle + test + + ./gradlew + + clean + build + publishToMavenLocal + + -PverifierVersion=${spring-cloud-contract.version} + + + + + exec + + + + + + + + + windows + + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + + gradle + test + + gradlew.bat + + clean + build + publishToMavenLocal + + -PverifierVersion=${spring-cloud-contract.version} + + + + + exec + + + + + + + + + diff --git a/samples/standalone/kotlin/http-server/settings.gradle.kts b/samples/standalone/kotlin/http-server/settings.gradle.kts new file mode 100644 index 0000000000..a512bc3448 --- /dev/null +++ b/samples/standalone/kotlin/http-server/settings.gradle.kts @@ -0,0 +1,21 @@ +pluginManagement { + repositories { + mavenCentral() + mavenLocal() + maven { url = uri("https://repo.spring.io/release") } + maven { url = uri("https://repo.spring.io/milestone") } + maven { url = uri("https://repo.spring.io/snapshot") } + gradlePluginPortal() + } + resolutionStrategy { + eachPlugin { + if (requested.id.id == "org.springframework.boot") { + useModule("org.springframework.boot:spring-boot-gradle-plugin:${requested.version}") + } + if (requested.id.id == "spring-cloud-contract") { + useModule("org.springframework.cloud:spring-cloud-contract-gradle-plugin:${requested.version}") + } + } + } +} +rootProject.name = "http-server-kotlin-gradle" diff --git a/samples/standalone/kotlin/http-server/src/main/kotlin/com/example/fraud/Application.kt b/samples/standalone/kotlin/http-server/src/main/kotlin/com/example/fraud/Application.kt new file mode 100644 index 0000000000..8a57bf9c51 --- /dev/null +++ b/samples/standalone/kotlin/http-server/src/main/kotlin/com/example/fraud/Application.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2013-2019 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.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class Application + +fun main(args: Array) { + runApplication(*args) +} \ No newline at end of file diff --git a/samples/standalone/kotlin/http-server/src/main/kotlin/com/example/fraud/FraudDetectionController.kt b/samples/standalone/kotlin/http-server/src/main/kotlin/com/example/fraud/FraudDetectionController.kt new file mode 100644 index 0000000000..c5a04af197 --- /dev/null +++ b/samples/standalone/kotlin/http-server/src/main/kotlin/com/example/fraud/FraudDetectionController.kt @@ -0,0 +1,50 @@ +/* + * Copyright 2013-2019 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 com.example.fraud.model.FraudCheck +import com.example.fraud.model.FraudCheckResult +import com.example.fraud.model.FraudCheckStatus +import org.springframework.web.bind.annotation.PutMapping +import org.springframework.web.bind.annotation.RequestBody +import org.springframework.web.bind.annotation.RestController +import java.math.BigDecimal + +@RestController +class FraudDetectionController { + + private val maxAmount = BigDecimal("5000") + + // tag::server_api[] + @PutMapping("/fraudcheck") + fun fraudCheck(@RequestBody fraudCheck: FraudCheck): FraudCheckResult { + // end::server_api[] + // tag::new_impl[] + if (amountGreaterThanThreshold(fraudCheck)) { + return FraudCheckResult(FraudCheckStatus.FRAUD, "Amount too high") + } + // end::new_impl[] + // tag::initial_impl[] + return FraudCheckResult(FraudCheckStatus.OK) + // end::initial_impl[] + } + + fun amountGreaterThanThreshold(fraudCheck: FraudCheck): Boolean { + return maxAmount < fraudCheck.loanAmount; + } + +} diff --git a/samples/standalone/kotlin/http-server/src/main/kotlin/com/example/fraud/FraudNameController.kt b/samples/standalone/kotlin/http-server/src/main/kotlin/com/example/fraud/FraudNameController.kt new file mode 100644 index 0000000000..cda4b5808e --- /dev/null +++ b/samples/standalone/kotlin/http-server/src/main/kotlin/com/example/fraud/FraudNameController.kt @@ -0,0 +1,51 @@ +/* + * Copyright 2013-2019 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.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 { + fun isFraudByName(name: String): Boolean +} + +data class NameRequest(val name: String) + +data class NameResponse(val result: String) + +@RestController +class FraudNameController constructor(val fraudVerifier: FraudVerifier) { + + @PutMapping("/frauds/name") + fun checkByName(@RequestBody request: NameRequest): NameResponse { + val fraud = this.fraudVerifier.isFraudByName(request.name); + if (fraud) { + return NameResponse("Sorry " + request.name + " but you're a fraud"); + } + return NameResponse("Don't worry " + request.name + " you're not a fraud"); + } + + @GetMapping("/frauds/name") + fun checkByName(@CookieValue("name") value: String, + @CookieValue("name2") value2: String): String { + return "$value $value2" + } + +} \ No newline at end of file diff --git a/samples/standalone/kotlin/http-server/src/main/kotlin/com/example/fraud/FraudStatsController.kt b/samples/standalone/kotlin/http-server/src/main/kotlin/com/example/fraud/FraudStatsController.kt new file mode 100644 index 0000000000..51d8c31795 --- /dev/null +++ b/samples/standalone/kotlin/http-server/src/main/kotlin/com/example/fraud/FraudStatsController.kt @@ -0,0 +1,45 @@ +/* + * Copyright 2013-2019 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; + +enum class FraudType { + DRUNKS, ALL; +} + +interface StatsProvider { + fun count(fraudType: FraudType): Int +} + +data class Response(val count: Int) + +@RestController +class FraudStatsController constructor(val statsProvider: StatsProvider) { + + @GetMapping("/frauds") + fun countAllFrauds(): Response { + return Response(this.statsProvider.count(FraudType.ALL)); + } + + @GetMapping("/drunks") + fun countAllDrunks(): Response { + return Response(this.statsProvider.count(FraudType.DRUNKS)); + } + +} \ No newline at end of file diff --git a/samples/standalone/kotlin/http-server/src/main/kotlin/com/example/fraud/TestController.kt b/samples/standalone/kotlin/http-server/src/main/kotlin/com/example/fraud/TestController.kt new file mode 100644 index 0000000000..ac138d3f0b --- /dev/null +++ b/samples/standalone/kotlin/http-server/src/main/kotlin/com/example/fraud/TestController.kt @@ -0,0 +1,58 @@ +/* + * Copyright 2013-2019 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.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 +import java.io.File +import java.net.URL +import java.nio.file.Files +import java.util.* + +fun URL.toByte(): ByteArray { + return Files.readAllBytes(File(toURI()).toPath()) +} + +data class Test(val status: String) + +@RestController +class TestController { + + private val request: ByteArray = javaClass.getResource("/contracts/binary/request.pdf").toByte() + private val response: ByteArray = javaClass.getResource("/contracts/binary/response.pdf").toByte() + + @PostMapping("/tests") + fun createNew(@RequestPart file1: MultipartFile, + @RequestPart file2: MultipartFile, + @RequestPart test: Test): Test { + return Test("ok"); + } + + @PutMapping("/1", consumes = [MediaType.APPLICATION_OCTET_STREAM_VALUE], produces = [MediaType.APPLICATION_OCTET_STREAM_VALUE]) + fun response(@RequestBody requestBody: ByteArray): ByteArray { + if (!Arrays.equals(this.request, requestBody)) { + throw IllegalStateException("Invalid request body"); + } + return this.response; + } + +} \ No newline at end of file diff --git a/samples/standalone/kotlin/http-server/src/main/kotlin/com/example/fraud/model/FraudCheck.kt b/samples/standalone/kotlin/http-server/src/main/kotlin/com/example/fraud/model/FraudCheck.kt new file mode 100644 index 0000000000..b16e078162 --- /dev/null +++ b/samples/standalone/kotlin/http-server/src/main/kotlin/com/example/fraud/model/FraudCheck.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2013-2019 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; + +data class FraudCheck constructor(@JsonProperty("client.id") val clientId: String, val loanAmount: BigDecimal) diff --git a/samples/standalone/kotlin/http-server/src/main/kotlin/com/example/fraud/model/FraudCheckResult.kt b/samples/standalone/kotlin/http-server/src/main/kotlin/com/example/fraud/model/FraudCheckResult.kt new file mode 100644 index 0000000000..df0bdf0e2b --- /dev/null +++ b/samples/standalone/kotlin/http-server/src/main/kotlin/com/example/fraud/model/FraudCheckResult.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2013-2019 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; + +data class FraudCheckResult constructor(val fraudCheckStatus: FraudCheckStatus, @JsonProperty("rejection.reason") var rejectionReason: String? = null) \ No newline at end of file diff --git a/samples/standalone/kotlin/http-server/src/main/kotlin/com/example/fraud/model/FraudCheckStatus.kt b/samples/standalone/kotlin/http-server/src/main/kotlin/com/example/fraud/model/FraudCheckStatus.kt new file mode 100644 index 0000000000..08f342a604 --- /dev/null +++ b/samples/standalone/kotlin/http-server/src/main/kotlin/com/example/fraud/model/FraudCheckStatus.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2013-2019 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; + +enum class FraudCheckStatus { + OK, FRAUD; +} diff --git a/samples/standalone/kotlin/http-server/src/main/resources/application.yml b/samples/standalone/kotlin/http-server/src/main/resources/application.yml new file mode 100644 index 0000000000..1c421cf2b7 --- /dev/null +++ b/samples/standalone/kotlin/http-server/src/main/resources/application.yml @@ -0,0 +1 @@ +server.port=0 \ No newline at end of file diff --git a/samples/standalone/kotlin/http-server/src/test/kotlin/com/example/fraud/BinaryBase.kt b/samples/standalone/kotlin/http-server/src/test/kotlin/com/example/fraud/BinaryBase.kt new file mode 100644 index 0000000000..4a49ea7462 --- /dev/null +++ b/samples/standalone/kotlin/http-server/src/test/kotlin/com/example/fraud/BinaryBase.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2013-2019 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.Before; + +open class BinaryBase { + + @Before + fun setUp() { + RestAssuredMockMvc.standaloneSetup(TestController()); + } + +} diff --git a/samples/standalone/kotlin/http-server/src/test/kotlin/com/example/fraud/FraudBase.kt b/samples/standalone/kotlin/http-server/src/test/kotlin/com/example/fraud/FraudBase.kt new file mode 100644 index 0000000000..eebe7967e5 --- /dev/null +++ b/samples/standalone/kotlin/http-server/src/test/kotlin/com/example/fraud/FraudBase.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2013-2019 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.Before; + +open class FraudBase { + + @Before + fun setup() { + RestAssuredMockMvc.standaloneSetup(FraudDetectionController(), + FraudStatsController(stubbedStatsProvider())) + } + + private fun stubbedStatsProvider(): StatsProvider { + return object : StatsProvider { + override fun count(fraudType: FraudType): Int { + return when (fraudType) { + FraudType.DRUNKS -> 100 + FraudType.ALL -> 200 + else -> 0 + } + } + } + } + + fun assertThatRejectionReasonIsNull(rejectionReason: Any?) { + assert(rejectionReason == null) + } + +} diff --git a/samples/standalone/kotlin/http-server/src/test/kotlin/com/example/fraud/FraudnameBase.kt b/samples/standalone/kotlin/http-server/src/test/kotlin/com/example/fraud/FraudnameBase.kt new file mode 100644 index 0000000000..88b949471f --- /dev/null +++ b/samples/standalone/kotlin/http-server/src/test/kotlin/com/example/fraud/FraudnameBase.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2013-2019 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.Before; + +open class FraudnameBase { + + @Before + fun setup() { + RestAssuredMockMvc.standaloneSetup(FraudNameController(object : FraudVerifier { + override fun isFraudByName(name: String): Boolean { + return "fraud" == name + } + })) + } + +} diff --git a/samples/standalone/kotlin/http-server/src/test/kotlin/com/example/fraud/MultipartBase.kt b/samples/standalone/kotlin/http-server/src/test/kotlin/com/example/fraud/MultipartBase.kt new file mode 100644 index 0000000000..534be86f19 --- /dev/null +++ b/samples/standalone/kotlin/http-server/src/test/kotlin/com/example/fraud/MultipartBase.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2013-2019 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.Before; + +open class MultipartBase { + + @Before + fun setUp() { + RestAssuredMockMvc.standaloneSetup(TestController()) + } + +} diff --git a/samples/standalone/kotlin/http-server/src/test/resources/contracts/binary/request.pdf b/samples/standalone/kotlin/http-server/src/test/resources/contracts/binary/request.pdf new file mode 100644 index 0000000000..69503635d8 Binary files /dev/null and b/samples/standalone/kotlin/http-server/src/test/resources/contracts/binary/request.pdf differ diff --git a/samples/standalone/kotlin/http-server/src/test/resources/contracts/binary/response.pdf b/samples/standalone/kotlin/http-server/src/test/resources/contracts/binary/response.pdf new file mode 100644 index 0000000000..c3b233056b Binary files /dev/null and b/samples/standalone/kotlin/http-server/src/test/resources/contracts/binary/response.pdf differ diff --git a/samples/standalone/kotlin/http-server/src/test/resources/contracts/binary/shouldWorkWithBinaryPayload.kts b/samples/standalone/kotlin/http-server/src/test/resources/contracts/binary/shouldWorkWithBinaryPayload.kts new file mode 100644 index 0000000000..10239d4d0e --- /dev/null +++ b/samples/standalone/kotlin/http-server/src/test/resources/contracts/binary/shouldWorkWithBinaryPayload.kts @@ -0,0 +1,38 @@ +/* + * Copyright 2013-2019 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 binary + +import org.springframework.cloud.contract.spec.ContractDsl.Companion.contract +import org.springframework.cloud.contract.spec.internal.HttpMethods + +contract { + request { + url = url("/1") + method = method(HttpMethods.PUT()) + headers { + contentType(applicationOctetStream()) + } + body = bodyFromFileAsBytes("request.pdf") + } + response { + status = code(200) + body = bodyFromFileAsBytes("response.pdf") + headers { + contentType(applicationOctetStream()) + } + } +} diff --git a/samples/standalone/kotlin/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsFraud.kts b/samples/standalone/kotlin/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsFraud.kts new file mode 100644 index 0000000000..766ca630d8 --- /dev/null +++ b/samples/standalone/kotlin/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsFraud.kts @@ -0,0 +1,74 @@ +/* + * Copyright 2013-2019 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 fraud + +import org.springframework.cloud.contract.spec.ContractDsl.Companion.contract +import org.springframework.cloud.contract.spec.internal.HttpStatus + +contract { + request { // (1) + method = method("PUT") // (2) + url = url("/fraudcheck") // (3) + body = body(// (4) + "client.id" to value(regex("[0-9]{10}")), + "loanAmount" to 99999) + headers { // (5) + contentType("application/json") + } + } + response { // (6) + status = code(HttpStatus.OK()) // (7) + body = body( // (8) + "fraudCheckStatus" to "FRAUD", + "rejection.reason" to "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/samples/standalone/kotlin/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsNotFraud.kts b/samples/standalone/kotlin/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsNotFraud.kts new file mode 100644 index 0000000000..f861e2ee6a --- /dev/null +++ b/samples/standalone/kotlin/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsNotFraud.kts @@ -0,0 +1,43 @@ +/* + * Copyright 2013-2019 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 fraud + +import org.springframework.cloud.contract.spec.ContractDsl.Companion.contract +import org.springframework.cloud.contract.spec.internal.HttpStatus + +contract { + request { + method = method("PUT") + url = url("/fraudcheck") + body = body( + "client.id" to value(consumer(regex("[0-9]{10}")), producer("1234567890")), + "loanAmount" to 123.123) + headers { + contentType("application/json") + } + } + response { + status = code(HttpStatus.OK()) + body = body( + "fraudCheckStatus" to "OK", + "rejection.reason" to value(consumer(null), producer(execute("assertThatRejectionReasonIsNull(\$it)"))) + ) + headers { + contentType("application/json") + } + } +} diff --git a/samples/standalone/kotlin/http-server/src/test/resources/contracts/fraud/shouldReturnFraudStats.kts b/samples/standalone/kotlin/http-server/src/test/resources/contracts/fraud/shouldReturnFraudStats.kts new file mode 100644 index 0000000000..70fe24c548 --- /dev/null +++ b/samples/standalone/kotlin/http-server/src/test/resources/contracts/fraud/shouldReturnFraudStats.kts @@ -0,0 +1,55 @@ +/* + * Copyright 2013-2019 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 fraud + +import org.springframework.cloud.contract.spec.ContractDsl.Companion.contract +import org.springframework.cloud.contract.spec.internal.HttpMethods +import org.springframework.cloud.contract.spec.internal.HttpStatus + +listOf( + contract { + name = "should count all frauds" + request { + method = method(HttpMethods.GET()) + url = url("/frauds") + } + response { + status = code(HttpStatus.OK()) + body = body( + "count" to value(regex("[2-9][0-9][0-9]")) + ) + headers { + contentType("application/json") + } + } + }, + contract { + request { + method = method(HttpMethods.GET()) + url = url("/drunks") + } + response { + status = code(HttpStatus.OK()) + body = body( + "count" to 100 + ) + headers { + contentType("application/json") + } + } + } +) \ No newline at end of file diff --git a/samples/standalone/kotlin/http-server/src/test/resources/contracts/fraudname/shouldReturnACookie.kts b/samples/standalone/kotlin/http-server/src/test/resources/contracts/fraudname/shouldReturnACookie.kts new file mode 100644 index 0000000000..b4eb9e05db --- /dev/null +++ b/samples/standalone/kotlin/http-server/src/test/resources/contracts/fraudname/shouldReturnACookie.kts @@ -0,0 +1,35 @@ +/* + * Copyright 2013-2019 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 fraudname + +import org.springframework.cloud.contract.spec.ContractDsl.Companion.contract +import org.springframework.cloud.contract.spec.internal.HttpMethods + +contract { + request { + method = method(HttpMethods.HttpMethod.GET) + url = url("/frauds/name") + cookies { + cookie("name", "foo") + cookie(mapOf("name2" to "bar")) + } + } + response { + status = code(200) + body = body("foo bar") + } +} diff --git a/samples/standalone/kotlin/http-server/src/test/resources/contracts/fraudname/shouldReturnAFraudForTheName.kts b/samples/standalone/kotlin/http-server/src/test/resources/contracts/fraudname/shouldReturnAFraudForTheName.kts new file mode 100644 index 0000000000..47c964df65 --- /dev/null +++ b/samples/standalone/kotlin/http-server/src/test/resources/contracts/fraudname/shouldReturnAFraudForTheName.kts @@ -0,0 +1,42 @@ +/* + * Copyright 2013-2019 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 fraudname + +import org.springframework.cloud.contract.spec.ContractDsl.Companion.contract +import org.springframework.cloud.contract.spec.internal.HttpMethods +import org.springframework.cloud.contract.spec.internal.HttpStatus + +contract { + // highest priority + priority = 1 + request { + method = method(HttpMethods.HttpMethod.PUT) + url = url("/frauds/name") + body = body("name" to "fraud") + headers { + contentType("application/json") + } + } + response { + status = code(HttpStatus.OK()) +// TODO +// body = body("result" to "Sorry ${fromRequest().body("$.name")} but you're a fraud") +// headers { +// header(contentType(), fromRequest().header(contentType())) +// } + } +} diff --git a/samples/standalone/kotlin/http-server/src/test/resources/contracts/fraudname/shouldReturnNonFraudForTheName.kts b/samples/standalone/kotlin/http-server/src/test/resources/contracts/fraudname/shouldReturnNonFraudForTheName.kts new file mode 100644 index 0000000000..be0685c105 --- /dev/null +++ b/samples/standalone/kotlin/http-server/src/test/resources/contracts/fraudname/shouldReturnNonFraudForTheName.kts @@ -0,0 +1,40 @@ +/* + * Copyright 2013-2019 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 fraudname + +import org.springframework.cloud.contract.spec.ContractDsl.Companion.contract +import org.springframework.cloud.contract.spec.internal.HttpMethods +import org.springframework.cloud.contract.spec.internal.HttpStatus + +contract { + request { + method = method(HttpMethods.HttpMethod.PUT) + url = url("/frauds/name") + body = body("name" to `$`(anyAlphaUnicode())) + headers { + contentType("application/json") + } + } + response { + status = code(HttpStatus.OK()) +// TODO +// body("result" to "Don't worry ${fromRequest().body("$.name")} you're not a fraud") +// headers { +// header(contentType(), fromRequest().header(contentType())) +// } + } +} diff --git a/samples/standalone/kotlin/http-server/src/test/resources/contracts/multipart/shouldWorkForMultipartAsBytesWithContentType.kts b/samples/standalone/kotlin/http-server/src/test/resources/contracts/multipart/shouldWorkForMultipartAsBytesWithContentType.kts new file mode 100644 index 0000000000..fee7c5fb65 --- /dev/null +++ b/samples/standalone/kotlin/http-server/src/test/resources/contracts/multipart/shouldWorkForMultipartAsBytesWithContentType.kts @@ -0,0 +1,49 @@ +/* + * Copyright 2013-2019 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 multipart + +import org.springframework.cloud.contract.spec.ContractDsl.Companion.contract +import org.springframework.cloud.contract.spec.internal.HttpMethods + +contract { + request { + method = method("POST") + url = url("/tests") + multipart = multipart(mapOf( + "file1" to named( + value(consumer(regex(nonEmpty())), producer("filename1")), + value(consumer(regex(nonEmpty())), producer("content1"))), + "file2" to named( + value(consumer(regex(nonEmpty())), producer("filename1")), + value(consumer(regex(nonEmpty())), producer("content1"))), + "test" to named( + value(consumer(regex(nonEmpty())), producer("filename1")), + value(consumer(regex(nonEmpty())), producer(fileAsBytes("test.json"))), + value("application/json")) + )) + headers { + contentType("multipart/form-data") + } + } + response { + status = code(200) + body = body("status" to "ok") + headers { + contentType("application/json") + } + } +} diff --git a/samples/standalone/kotlin/http-server/src/test/resources/contracts/multipart/shouldWorkForMultipartWithContentType.kts b/samples/standalone/kotlin/http-server/src/test/resources/contracts/multipart/shouldWorkForMultipartWithContentType.kts new file mode 100644 index 0000000000..d79620df84 --- /dev/null +++ b/samples/standalone/kotlin/http-server/src/test/resources/contracts/multipart/shouldWorkForMultipartWithContentType.kts @@ -0,0 +1,49 @@ +/* + * Copyright 2013-2019 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 multipart + +import org.springframework.cloud.contract.spec.ContractDsl.Companion.contract +import org.springframework.cloud.contract.spec.internal.HttpMethods + +contract { + request { + method = method("POST") + url = url("/tests") + multipart = multipart(mapOf( + "file1" to named( + value(consumer(regex(nonEmpty())), producer("filename1")), + value(consumer(regex(nonEmpty())), producer("content1"))), + "file2" to named( + value(consumer(regex(nonEmpty())), producer("filename1")), + value(consumer(regex(nonEmpty())), producer("content2"))), + "test" to named( + value(consumer(regex(nonEmpty())), producer("filename1")), + value(consumer(regex(nonEmpty())), producer(file("test.json"))), + value("application/json")) + )) + headers { + contentType("multipart/form-data") + } + } + response { + status = code(200) + body = body("status" to "ok") + headers { + contentType("application/json") + } + } +} diff --git a/samples/standalone/kotlin/http-server/src/test/resources/contracts/multipart/test.json b/samples/standalone/kotlin/http-server/src/test/resources/contracts/multipart/test.json new file mode 100644 index 0000000000..984c08fbdf --- /dev/null +++ b/samples/standalone/kotlin/http-server/src/test/resources/contracts/multipart/test.json @@ -0,0 +1,3 @@ +{ + "status": "test" +} diff --git a/samples/standalone/kotlin/pom.xml b/samples/standalone/kotlin/pom.xml new file mode 100644 index 0000000000..5303170231 --- /dev/null +++ b/samples/standalone/kotlin/pom.xml @@ -0,0 +1,42 @@ + + + 4.0.0 + + + org.springframework.cloud + spring-cloud-contract-samples-standalone + 2.2.0.BUILD-SNAPSHOT + .. + + + spring-cloud-contract-samples-kotlin + pom + + Spring Cloud Contract Standalone Dsl Test Samples + Spring Cloud Contract Standalone Test Samples used for end to end tests + + + + 2.2.0.BUILD-SNAPSHOT + + + + http-server + http-client + + + + + + maven-deploy-plugin + 2.8.2 + + true + + + + + + diff --git a/samples/standalone/pom.xml b/samples/standalone/pom.xml index b5eb7912fe..bcc27de7f0 100644 --- a/samples/standalone/pom.xml +++ b/samples/standalone/pom.xml @@ -30,6 +30,7 @@ pact webclient yml + kotlin