Sync docs from v1.2.7.RELEASE to gh-pages

This commit is contained in:
buildmaster
2019-05-23 16:49:52 +00:00
parent 3708fbf69d
commit 0eaca4243f
126 changed files with 32802 additions and 0 deletions

View File

@@ -0,0 +1,35 @@
/*
code highlight CSS resemblign the Eclipse IDE default color schema
@author Costin Leau
*/
.hl-keyword {
color: #7F0055;
font-weight: bold;
}
.hl-comment {
color: #3F5F5F;
font-style: italic;
}
.hl-multiline-comment {
color: #3F5FBF;
font-style: italic;
}
.hl-tag {
color: #3F7F7F;
}
.hl-attribute {
color: #7F007F;
}
.hl-value {
color: #2A00FF;
}
.hl-string {
color: #2A00FF;
}

View File

@@ -0,0 +1,9 @@
@IMPORT url("manual.css");
body.firstpage {
background: url("../images/background.png") no-repeat center top;
}
div.part h1 {
border-top: none;
}

View File

@@ -0,0 +1,6 @@
@IMPORT url("manual.css");
body {
background: url("../images/background.png") no-repeat center top;
}

View File

@@ -0,0 +1,344 @@
@IMPORT url("highlight.css");
html {
padding: 0pt;
margin: 0pt;
}
body {
color: #333333;
margin: 15px 30px;
font-family: Helvetica, Arial, Freesans, Clean, Sans-serif;
line-height: 1.6;
-webkit-font-smoothing: antialiased;
}
code {
font-size: 16px;
font-family: Consolas, "Liberation Mono", Courier, monospace;
}
:not(a)>code {
color: #6D180B;
}
:not(pre)>code {
background-color: #F2F2F2;
border: 1px solid #CCCCCC;
border-radius: 4px;
padding: 1px 3px 0;
text-shadow: none;
white-space: nowrap;
}
body>*:first-child {
margin-top: 0 !important;
}
div {
margin: 0pt;
}
hr {
border: 1px solid #CCCCCC;
background: #CCCCCC;
}
h1,h2,h3,h4,h5,h6 {
color: #000000;
cursor: text;
font-weight: bold;
margin: 30px 0 10px;
padding: 0;
}
h1,h2,h3 {
margin: 40px 0 10px;
}
h1 {
margin: 70px 0 30px;
padding-top: 20px;
}
div.part h1 {
border-top: 1px dotted #CCCCCC;
}
h1,h1 code {
font-size: 32px;
}
h2,h2 code {
font-size: 24px;
}
h3,h3 code {
font-size: 20px;
}
h4,h1 code,h5,h5 code,h6,h6 code {
font-size: 18px;
}
div.book,div.chapter,div.appendix,div.part,div.preface {
min-width: 300px;
max-width: 1200px;
margin: 0 auto;
}
p.releaseinfo {
font-weight: bold;
margin-bottom: 40px;
margin-top: 40px;
}
div.authorgroup {
line-height: 1;
}
p.copyright {
line-height: 1;
margin-bottom: -5px;
}
.legalnotice p {
font-style: italic;
font-size: 14px;
line-height: 1;
}
div.titlepage+p,div.titlepage+p {
margin-top: 0;
}
pre {
line-height: 1.0;
color: black;
}
a {
color: #4183C4;
text-decoration: none;
}
p {
margin: 15px 0;
text-align: left;
}
ul,ol {
padding-left: 30px;
}
li p {
margin: 0;
}
div.table {
margin: 1em;
padding: 0.5em;
text-align: center;
}
div.table table,div.informaltable table {
display: table;
width: 100%;
}
div.table td {
padding-left: 7px;
padding-right: 7px;
}
.sidebar {
line-height: 1.4;
padding: 0 20px;
background-color: #F8F8F8;
border: 1px solid #CCCCCC;
border-radius: 3px 3px 3px 3px;
}
.sidebar p.title {
color: #6D180B;
}
pre.programlisting,pre.screen {
font-size: 15px;
padding: 6px 10px;
background-color: #F8F8F8;
border: 1px solid #CCCCCC;
border-radius: 3px 3px 3px 3px;
clear: both;
overflow: auto;
line-height: 1.4;
font-family: Consolas, "Liberation Mono", Courier, monospace;
}
table {
border-collapse: collapse;
border-spacing: 0;
border: 1px solid #DDDDDD !important;
border-radius: 4px !important;
border-collapse: separate !important;
line-height: 1.6;
}
table thead {
background: #F5F5F5;
}
table tr {
border: none;
border-bottom: none;
}
table th {
font-weight: bold;
}
table th,table td {
border: none !important;
padding: 6px 13px;
}
table tr:nth-child(2n) {
background-color: #F8F8F8;
}
td p {
margin: 0 0 15px 0;
}
div.table-contents td p {
margin: 0;
}
div.important *,div.note *,div.tip *,div.warning *,div.navheader *,div.navfooter *,div.calloutlist *
{
border: none !important;
background: none !important;
margin: 0;
}
div.important p,div.note p,div.tip p,div.warning p {
color: #6F6F6F;
line-height: 1.6;
}
div.important code,div.note code,div.tip code,div.warning code {
background-color: #F2F2F2 !important;
border: 1px solid #CCCCCC !important;
border-radius: 4px !important;
padding: 1px 3px 0 !important;
text-shadow: none !important;
white-space: nowrap !important;
}
.note th,.tip th,.warning th {
display: none;
}
.note tr:first-child td,.tip tr:first-child td,.warning tr:first-child td
{
border-right: 1px solid #CCCCCC !important;
padding-top: 10px;
}
div.calloutlist p,div.calloutlist td {
padding: 0;
margin: 0;
}
div.calloutlist>table>tbody>tr>td:first-child {
padding-left: 10px;
width: 30px !important;
}
div.important,div.note,div.tip,div.warning {
margin-left: 0px !important;
margin-right: 20px !important;
margin-top: 20px;
margin-bottom: 20px;
padding-top: 10px;
padding-bottom: 10px;
}
div.toc {
line-height: 1.2;
}
dl,dt {
margin-top: 1px;
margin-bottom: 0;
}
div.toc>dl>dt {
font-size: 32px;
font-weight: bold;
margin: 30px 0 10px 0;
display: block;
}
div.toc>dl>dd>dl>dt {
font-size: 24px;
font-weight: bold;
margin: 20px 0 10px 0;
display: block;
}
div.toc>dl>dd>dl>dd>dl>dt {
font-weight: bold;
font-size: 20px;
margin: 10px 0 0 0;
}
tbody.footnotes * {
border: none !important;
}
div.footnote p {
margin: 0;
line-height: 1;
}
div.footnote p sup {
margin-right: 6px;
vertical-align: middle;
}
div.navheader {
border-bottom: 1px solid #CCCCCC;
}
div.navfooter {
border-top: 1px solid #CCCCCC;
}
.title {
margin-left: -1em;
padding-left: 1em;
}
.title>a {
position: absolute;
visibility: hidden;
display: block;
font-size: 0.85em;
margin-top: 0.05em;
margin-left: -1em;
vertical-align: text-top;
color: black;
}
.title>a:before {
content: "\00A7";
}
.title:hover>a,.title>a:hover,.title:hover>a:hover {
visibility: visible;
}
.title:focus>a,.title>a:focus,.title:focus>a:focus {
outline: 0;
}

View File

@@ -0,0 +1,330 @@
#!/bin/bash -x
set -e
# Set default props like MAVEN_PATH, ROOT_FOLDER etc.
function set_default_props() {
# The script should be executed from the root folder
ROOT_FOLDER=`pwd`
echo "Current folder is ${ROOT_FOLDER}"
if [[ ! -e "${ROOT_FOLDER}/.git" ]]; then
echo "You're not in the root folder of the project!"
exit 1
fi
# Prop that will let commit the changes
COMMIT_CHANGES="no"
MAVEN_PATH=${MAVEN_PATH:-}
echo "Path to Maven is [${MAVEN_PATH}]"
REPO_NAME=${PWD##*/}
echo "Repo name is [${REPO_NAME}]"
SPRING_CLOUD_STATIC_REPO=${SPRING_CLOUD_STATIC_REPO:-git@github.com:spring-cloud/spring-cloud-static.git}
echo "Spring Cloud Static repo is [${SPRING_CLOUD_STATIC_REPO}"
}
# Check if gh-pages exists and docs have been built
function check_if_anything_to_sync() {
git remote set-url --push origin `git config remote.origin.url | sed -e 's/^git:/https:/'`
if ! (git remote set-branches --add origin gh-pages && git fetch -q); then
echo "No gh-pages, so not syncing"
exit 0
fi
if ! [ -d docs/target/generated-docs ] && ! [ "${BUILD}" == "yes" ]; then
echo "No gh-pages sources in docs/target/generated-docs, so not syncing"
exit 0
fi
}
function retrieve_current_branch() {
# Code getting the name of the current branch. For master we want to publish as we did until now
# https://stackoverflow.com/questions/1593051/how-to-programmatically-determine-the-current-checked-out-git-branch
# If there is a branch already passed will reuse it - otherwise will try to find it
CURRENT_BRANCH=${BRANCH}
if [[ -z "${CURRENT_BRANCH}" ]] ; then
CURRENT_BRANCH=$(git symbolic-ref -q HEAD)
CURRENT_BRANCH=${CURRENT_BRANCH##refs/heads/}
CURRENT_BRANCH=${CURRENT_BRANCH:-HEAD}
fi
echo "Current branch is [${CURRENT_BRANCH}]"
git checkout ${CURRENT_BRANCH} || echo "Failed to check the branch... continuing with the script"
}
# Switches to the provided value of the release version. We always prefix it with `v`
function switch_to_tag() {
git checkout v${VERSION}
}
# Build the docs if switch is on
function build_docs_if_applicable() {
if [[ "${BUILD}" == "yes" ]] ; then
./mvnw clean install -P docs -pl docs -DskipTests
fi
}
# Get the name of the `docs.main` property
# Get whitelisted branches - assumes that a `docs` module is available under `docs` profile
function retrieve_doc_properties() {
MAIN_ADOC_VALUE=$("${MAVEN_PATH}"mvn -q \
-Dexec.executable="echo" \
-Dexec.args='${docs.main}' \
--non-recursive \
org.codehaus.mojo:exec-maven-plugin:1.3.1:exec)
echo "Extracted 'main.adoc' from Maven build [${MAIN_ADOC_VALUE}]"
WHITELIST_PROPERTY=${WHITELIST_PROPERTY:-"docs.whitelisted.branches"}
WHITELISTED_BRANCHES_VALUE=$("${MAVEN_PATH}"mvn -q \
-Dexec.executable="echo" \
-Dexec.args="\${${WHITELIST_PROPERTY}}" \
org.codehaus.mojo:exec-maven-plugin:1.3.1:exec \
-P docs \
-pl docs)
echo "Extracted '${WHITELIST_PROPERTY}' from Maven build [${WHITELISTED_BRANCHES_VALUE}]"
}
# Stash any outstanding changes
function stash_changes() {
git diff-index --quiet HEAD && dirty=$? || (echo "Failed to check if the current repo is dirty. Assuming that it is." && dirty="1")
if [ "$dirty" != "0" ]; then git stash; fi
}
# Switch to gh-pages branch to sync it with current branch
function add_docs_from_target() {
local DESTINATION_REPO_FOLDER
if [[ -z "${DESTINATION}" && -z "${CLONE}" ]] ; then
DESTINATION_REPO_FOLDER=${ROOT_FOLDER}
elif [[ "${CLONE}" == "yes" ]]; then
mkdir -p ${ROOT_FOLDER}/target
local clonedStatic=${ROOT_FOLDER}/target/spring-cloud-static
if [[ ! -e "${clonedStatic}/.git" ]]; then
echo "Cloning Spring Cloud Static to target"
git clone ${SPRING_CLOUD_STATIC_REPO} ${clonedStatic} && git checkout gh-pages
else
echo "Spring Cloud Static already cloned - will pull changes"
cd ${clonedStatic} && git checkout gh-pages && git pull origin gh-pages
fi
DESTINATION_REPO_FOLDER=${clonedStatic}/${REPO_NAME}
mkdir -p ${DESTINATION_REPO_FOLDER}
else
if [[ ! -e "${DESTINATION}/.git" ]]; then
echo "[${DESTINATION}] is not a git repository"
exit 1
fi
DESTINATION_REPO_FOLDER=${DESTINATION}/${REPO_NAME}
mkdir -p ${DESTINATION_REPO_FOLDER}
echo "Destination was provided [${DESTINATION}]"
fi
cd ${DESTINATION_REPO_FOLDER}
git checkout gh-pages
git pull origin gh-pages
# Add git branches
###################################################################
if [[ -z "${VERSION}" ]] ; then
copy_docs_for_current_version
else
copy_docs_for_provided_version
fi
commit_changes_if_applicable
}
# Copies the docs by using the retrieved properties from Maven build
function copy_docs_for_current_version() {
if [[ "${CURRENT_BRANCH}" == "master" ]] ; then
echo -e "Current branch is master - will copy the current docs only to the root folder"
for f in docs/target/generated-docs/*; do
file=${f#docs/target/generated-docs/*}
if ! git ls-files -i -o --exclude-standard --directory | grep -q ^$file$; then
# Not ignored...
cp -rf $f ${ROOT_FOLDER}/
git add -A ${ROOT_FOLDER}/$file
fi
done
COMMIT_CHANGES="yes"
else
echo -e "Current branch is [${CURRENT_BRANCH}]"
# https://stackoverflow.com/questions/29300806/a-bash-script-to-check-if-a-string-is-present-in-a-comma-separated-list-of-strin
if [[ ",${WHITELISTED_BRANCHES_VALUE}," = *",${CURRENT_BRANCH},"* ]] ; then
mkdir -p ${ROOT_FOLDER}/${CURRENT_BRANCH}
echo -e "Branch [${CURRENT_BRANCH}] is whitelisted! Will copy the current docs to the [${CURRENT_BRANCH}] folder"
for f in docs/target/generated-docs/*; do
file=${f#docs/target/generated-docs/*}
if ! git ls-files -i -o --exclude-standard --directory | grep -q ^$file$; then
# Not ignored...
# We want users to access 1.0.0.RELEASE/ instead of 1.0.0.RELEASE/spring-cloud.sleuth.html
if [[ "${file}" == "${MAIN_ADOC_VALUE}.html" ]] ; then
# We don't want to copy the spring-cloud-sleuth.html
# we want it to be converted to index.html
cp -rf $f ${ROOT_FOLDER}/${CURRENT_BRANCH}/index.html
git add -A ${ROOT_FOLDER}/${CURRENT_BRANCH}/index.html
else
cp -rf $f ${ROOT_FOLDER}/${CURRENT_BRANCH}
git add -A ${ROOT_FOLDER}/${CURRENT_BRANCH}/$file
fi
fi
done
COMMIT_CHANGES="yes"
else
echo -e "Branch [${CURRENT_BRANCH}] is not on the white list! Check out the Maven [${WHITELIST_PROPERTY}] property in
[docs] module available under [docs] profile. Won't commit any changes to gh-pages for this branch."
fi
fi
}
# Copies the docs by using the explicitly provided version
function copy_docs_for_provided_version() {
local FOLDER=${DESTINATION_REPO_FOLDER}/${VERSION}
mkdir -p ${FOLDER}
echo -e "Current tag is [v${VERSION}] Will copy the current docs to the [${FOLDER}] folder"
for f in ${ROOT_FOLDER}/docs/target/generated-docs/*; do
file=${f#${ROOT_FOLDER}/docs/target/generated-docs/*}
copy_docs_for_branch ${file} ${FOLDER}
done
COMMIT_CHANGES="yes"
CURRENT_BRANCH="v${VERSION}"
}
# Copies the docs from target to the provided destination
# Params:
# $1 - file from target
# $2 - destination to which copy the files
function copy_docs_for_branch() {
local file=$1
local destination=$2
if ! git ls-files -i -o --exclude-standard --directory | grep -q ^${file}$; then
# Not ignored...
# We want users to access 1.0.0.RELEASE/ instead of 1.0.0.RELEASE/spring-cloud.sleuth.html
if [[ ("${file}" == "${MAIN_ADOC_VALUE}.html") || ("${file}" == "${REPO_NAME}.html") ]] ; then
# We don't want to copy the spring-cloud-sleuth.html
# we want it to be converted to index.html
cp -rf $f ${destination}/index.html
git add -A ${destination}/index.html
else
cp -rf $f ${destination}
git add -A ${destination}/$file
fi
fi
}
function commit_changes_if_applicable() {
if [[ "${COMMIT_CHANGES}" == "yes" ]] ; then
COMMIT_SUCCESSFUL="no"
git commit -a -m "Sync docs from ${CURRENT_BRANCH} to gh-pages" && COMMIT_SUCCESSFUL="yes" || echo "Failed to commit changes"
# Uncomment the following push if you want to auto push to
# the gh-pages branch whenever you commit to master locally.
# This is a little extreme. Use with care!
###################################################################
if [[ "${COMMIT_SUCCESSFUL}" == "yes" ]] ; then
git push origin gh-pages
fi
fi
}
# Switch back to the previous branch and exit block
function checkout_previous_branch() {
# If -version was provided we need to come back to root project
cd ${ROOT_FOLDER}
git checkout ${CURRENT_BRANCH} || echo "Failed to check the branch... continuing with the script"
if [ "$dirty" != "0" ]; then git stash pop; fi
exit 0
}
# Assert if properties have been properly passed
function assert_properties() {
echo "VERSION [${VERSION}], DESTINATION [${DESTINATION}], CLONE [${CLONE}]"
if [[ "${VERSION}" != "" && (-z "${DESTINATION}" && -z "${CLONE}") ]] ; then echo "Version was set but destination / clone was not!"; exit 1;fi
if [[ ("${DESTINATION}" != "" && "${CLONE}" != "") && -z "${VERSION}" ]] ; then echo "Destination / clone was set but version was not!"; exit 1;fi
if [[ "${DESTINATION}" != "" && "${CLONE}" == "yes" ]] ; then echo "Destination and clone was set. Pick one!"; exit 1;fi
}
# Prints the usage
function print_usage() {
cat <<EOF
The idea of this script is to update gh-pages branch with the generated docs. Without any options
the script will work in the following manner:
- if there's no gh-pages / target for docs module then the script ends
- for master branch the generated docs are copied to the root of gh-pages branch
- for any other branch (if that branch is whitelisted) a subfolder with branch name is created
and docs are copied there
- if the version switch is passed (-v) then a tag with (v) prefix will be retrieved and a folder
with that version number will be created in the gh-pages branch. WARNING! No whitelist verification will take place
- if the destination switch is passed (-d) then the script will check if the provided dir is a git repo and then will
switch to gh-pages of that repo and copy the generated docs to `docs/<project-name>/<version>`
- if the destination switch is passed (-d) then the script will check if the provided dir is a git repo and then will
switch to gh-pages of that repo and copy the generated docs to `docs/<project-name>/<version>`
USAGE:
You can use the following options:
-v|--version - the script will apply the whole procedure for a particular library version
-d|--destination - the root of destination folder where the docs should be copied. You have to use the full path.
E.g. point to spring-cloud-static folder. Can't be used with (-c)
-b|--build - will run the standard build process after checking out the branch
-c|--clone - will automatically clone the spring-cloud-static repo instead of providing the destination.
Obviously can't be used with (-d)
EOF
}
# ==========================================
# ____ ____ _____ _____ _____ _______
# / ____|/ ____| __ \|_ _| __ \__ __|
# | (___ | | | |__) | | | | |__) | | |
# \___ \| | | _ / | | | ___/ | |
# ____) | |____| | \ \ _| |_| | | |
# |_____/ \_____|_| \_\_____|_| |_|
#
# ==========================================
while [[ $# > 0 ]]
do
key="$1"
case ${key} in
-v|--version)
VERSION="$2"
shift # past argument
;;
-d|--destination)
DESTINATION="$2"
shift # past argument
;;
-b|--build)
BUILD="yes"
;;
-c|--clone)
CLONE="yes"
;;
-h|--help)
print_usage
exit 0
;;
*)
echo "Invalid option: [$1]"
print_usage
exit 1
;;
esac
shift # past argument or value
done
assert_properties
set_default_props
check_if_anything_to_sync
if [[ -z "${VERSION}" ]] ; then
retrieve_current_branch
else
switch_to_tag
fi
build_docs_if_applicable
retrieve_doc_properties
stash_changes
add_docs_from_target
checkout_previous_branch

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 350 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 931 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -0,0 +1,117 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 1.5.5">
<title>spring-cloud-contract</title>
<link rel="stylesheet" href="css/manual-singlepage.css">
<style>
.hidden {
display: none;
}
.switch {
border-width: 1px 1px 0 1px;
border-style: solid;
border-color: #7a2518;
display: inline-block;
}
.switch--item {
padding: 10px;
background-color: #ffffff;
color: #7a2518;
display: inline-block;
cursor: pointer;
}
.switch--item.selected {
background-color: #7a2519;
color: #ffffff;
}
</style>
<script src="http://cdnjs.cloudflare.com/ajax/libs/zepto/1.2.0/zepto.min.js"></script>
<script type="text/javascript">
function addBlockSwitches() {
$('.primary').each(function() {
primary = $(this);
createSwitchItem(primary, createBlockSwitch(primary)).item.addClass("selected");
primary.children('.title').remove();
});
$('.secondary').each(function(idx, node) {
secondary = $(node);
primary = findPrimary(secondary);
switchItem = createSwitchItem(secondary, primary.children('.switch'));
switchItem.content.addClass('hidden');
findPrimary(secondary).append(switchItem.content);
secondary.remove();
});
}
function createBlockSwitch(primary) {
blockSwitch = $('<div class="switch"></div>');
primary.prepend(blockSwitch);
return blockSwitch;
}
function findPrimary(secondary) {
candidate = secondary.prev();
while (!candidate.is('.primary')) {
candidate = candidate.prev();
}
return candidate;
}
function createSwitchItem(block, blockSwitch) {
blockName = block.children('.title').text();
content = block.children('.content').first().append(block.next('.colist'));
item = $('<div class="switch--item">' + blockName + '</div>');
item.on('click', '', content, function(e) {
$(this).addClass('selected');
$(this).siblings().removeClass('selected');
e.data.siblings('.content').addClass('hidden');
e.data.removeClass('hidden');
});
blockSwitch.append(item);
return {'item': item, 'content': content};
}
$(addBlockSwitches);
</script>
</head>
<body class="article">
<div id="header">
<h1>spring-cloud-contract</h1>
</div>
<div id="content">
<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>1.2.7.RELEASE</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_pick_the_documentation_option">Pick The Documentation Option</h2>
<div class="sectionbody">
<div class="ulist">
<ul>
<li>
<p><a href="single/spring-cloud-contract.html">Single HTML</a></p>
</li>
<li>
<p><a href="multi/multi_spring-cloud-contract.html">Multi HTML</a></p>
</li>
</ul>
</div>
</div>
</div>
</div>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.js"></script>
<script>prettyPrint()</script>
</body>
</html>

View File

@@ -0,0 +1,35 @@
/*
code highlight CSS resemblign the Eclipse IDE default color schema
@author Costin Leau
*/
.hl-keyword {
color: #7F0055;
font-weight: bold;
}
.hl-comment {
color: #3F5F5F;
font-style: italic;
}
.hl-multiline-comment {
color: #3F5FBF;
font-style: italic;
}
.hl-tag {
color: #3F7F7F;
}
.hl-attribute {
color: #7F007F;
}
.hl-value {
color: #2A00FF;
}
.hl-string {
color: #2A00FF;
}

View File

@@ -0,0 +1,9 @@
@IMPORT url("manual.css");
body.firstpage {
background: url("../images/background.png") no-repeat center top;
}
div.part h1 {
border-top: none;
}

View File

@@ -0,0 +1,6 @@
@IMPORT url("manual.css");
body {
background: url("../images/background.png") no-repeat center top;
}

View File

@@ -0,0 +1,344 @@
@IMPORT url("highlight.css");
html {
padding: 0pt;
margin: 0pt;
}
body {
color: #333333;
margin: 15px 30px;
font-family: Helvetica, Arial, Freesans, Clean, Sans-serif;
line-height: 1.6;
-webkit-font-smoothing: antialiased;
}
code {
font-size: 16px;
font-family: Consolas, "Liberation Mono", Courier, monospace;
}
:not(a)>code {
color: #6D180B;
}
:not(pre)>code {
background-color: #F2F2F2;
border: 1px solid #CCCCCC;
border-radius: 4px;
padding: 1px 3px 0;
text-shadow: none;
white-space: nowrap;
}
body>*:first-child {
margin-top: 0 !important;
}
div {
margin: 0pt;
}
hr {
border: 1px solid #CCCCCC;
background: #CCCCCC;
}
h1,h2,h3,h4,h5,h6 {
color: #000000;
cursor: text;
font-weight: bold;
margin: 30px 0 10px;
padding: 0;
}
h1,h2,h3 {
margin: 40px 0 10px;
}
h1 {
margin: 70px 0 30px;
padding-top: 20px;
}
div.part h1 {
border-top: 1px dotted #CCCCCC;
}
h1,h1 code {
font-size: 32px;
}
h2,h2 code {
font-size: 24px;
}
h3,h3 code {
font-size: 20px;
}
h4,h1 code,h5,h5 code,h6,h6 code {
font-size: 18px;
}
div.book,div.chapter,div.appendix,div.part,div.preface {
min-width: 300px;
max-width: 1200px;
margin: 0 auto;
}
p.releaseinfo {
font-weight: bold;
margin-bottom: 40px;
margin-top: 40px;
}
div.authorgroup {
line-height: 1;
}
p.copyright {
line-height: 1;
margin-bottom: -5px;
}
.legalnotice p {
font-style: italic;
font-size: 14px;
line-height: 1;
}
div.titlepage+p,div.titlepage+p {
margin-top: 0;
}
pre {
line-height: 1.0;
color: black;
}
a {
color: #4183C4;
text-decoration: none;
}
p {
margin: 15px 0;
text-align: left;
}
ul,ol {
padding-left: 30px;
}
li p {
margin: 0;
}
div.table {
margin: 1em;
padding: 0.5em;
text-align: center;
}
div.table table,div.informaltable table {
display: table;
width: 100%;
}
div.table td {
padding-left: 7px;
padding-right: 7px;
}
.sidebar {
line-height: 1.4;
padding: 0 20px;
background-color: #F8F8F8;
border: 1px solid #CCCCCC;
border-radius: 3px 3px 3px 3px;
}
.sidebar p.title {
color: #6D180B;
}
pre.programlisting,pre.screen {
font-size: 15px;
padding: 6px 10px;
background-color: #F8F8F8;
border: 1px solid #CCCCCC;
border-radius: 3px 3px 3px 3px;
clear: both;
overflow: auto;
line-height: 1.4;
font-family: Consolas, "Liberation Mono", Courier, monospace;
}
table {
border-collapse: collapse;
border-spacing: 0;
border: 1px solid #DDDDDD !important;
border-radius: 4px !important;
border-collapse: separate !important;
line-height: 1.6;
}
table thead {
background: #F5F5F5;
}
table tr {
border: none;
border-bottom: none;
}
table th {
font-weight: bold;
}
table th,table td {
border: none !important;
padding: 6px 13px;
}
table tr:nth-child(2n) {
background-color: #F8F8F8;
}
td p {
margin: 0 0 15px 0;
}
div.table-contents td p {
margin: 0;
}
div.important *,div.note *,div.tip *,div.warning *,div.navheader *,div.navfooter *,div.calloutlist *
{
border: none !important;
background: none !important;
margin: 0;
}
div.important p,div.note p,div.tip p,div.warning p {
color: #6F6F6F;
line-height: 1.6;
}
div.important code,div.note code,div.tip code,div.warning code {
background-color: #F2F2F2 !important;
border: 1px solid #CCCCCC !important;
border-radius: 4px !important;
padding: 1px 3px 0 !important;
text-shadow: none !important;
white-space: nowrap !important;
}
.note th,.tip th,.warning th {
display: none;
}
.note tr:first-child td,.tip tr:first-child td,.warning tr:first-child td
{
border-right: 1px solid #CCCCCC !important;
padding-top: 10px;
}
div.calloutlist p,div.calloutlist td {
padding: 0;
margin: 0;
}
div.calloutlist>table>tbody>tr>td:first-child {
padding-left: 10px;
width: 30px !important;
}
div.important,div.note,div.tip,div.warning {
margin-left: 0px !important;
margin-right: 20px !important;
margin-top: 20px;
margin-bottom: 20px;
padding-top: 10px;
padding-bottom: 10px;
}
div.toc {
line-height: 1.2;
}
dl,dt {
margin-top: 1px;
margin-bottom: 0;
}
div.toc>dl>dt {
font-size: 32px;
font-weight: bold;
margin: 30px 0 10px 0;
display: block;
}
div.toc>dl>dd>dl>dt {
font-size: 24px;
font-weight: bold;
margin: 20px 0 10px 0;
display: block;
}
div.toc>dl>dd>dl>dd>dl>dt {
font-weight: bold;
font-size: 20px;
margin: 10px 0 0 0;
}
tbody.footnotes * {
border: none !important;
}
div.footnote p {
margin: 0;
line-height: 1;
}
div.footnote p sup {
margin-right: 6px;
vertical-align: middle;
}
div.navheader {
border-bottom: 1px solid #CCCCCC;
}
div.navfooter {
border-top: 1px solid #CCCCCC;
}
.title {
margin-left: -1em;
padding-left: 1em;
}
.title>a {
position: absolute;
visibility: hidden;
display: block;
font-size: 0.85em;
margin-top: 0.05em;
margin-left: -1em;
vertical-align: text-top;
color: black;
}
.title>a:before {
content: "\00A7";
}
.title:hover>a,.title>a:hover,.title:hover>a:hover {
visibility: visible;
}
.title:focus>a,.title>a:focus,.title:focus>a:focus {
outline: 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 350 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 931 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,217 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>9.&nbsp;Customization</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud-contract.html" title="Spring Cloud Contract"><link rel="up" href="multi_spring-cloud-contract.html" title="Spring Cloud Contract"><link rel="prev" href="multi__contract_dsl.html" title="8.&nbsp;Contract DSL"><link rel="next" href="multi__using_the_pluggable_architecture.html" title="10.&nbsp;Using the Pluggable Architecture"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">9.&nbsp;Customization</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__contract_dsl.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi__using_the_pluggable_architecture.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_customization" href="#_customization"></a>9.&nbsp;Customization</h1></div></div></div><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>This section is valid only for Groovy DSL</p></td></tr></table></div><p>You can customize the Spring Cloud Contract Verifier by extending the DSL, as shown in
the remainder of this section.</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_extending_the_dsl" href="#_extending_the_dsl"></a>9.1&nbsp;Extending the DSL</h2></div></div></div><p>You can provide your own functions to the DSL. The key requirement for this feature is to
maintain the static compatibility. Later in this document, you can see examples of:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Creating a JAR with reusable classes.</li><li class="listitem">Referencing of these classes in the DSLs.</li></ul></div><p>You can find the full example
<a class="link" href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples" target="_top">here</a>.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_common_jar" href="#_common_jar"></a>9.1.1&nbsp;Common JAR</h3></div></div></div><p>The following examples show three classes that can be reused in the DSLs.</p><p><span class="strong"><strong>PatternUtils</strong></span> contains functions used by both the <span class="strong"><strong>consumer</strong></span> and the <span class="strong"><strong>producer</strong></span>.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">package</span> com.example;
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> java.util.regex.Pattern;
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
* If you want to use {@link Pattern} directly in your tests
* then you can create a class resembling this one. It can
* contain all the {@link Pattern} you want to use in the DSL.
*
* &lt;pre&gt;
* {@code
* request {
* body(
* [ age: $(c(PatternUtils.oldEnough()))]
* )
* }
* &lt;/pre&gt;
*
* Notice that we're using both {@code $()} for dynamic values
* and {@code c()} for the consumer side.
*
* @author Marcin Grzejszczak
*/</xslthl:doccomment>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//tag::impl[]</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> PatternUtils {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> String tooYoung() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//remove::start[]</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"[0-1][0-9]"</span>;
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//remove::end[return]</span>
}
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> Pattern oldEnough() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//remove::start[]</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> Pattern.compile(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"[2-9][0-9]"</span>);
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//remove::end[return]</span>
}
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
* Makes little sense but it's just an example ;)
*/</xslthl:doccomment>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> Pattern ok() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//remove::start[]</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> Pattern.compile(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"OK"</span>);
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//remove::end[return]</span>
}
}
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//end::impl[]</span></pre><p><span class="strong"><strong>ConsumerUtils</strong></span> contains functions used by the <span class="strong"><strong>consumer</strong></span>.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">package</span> com.example;
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.cloud.contract.spec.internal.ClientDslProperty;
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
* DSL Properties passed to the DSL from the consumer's perspective.
* That means that on the input side {@code Request} for HTTP
* or {@code Input} for messaging you can have a regular expression.
* On the {@code Response} for HTTP or {@code Output} for messaging
* you have to have a concrete value.
*
* @author Marcin Grzejszczak
*/</xslthl:doccomment>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//tag::impl[]</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> ConsumerUtils {
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
* Consumer side property. By using the {@link ClientDslProperty}
* you can omit most of boilerplate code from the perspective
* of dynamic values. Example
*
* &lt;pre&gt;
* {@code
* request {
* body(
* [ age: $(ConsumerUtils.oldEnough())]
* )
* }
* &lt;/pre&gt;
*
* That way it's in the implementation that we decide what value we will pass to the consumer
* and which one to the producer.
*
* @author Marcin Grzejszczak
*/</xslthl:doccomment>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> ClientDslProperty oldEnough() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//remove::start[]</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// this example is not the best one and</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// theoretically you could just pass the regex instead of `ServerDslProperty` but</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// it's just to show some new tricks :)</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> ClientDslProperty(PatternUtils.oldEnough(), <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">40</xslthl:number>);
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//remove::end[return]</span>
}
}
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//end::impl[]</span></pre><p><span class="strong"><strong>ProducerUtils</strong></span> contains functions used by the <span class="strong"><strong>producer</strong></span>.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">package</span> com.example;
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.cloud.contract.spec.internal.ServerDslProperty;
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
* DSL Properties passed to the DSL from the producer's perspective.
* That means that on the input side {@code Request} for HTTP
* or {@code Input} for messaging you have to have a concrete value.
* On the {@code Response} for HTTP or {@code Output} for messaging
* you can have a regular expression.
*
* @author Marcin Grzejszczak
*/</xslthl:doccomment>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//tag::impl[]</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> ProducerUtils {
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
* Producer side property. By using the {@link ProducerUtils}
* you can omit most of boilerplate code from the perspective
* of dynamic values. Example
*
* &lt;pre&gt;
* {@code
* response {
* body(
* [ status: $(ProducerUtils.ok())]
* )
* }
* &lt;/pre&gt;
*
* That way it's in the implementation that we decide what value we will pass to the consumer
* and which one to the producer.
*/</xslthl:doccomment>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> ServerDslProperty ok() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// this example is not the best one and</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// theoretically you could just pass the regex instead of `ServerDslProperty` but</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// it's just to show some new tricks :)</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> ServerDslProperty( PatternUtils.ok(), <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"OK"</span>);
}
}
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//end::impl[]</span></pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_adding_the_dependency_to_the_project" href="#_adding_the_dependency_to_the_project"></a>9.1.2&nbsp;Adding the Dependency to the Project</h3></div></div></div><p>In order for the plugins and IDE to be able to reference the common JAR classes, you need
to pass the dependency to your project.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_test_the_dependency_in_the_project_s_dependencies" href="#_test_the_dependency_in_the_project_s_dependencies"></a>9.1.3&nbsp;Test the Dependency in the Project&#8217;s Dependencies</h3></div></div></div><p>First, add the common jar dependency as a test dependency. Because your contracts files
are available on the test resources path, the common jar classes automatically become
visible in your Groovy files. The following examples show how to test the dependency:</p><p class="primary"><b>Maven.&nbsp;</b>
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;dependency&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>com.example<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>beer-common<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;version&gt;</span>${project.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/version&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;scope&gt;</span>test<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/scope&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/dependency&gt;</span></pre><p class="primary">
</p><p class="secondary"><b>Gradle.&nbsp;</b>
</p><pre class="programlisting">testCompile(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"com.example:beer-common:0.0.1.BUILD-SNAPSHOT"</span>)</pre><p class="secondary">
</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_test_a_dependency_in_the_plugin_s_dependencies" href="#_test_a_dependency_in_the_plugin_s_dependencies"></a>9.1.4&nbsp;Test a Dependency in the Plugin&#8217;s Dependencies</h3></div></div></div><p>Now, you must add the dependency for the plugin to reuse at runtime, as shown in the
following example:</p><p class="primary"><b>Maven.&nbsp;</b>
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;plugin&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>spring-cloud-contract-maven-plugin<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;version&gt;</span>${spring-cloud-contract.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/version&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;extensions&gt;</span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/extensions&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;configuration&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;packageWithBaseClasses&gt;</span>com.example<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/packageWithBaseClasses&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;baseClassMappings&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;baseClassMapping&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;contractPackageRegex&gt;</span>.*intoxication.*<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/contractPackageRegex&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;baseClassFQN&gt;</span>com.example.intoxication.BeerIntoxicationBase<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/baseClassFQN&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/baseClassMapping&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/baseClassMappings&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/configuration&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;dependencies&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;dependency&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>com.example<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>beer-common<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;version&gt;</span>${project.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/version&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;scope&gt;</span>compile<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/scope&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/dependency&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/dependencies&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/plugin&gt;</span></pre><p class="primary">
</p><p class="secondary"><b>Gradle.&nbsp;</b>
</p><pre class="programlisting">classpath <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"com.example:beer-common:0.0.1.BUILD-SNAPSHOT"</span></pre><p class="secondary">
</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_referencing_classes_in_dsls" href="#_referencing_classes_in_dsls"></a>9.1.5&nbsp;Referencing classes in DSLs</h3></div></div></div><p>You can now reference your classes in your DSL, as shown in the following example:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">package</span> contracts.beer.rest
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> com.example.ConsumerUtils
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> com.example.ProducerUtils
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.cloud.contract.spec.Contract
Contract.make {
description(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">""</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"
</span>Represents a successful scenario of getting a beer
```
given:
client is old enough
when:
he applies <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">for</span> a beer
then:
we<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'ll grant him the beer
</span>```
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">""</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">")
</span> request {
method <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'POST'</span>
url <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'/check'</span>
body(
age: $(ConsumerUtils.oldEnough())
)
headers {
contentType(applicationJson())
}
}
response {
status <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>
body(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">""</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"
</span> {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"status"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"${value(ProducerUtils.ok())}"</span>
}
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">""</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">")
</span> headers {
contentType(applicationJson())
}
}
}</pre></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__contract_dsl.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi__using_the_pluggable_architecture.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">8.&nbsp;Contract DSL&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-contract.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;10.&nbsp;Using the Pluggable Architecture</td></tr></table></div></body></html>

View File

@@ -0,0 +1,11 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>13.&nbsp;Links</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud-contract.html" title="Spring Cloud Contract"><link rel="up" href="multi_spring-cloud-contract.html" title="Spring Cloud Contract"><link rel="prev" href="multi__migrations.html" title="12.&nbsp;Migrations"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">13.&nbsp;Links</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__migrations.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;</td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_links" href="#_links"></a>13.&nbsp;Links</h1></div></div></div><p>The following links may be helpful when working with Spring Cloud Contract Verifier:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a class="link" href="https://github.com/spring-cloud/spring-cloud-contract/" target="_top">Spring Cloud Contract Github
Repository</a></li><li class="listitem"><a class="link" href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples/" target="_top">Spring Cloud
Contract Samples</a></li><li class="listitem"><a class="link" href="https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html" target="_top">Spring Cloud
Contract Documentation</a></li><li class="listitem"><a class="link" href="https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html/deprecated" target="_top">Accurest
Legacy Documentation</a></li><li class="listitem"><a class="link" href="https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html/#spring-cloud-contract-stub-runner" target="_top">Spring
Cloud Contract Stub Runner Documentation</a></li><li class="listitem"><a class="link" href="https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html/#stub-runner-for-messaging" target="_top">Spring
Cloud Contract Stub Runner Messaging Documentation</a></li><li class="listitem"><a class="link" href="https://gitter.im/spring-cloud/spring-cloud-contract" target="_top">Spring Cloud Contract Gitter</a></li><li class="listitem"><a class="link" href="https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract-maven-plugin/" target="_top">Spring
Cloud Contract Maven Plugin</a></li><li class="listitem"><a class="link" href="https://www.youtube.com/watch?v=sAAklvxmPmk" target="_top">Spring Cloud Contract WJUG Presentation by
Marcin Grzejszczak</a></li></ul></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__migrations.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;</td></tr><tr><td width="40%" align="left" valign="top">12.&nbsp;Migrations&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-contract.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;</td></tr></table></div></body></html>

View File

@@ -0,0 +1,95 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>12.&nbsp;Migrations</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud-contract.html" title="Spring Cloud Contract"><link rel="up" href="multi_spring-cloud-contract.html" title="Spring Cloud Contract"><link rel="prev" href="multi__spring_cloud_contract_wiremock.html" title="11.&nbsp;Spring Cloud Contract WireMock"><link rel="next" href="multi__links.html" title="13.&nbsp;Links"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">12.&nbsp;Migrations</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__spring_cloud_contract_wiremock.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi__links.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_migrations" href="#_migrations"></a>12.&nbsp;Migrations</h1></div></div></div><p>This section covers migrating from one version of Spring Cloud Contract Verifier to the
next version. It covers the following versions upgrade paths:</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="cloud-verifier-1.0-1.1" href="#cloud-verifier-1.0-1.1"></a>12.1&nbsp;1.0.x &#8594; 1.1.x</h2></div></div></div><p>This section covers upgrading from version 1.0 to version 1.1.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_new_structure_of_generated_stubs" href="#_new_structure_of_generated_stubs"></a>12.1.1&nbsp;New structure of generated stubs</h3></div></div></div><p>In <code class="literal">1.1.x</code> we have introduced a change to the structure of generated stubs. If you have
been using the <code class="literal">@AutoConfigureWireMock</code> notation to use the stubs from the classpath,
it no longer works. The following example shows how the <code class="literal">@AutoConfigureWireMock</code> notation
used to work:</p><pre class="programlisting">@AutoConfigureWireMock(stubs = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"classpath:/customer-stubs/mappings"</span>, port = <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">8084</xslthl:number>)</pre><p>You must either change the location of the stubs to:
<code class="literal">classpath:&#8230;&#8203;/META-INF/groupId/artifactId/version/mappings</code> or use the new
classpath-based <code class="literal">@AutoConfigureStubRunner</code>, as shown in the following example:</p><pre class="programlisting">@AutoConfigureWireMock(stubs = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"classpath:customer-stubs/META-INF/travel.components/customer-contract/1.0.2-SNAPSHOT/mappings/"</span>, port = <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">8084</xslthl:number>)</pre><p>If you do not want to use <code class="literal">@AutoConfigureStubRunner</code> and you want to remain with the old
structure, set your plugin tasks accordingly. The following example would work for the
structure presented in the previous snippet.</p><p class="primary"><b>Maven.&nbsp;</b>
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">&lt;!-- start of pom.xml --&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;properties&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">&lt;!-- we don't want the verifier to do a jar for us --&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;spring.cloud.contract.verifier.skip&gt;</span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/spring.cloud.contract.verifier.skip&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/properties&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">&lt;!-- ... --&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">&lt;!-- You need to set up the assembly plugin --&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;build&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;plugins&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;plugin&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>org.apache.maven.plugins<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>maven-assembly-plugin<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;executions&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;execution&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;id&gt;</span>stub<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/id&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;phase&gt;</span>prepare-package<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/phase&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;goals&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;goal&gt;</span>single<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/goal&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/goals&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;inherited&gt;</span>false<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/inherited&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;configuration&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;attach&gt;</span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/attach&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;descriptor&gt;</span>${basedir}/src/assembly/stub.xml<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/descriptor&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/configuration&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/execution&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/executions&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/plugin&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/plugins&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/build&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">&lt;!-- end of pom.xml --&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">&lt;!-- start of stub.xml--&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;assembly</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">xmlns</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">xmlns:xsi</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"http://www.w3.org/2001/XMLSchema-instance"</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">xsi:schemaLocation</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 https://maven.apache.org/xsd/assembly-1.1.3.xsd"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;id&gt;</span>stubs<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/id&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;formats&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;format&gt;</span>jar<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/format&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/formats&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;includeBaseDirectory&gt;</span>false<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/includeBaseDirectory&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;fileSets&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;fileSet&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;directory&gt;</span>${project.build.directory}/snippets/stubs<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/directory&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;outputDirectory&gt;</span>customer-stubs/mappings<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/outputDirectory&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;includes&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;include&gt;</span>**/*<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/include&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/includes&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/fileSet&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;fileSet&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;directory&gt;</span>${basedir}/src/test/resources/contracts<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/directory&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;outputDirectory&gt;</span>customer-stubs/contracts<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/outputDirectory&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;includes&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;include&gt;</span>**/*.groovy<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/include&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/includes&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/fileSet&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/fileSets&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/assembly&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">&lt;!-- end of stub.xml--&gt;</span></pre><p class="primary">
</p><p class="secondary"><b>Gradle.&nbsp;</b>
</p><pre class="programlisting">task copyStubs(type: Copy, dependsOn: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'generateWireMockClientStubs'</span>) {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Preserve directory structure from 1.0.X of spring-cloud-contract</span>
from <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"${project.buildDir}/resources/main/customer-stubs/META-INF/${project.group}/${project.name}/${project.version}"</span>
into <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"${project.buildDir}/resources/main/customer-stubs"</span>
}</pre><p class="secondary">
</p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="cloud-verifier-1.1-1.2" href="#cloud-verifier-1.1-1.2"></a>12.2&nbsp;1.1.x &#8594; 1.2.x</h2></div></div></div><p>This section covers upgrading from version 1.1 to version 1.2.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_custom_literal_httpserverstub_literal" href="#_custom_literal_httpserverstub_literal"></a>12.2.1&nbsp;Custom <code class="literal">HttpServerStub</code></h3></div></div></div><p><code class="literal">HttpServerStub</code> includes a method that was not in version 1.1. The method is
<code class="literal">String registeredMappings()</code> If you have classes that implement <code class="literal">HttpServerStub</code>, you
now have to implement the <code class="literal">registeredMappings()</code> method. It should return a <code class="literal">String</code>
representing all mappings available in a single <code class="literal">HttpServerStub</code>.</p><p>See <a class="link" href="https://github.com/spring-cloud/spring-cloud-contract/issues/355" target="_top">issue 355</a> for more
detail.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_new_packages_for_generated_tests" href="#_new_packages_for_generated_tests"></a>12.2.2&nbsp;New packages for generated tests</h3></div></div></div><p>The flow for setting the generated tests package name will look like this:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Set <code class="literal">basePackageForTests</code></li><li class="listitem">If <code class="literal">basePackageForTests</code> was not set, pick the package from <code class="literal">baseClassForTests</code></li><li class="listitem">If <code class="literal">baseClassForTests</code> was not set, pick <code class="literal">packageWithBaseClasses</code></li><li class="listitem">If nothing got set, pick the default value:
<code class="literal">org.springframework.cloud.contract.verifier.tests</code></li></ul></div><p>See <a class="link" href="https://github.com/spring-cloud/spring-cloud-contract/issues/260" target="_top">issue 260</a> for more
detail.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_new_methods_in_templateprocessor" href="#_new_methods_in_templateprocessor"></a>12.2.3&nbsp;New Methods in TemplateProcessor</h3></div></div></div><p>In order to add support for <code class="literal">fromRequest.path</code>, the following methods had to be added to the
<code class="literal">TemplateProcessor</code> interface:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">path()</code></li><li class="listitem"><code class="literal">path(int index)</code></li></ul></div><p>See <a class="link" href="https://github.com/spring-cloud/spring-cloud-contract/issues/388" target="_top">issue 388</a> for more
detail.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_restassured_3_0" href="#_restassured_3_0"></a>12.2.4&nbsp;RestAssured 3.0</h3></div></div></div><p>Rest Assured, used in the generated test classes, got bumped to <code class="literal">3.0</code>. If
you manually set versions of Spring Cloud Contract and the release train
you might see the following exception:</p><pre class="programlisting">Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">3.1</xslthl:number>:testCompile (default-testCompile) on project some-project: Compilation failure: Compilation failure:
[ERROR] /some/path/SomeClass.java:[<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">4</xslthl:number>,<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">39</xslthl:number>] package com.jayway.restassured.response does not exist</pre><p>This exception will occur due to the fact that the tests got generated with
an old version of plugin and at test execution time you have an incompatible
version of the release train (and vice versa).</p><p>Done via <a class="link" href="https://github.com/spring-cloud/spring-cloud-contract/issues/267" target="_top">issue 267</a></p></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__spring_cloud_contract_wiremock.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi__links.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">11.&nbsp;Spring Cloud Contract WireMock&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-contract.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;13.&nbsp;Links</td></tr></table></div></body></html>

View File

@@ -0,0 +1,7 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>1.&nbsp;Spring Cloud Contract</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud-contract.html" title="Spring Cloud Contract"><link rel="up" href="multi_spring-cloud-contract.html" title="Spring Cloud Contract"><link rel="prev" href="multi_pr01.html" title=""><link rel="next" href="multi__spring_cloud_contract_verifier_introduction.html" title="2.&nbsp;Spring Cloud Contract Verifier Introduction"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">1.&nbsp;Spring Cloud Contract</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi_pr01.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi__spring_cloud_contract_verifier_introduction.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_spring_cloud_contract" href="#_spring_cloud_contract"></a>1.&nbsp;Spring Cloud Contract</h1></div></div></div><p>You need confidence when pushing new features to a new application or service in a
distributed system. This project provides support for Consumer Driven Contracts and
service schemas in Spring applications (for both HTTP and message-based interactions),
covering a range of options for writing tests, publishing them as assets, and asserting
that a contract is kept by producers and consumers.</p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi_pr01.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi__spring_cloud_contract_verifier_introduction.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-contract.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;2.&nbsp;Spring Cloud Contract Verifier Introduction</td></tr></table></div></body></html>

View File

@@ -0,0 +1,302 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>3.&nbsp;Spring Cloud Contract FAQ</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud-contract.html" title="Spring Cloud Contract"><link rel="up" href="multi_spring-cloud-contract.html" title="Spring Cloud Contract"><link rel="prev" href="multi__spring_cloud_contract_verifier_introduction.html" title="2.&nbsp;Spring Cloud Contract Verifier Introduction"><link rel="next" href="multi__spring_cloud_contract_verifier_setup.html" title="4.&nbsp;Spring Cloud Contract Verifier Setup"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">3.&nbsp;Spring Cloud Contract FAQ</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__spring_cloud_contract_verifier_introduction.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi__spring_cloud_contract_verifier_setup.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_spring_cloud_contract_faq" href="#_spring_cloud_contract_faq"></a>3.&nbsp;Spring Cloud Contract FAQ</h1></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_why_use_spring_cloud_contract_verifier_and_not_x" href="#_why_use_spring_cloud_contract_verifier_and_not_x"></a>3.1&nbsp;Why use Spring Cloud Contract Verifier and not X ?</h2></div></div></div><p>For the time being Spring Cloud Contract Verifier is a JVM based tool. So it could be your first pick when you&#8217;re already creating
software for the JVM. This project has a lot of really interesting features but especially quite a few of them definitely make
Spring Cloud Contract Verifier stand out on the "market" of Consumer Driven Contract (CDC) tooling. Out of many the most interesting are:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Possibility to do CDC with messaging</li><li class="listitem">Clear and easy to use, statically typed DSL</li><li class="listitem">Possibility to copy paste your current JSON file to the contract and only edit its elements</li><li class="listitem">Automatic generation of tests from the defined Contract</li><li class="listitem">Stub Runner functionality - the stubs are automatically downloaded at runtime from Nexus / Artifactory</li><li class="listitem">Spring Cloud integration - no discovery service is needed for integration tests</li></ul></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_i_don_t_want_to_write_a_contract_in_groovy" href="#_i_don_t_want_to_write_a_contract_in_groovy"></a>3.2&nbsp;I don&#8217;t want to write a contract in Groovy!</h2></div></div></div><p>No problem. You can write a contract in YAML!</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_what_is_this_value_consumer_producer" href="#_what_is_this_value_consumer_producer"></a>3.3&nbsp;What is this value(consumer(), producer()) ?</h2></div></div></div><p>One of the biggest challenges related to stubs is their reusability. Only if they can be vastly used, will they serve their purpose.
What typically makes that difficult are the hard-coded values of request / response elements. For example dates or ids.
Imagine the following JSON request</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"time"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"2016-10-10 20:10:15"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"id"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"9febab1c-6f36-4a0b-88d6-3b6a6d81cd4a"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"body"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"foo"</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span></pre><p>and JSON response</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"time"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"2016-10-10 21:10:15"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"id"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"c4231e1f-3ca9-48d3-b7e7-567d55f0d051"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"body"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"bar"</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span></pre><p>Imagine the pain required to set proper value of the <code class="literal">time</code> field (let&#8217;s assume that this content is generated by the
database) by changing the clock in the system or providing stub implementations of data providers. The same is related
to the field called <code class="literal">id</code>. Will you create a stubbed implementation of UUID generator? Makes little sense&#8230;&#8203;</p><p>So as a consumer you would like to send a request that matches any form of a time or any UUID. That way your system
will work as usual - will generate data and you won&#8217;t have to stub anything out. Let&#8217;s assume that in case of the aforementioned
JSON the most important part is the <code class="literal">body</code> field. You can focus on that and provide matching for other fields. In other words
you would like the stub to work like this:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"time"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"SOMETHING THAT MATCHES TIME"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"id"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"SOMETHING THAT MATCHES UUID"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"body"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"foo"</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span></pre><p>As far as the response goes as a consumer you need a concrete value that you can operate on. So such a JSON is valid</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"time"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"2016-10-10 21:10:15"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"id"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"c4231e1f-3ca9-48d3-b7e7-567d55f0d051"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"body"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"bar"</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span></pre><p>As you could see in the previous sections we generate tests from contracts. So from the producer&#8217;s side the situation looks
much different. We&#8217;re parsing the provided contract and in the test we want to send a real request to your endpoints.
So for the case of a producer for the request we can&#8217;t have any sort of matching. We need concrete values that the
producer&#8217;s backend can work on. Such a JSON would be a valid one:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"time"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"2016-10-10 20:10:15"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"id"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"9febab1c-6f36-4a0b-88d6-3b6a6d81cd4a"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"body"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"foo"</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span></pre><p>On the other hand from the point of view of the validity of the contract the response doesn&#8217;t necessarily have to
contain concrete values of <code class="literal">time</code> or <code class="literal">id</code>. Let&#8217;s say that you generate those on the producer side - again, you&#8217;d
have to do a lot of stubbing to ensure that you always return the same values. That&#8217;s why from the producer&#8217;s side
what you might want is the following response:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"time"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"SOMETHING THAT MATCHES TIME"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"id"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"SOMETHING THAT MATCHES UUID"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"body"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"bar"</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span></pre><p>How can you then provide one time a matcher for the consumer and a concrete value for the producer and vice versa?
In Spring Cloud Contract we&#8217;re allowing you to provide a <span class="strong"><strong>dynamic value</strong></span>. That means that it can differ for both
sides of the communication. You can pass the values:</p><p>Either via the <code class="literal">value</code> method</p><pre class="programlisting">value(consumer(...), producer(...))
value(stub(...), test(...))
value(client(...), server(...))</pre><p>or using the <code class="literal">$()</code> method</p><pre class="programlisting">$(consumer(...), producer(...))
$(stub(...), test(...))
$(client(...), server(...))</pre><p>You can read more about this in the <a class="link" href="https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html#_contract_dsl" target="_top">Contract DSL section</a>.</p><p>Calling <code class="literal">value()</code> or <code class="literal">$()</code> tells Spring Cloud Contract that you will be passing a dynamic value.
Inside the <code class="literal">consumer()</code> method you pass the value that should be used on the consumer side (in the generated stub).
Inside the <code class="literal">producer()</code> method you pass the value that should be used on the producer side (in the generated test).</p><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Tip</th></tr><tr><td align="left" valign="top"><p>If on one side you have passed the regular expression and you haven&#8217;t passed the other, then the
other side will get auto-generated.</p></td></tr></table></div><p>Most often you will use that method together with the <code class="literal">regex</code> helper method. E.g. <code class="literal">consumer(regex('[0-9]{10}'))</code>.</p><p>To sum it up the contract for the aforementioned scenario would look more or less like this (the regular expression
for time and UUID are simplified and most likely invalid but we want to keep things very simple in this example):</p><pre class="programlisting">org.springframework.cloud.contract.spec.Contract.make {
request {
method <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'GET'</span>
url <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'/someUrl'</span>
body([
time : value(consumer(regex(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'[0-9]{4}-[0-9]{2}-[0-9]{2} [0-2][0-9]-[0-5][0-9]-[0-5][0-9]'</span>)),
id: value(consumer(regex(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'[0-9a-zA-z]{8}-[0-9a-zA-z]{4}-[0-9a-zA-z]{4}-[0-9a-zA-z]{12}'</span>))
body: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"foo"</span>
])
}
response {
status <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>
body([
time : value(producer(regex(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'[0-9]{4}-[0-9]{2}-[0-9]{2} [0-2][0-9]-[0-5][0-9]-[0-5][0-9]'</span>)),
id: value([producer(regex(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'[0-9a-zA-z]{8}-[0-9a-zA-z]{4}-[0-9a-zA-z]{4}-[0-9a-zA-z]{12}'</span>))
body: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"bar"</span>
])
}
}</pre><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>Please read the <a class="link" href="https://groovy-lang.org/json.html" target="_top">Groovy docs related to JSON</a> to understand how to
properly structure the request / response bodies.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_how_to_do_stubs_versioning" href="#_how_to_do_stubs_versioning"></a>3.4&nbsp;How to do Stubs versioning?</h2></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_api_versioning" href="#_api_versioning"></a>3.4.1&nbsp;API Versioning</h3></div></div></div><p>Let&#8217;s try to answer a question what versioning really means. If you&#8217;re referring to the API version then there are
different approaches.</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">use Hypermedia, links and do not version your API by any means</li><li class="listitem">pass versions through headers / urls</li></ul></div><p>I will not try to answer a question which approach is better. Whatever suit your needs and allows you to generate
business value should be picked.</p><p>Let&#8217;s assume that you do version your API. In that case you should provide as many contracts as many versions you support.
You can create a subfolder for every version or append it to th contract name - whatever suits you more.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_jar_versioning" href="#_jar_versioning"></a>3.4.2&nbsp;JAR versioning</h3></div></div></div><p>If by versioning you mean the version of the JAR that contains the stubs then there are essentially two main approaches.</p><p>Let&#8217;s assume that you&#8217;re doing Continuous Delivery / Deployment which means that you&#8217;re generating a new version of
the jar each time you go through the pipeline and that jar can go to production at any time. For example your jar version
looks like this (it got built on the 20.10.2016 at 20:15:21) :</p><pre class="programlisting"><xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.20161020</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">201521</xslthl:number>-RELEASE</pre><p>In that case your generated stub jar will look like this.</p><pre class="programlisting"><xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.20161020</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">201521</xslthl:number>-RELEASE-stubs.jar</pre><p>In this case you should inside your <code class="literal">application.yml</code> or <code class="literal">@AutoConfigureStubRunner</code> when referencing stubs provide the
latest version of the stubs. You can do that by passing the <code class="literal">+</code> sign. Example</p><pre class="programlisting">@AutoConfigureStubRunner(ids = {<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"com.example:http-server-dsl:+:stubs:8080"</span>})</pre><p>If the versioning however is fixed (e.g. <code class="literal">1.0.4.RELEASE</code> or <code class="literal">2.1.1</code>) then you have to set the concrete value of the jar
version. Example for 2.1.1.</p><pre class="programlisting">@AutoConfigureStubRunner(ids = {<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"com.example:http-server-dsl:2.1.1:stubs:8080"</span>})</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_dev_or_prod_stubs" href="#_dev_or_prod_stubs"></a>3.4.3&nbsp;Dev or prod stubs</h3></div></div></div><p>You can manipulate the classifier to run the tests against current development version of the stubs of other services
or the ones that were deployed to production. If you alter your build to deploy the stubs with the <code class="literal">prod-stubs</code> classifier
once you reach production deployment then you can run tests in one case with dev stubs and one with prod stubs.</p><p>Example of tests using development version of stubs</p><pre class="programlisting">@AutoConfigureStubRunner(ids = {<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"com.example:http-server-dsl:+:stubs:8080"</span>})</pre><p>Example of tests using production version of stubs</p><pre class="programlisting">@AutoConfigureStubRunner(ids = {<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"com.example:http-server-dsl:+:prod-stubs:8080"</span>})</pre><p>You can pass those values also via properties from your deployment pipeline.</p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_common_repo_with_contracts" href="#_common_repo_with_contracts"></a>3.5&nbsp;Common repo with contracts</h2></div></div></div><p>Another way of storing contracts other than having them with the producer is keeping them in a common place.
It can be related to security issues where the consumers can&#8217;t clone the producer&#8217;s code. Also if you keep
contracts in a single place then you, as a producer, will know how many consumers you have and which
consumer will you break with your local changes.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_repo_structure" href="#_repo_structure"></a>3.5.1&nbsp;Repo structure</h3></div></div></div><p>Let&#8217;s assume that we have a producer with coordinates <code class="literal">com.example:server</code> and 3 consumers: <code class="literal">client1</code>,
<code class="literal">client2</code>, <code class="literal">client3</code>. Then in the repository with common contracts you would have the following setup
(which you can checkout <a class="link" href="https://github.com/spring-cloud/spring-cloud-contract/tree/1.0.x/samples/standalone/contracts" target="_top">here</a>:</p><pre class="programlisting">&#9500;&#9472;&#9472; com
&#9474;&nbsp;&nbsp; &#9492;&#9472;&#9472; example
&#9474;&nbsp;&nbsp; &#9492;&#9472;&#9472; server
&#9474;&nbsp;&nbsp; &#9500;&#9472;&#9472; client1
&#9474;&nbsp;&nbsp; &#9474;&nbsp;&nbsp; &#9492;&#9472;&#9472; expectation.groovy
&#9474;&nbsp;&nbsp; &#9500;&#9472;&#9472; client2
&#9474;&nbsp;&nbsp; &#9474;&nbsp;&nbsp; &#9492;&#9472;&#9472; expectation.groovy
&#9474;&nbsp;&nbsp; &#9500;&#9472;&#9472; client3
&#9474;&nbsp;&nbsp; &#9474;&nbsp;&nbsp; &#9492;&#9472;&#9472; expectation.groovy
&#9474;&nbsp;&nbsp; &#9492;&#9472;&#9472; pom.xml
&#9500;&#9472;&#9472; mvnw
&#9500;&#9472;&#9472; mvnw.cmd
&#9500;&#9472;&#9472; pom.xml
&#9492;&#9472;&#9472; src
&#9492;&#9472;&#9472; assembly
&#9492;&#9472;&#9472; contracts.xml</pre><p>As you can see the under the slash-delimited groupid <code class="literal">/</code> artifact id folder (<code class="literal">com/example/server</code>) you have
expectations of the 3 consumers (<code class="literal">client1</code>, <code class="literal">client2</code> and <code class="literal">client3</code>). Expectations are the standard Groovy DSL
contract files as described throughout this documentation. This repository has to produce a JAR file that maps
one to one to the contents of the repo.</p><p>Example of a <code class="literal">pom.xml</code> inside the <code class="literal">server</code> folder.</p><pre class="programlisting"><xslthl:directive xmlns:xslthl="http://xslthl.sourceforge.net/">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</xslthl:directive>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;project</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">xmlns</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"http://maven.apache.org/POM/4.0.0"</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">xmlns:xsi</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"http://www.w3.org/2001/XMLSchema-instance"</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">xsi:schemaLocation</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;modelVersion&gt;</span>4.0.0<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/modelVersion&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>com.example<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>server<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;version&gt;</span>0.0.1-SNAPSHOT<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/version&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;name&gt;</span>Server Stubs<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/name&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;description&gt;</span>POM used to install locally stubs for consumer side<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/description&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;parent&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>org.springframework.boot<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>spring-boot-starter-parent<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;version&gt;</span>1.5.16.RELEASE<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/version&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;relativePath /&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/parent&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;properties&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;project.build.sourceEncoding&gt;</span>UTF-8<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/project.build.sourceEncoding&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;java.version&gt;</span>1.8<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/java.version&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;spring-cloud-contract.version&gt;</span>1.2.7.BUILD-SNAPSHOT<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/spring-cloud-contract.version&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;spring-cloud-dependencies.version&gt;</span>1.3.11.BUILD-SNAPSHOT<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/spring-cloud-dependencies.version&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;excludeBuildFolders&gt;</span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/excludeBuildFolders&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/properties&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;dependencyManagement&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;dependencies&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;dependency&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>spring-cloud-dependencies<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;version&gt;</span>${spring-cloud-dependencies.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/version&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;type&gt;</span>pom<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/type&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;scope&gt;</span>import<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/scope&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/dependency&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/dependencies&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/dependencyManagement&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;build&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;plugins&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;plugin&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>spring-cloud-contract-maven-plugin<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;version&gt;</span>${spring-cloud-contract.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/version&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;extensions&gt;</span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/extensions&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;configuration&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">&lt;!-- By default it would search under src/test/resources/ --&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;contractsDirectory&gt;</span>${project.basedir}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/contractsDirectory&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/configuration&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/plugin&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/plugins&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/build&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;repositories&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;repository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;id&gt;</span>spring-snapshots<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/id&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;name&gt;</span>Spring Snapshots<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/name&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;url&gt;</span>https://repo.spring.io/snapshot<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/url&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;enabled&gt;</span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/enabled&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/repository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;repository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;id&gt;</span>spring-milestones<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/id&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;name&gt;</span>Spring Milestones<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/name&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;url&gt;</span>https://repo.spring.io/milestone<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/url&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;enabled&gt;</span>false<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/enabled&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/repository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;repository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;id&gt;</span>spring-releases<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/id&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;name&gt;</span>Spring Releases<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/name&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;url&gt;</span>https://repo.spring.io/release<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/url&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;enabled&gt;</span>false<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/enabled&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/repository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/repositories&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;pluginRepositories&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;pluginRepository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;id&gt;</span>spring-snapshots<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/id&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;name&gt;</span>Spring Snapshots<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/name&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;url&gt;</span>https://repo.spring.io/snapshot<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/url&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;enabled&gt;</span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/enabled&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/pluginRepository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;pluginRepository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;id&gt;</span>spring-milestones<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/id&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;name&gt;</span>Spring Milestones<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/name&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;url&gt;</span>https://repo.spring.io/milestone<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/url&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;enabled&gt;</span>false<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/enabled&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/pluginRepository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;pluginRepository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;id&gt;</span>spring-releases<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/id&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;name&gt;</span>Spring Releases<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/name&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;url&gt;</span>https://repo.spring.io/release<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/url&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;enabled&gt;</span>false<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/enabled&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/pluginRepository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/pluginRepositories&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/project&gt;</span></pre><p>As you can see there are no dependencies other than the Spring Cloud Contract Maven Plugin.
Those poms are necessary for the consumer side to run <code class="literal">mvn clean install -DskipTests</code> to locally install
stubs of the producer project.</p><p>The <code class="literal">pom.xml</code> in the root folder can look like this:</p><pre class="programlisting"><xslthl:directive xmlns:xslthl="http://xslthl.sourceforge.net/">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</xslthl:directive>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;project</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">xmlns</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"http://maven.apache.org/POM/4.0.0"</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">xmlns:xsi</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"http://www.w3.org/2001/XMLSchema-instance"</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">xsi:schemaLocation</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;modelVersion&gt;</span>4.0.0<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/modelVersion&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>com.example.standalone<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>contracts<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;version&gt;</span>0.0.1-SNAPSHOT<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/version&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;name&gt;</span>Contracts<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/name&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;description&gt;</span>Contains all the Spring Cloud Contracts, well, contracts. JAR used by the producers to generate tests and stubs<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/description&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;properties&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;project.build.sourceEncoding&gt;</span>UTF-8<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/project.build.sourceEncoding&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/properties&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;build&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;plugins&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;plugin&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>org.apache.maven.plugins<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>maven-assembly-plugin<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;executions&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;execution&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;id&gt;</span>contracts<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/id&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;phase&gt;</span>prepare-package<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/phase&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;goals&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;goal&gt;</span>single<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/goal&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/goals&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;configuration&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;attach&gt;</span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/attach&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;descriptor&gt;</span>${basedir}/src/assembly/contracts.xml<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/descriptor&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">&lt;!-- If you want an explicit classifier remove the following line --&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;appendAssemblyId&gt;</span>false<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/appendAssemblyId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/configuration&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/execution&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/executions&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/plugin&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/plugins&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/build&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/project&gt;</span></pre><p>It&#8217;s using the assembly plugin in order to build the JAR with all the contracts. Example of such setup is here:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;assembly</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">xmlns</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">xmlns:xsi</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"http://www.w3.org/2001/XMLSchema-instance"</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">xsi:schemaLocation</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 https://maven.apache.org/xsd/assembly-1.1.3.xsd"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;id&gt;</span>project<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/id&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;formats&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;format&gt;</span>jar<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/format&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/formats&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;includeBaseDirectory&gt;</span>false<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/includeBaseDirectory&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;fileSets&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;fileSet&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;directory&gt;</span>${project.basedir}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/directory&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;outputDirectory&gt;</span>/<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/outputDirectory&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;useDefaultExcludes&gt;</span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/useDefaultExcludes&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;excludes&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;exclude&gt;</span>**/${project.build.directory}/**<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/exclude&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;exclude&gt;</span>mvnw<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/exclude&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;exclude&gt;</span>mvnw.cmd<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/exclude&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;exclude&gt;</span>.mvn/**<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/exclude&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;exclude&gt;</span>src/**<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/exclude&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/excludes&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/fileSet&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/fileSets&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/assembly&gt;</span></pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_workflow" href="#_workflow"></a>3.5.2&nbsp;Workflow</h3></div></div></div><p>The workflow would look similar to the one presented in the <code class="literal">Step by step guide to CDC</code>. The only difference
is that the producer doesn&#8217;t own the contracts anymore. So the consumer and the producer have to work on
common contracts in a common repository.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_consumer" href="#_consumer"></a>3.5.3&nbsp;Consumer</h3></div></div></div><p>When the <span class="strong"><strong>consumer</strong></span> wants to work on the contracts offline, instead of cloning the producer code, the
consumer team clones the common repository, goes to the required producer&#8217;s folder (e.g. <code class="literal">com/example/server</code>)
and runs <code class="literal">mvn clean install -DskipTests</code> to install locally the stubs converted from the contracts.</p><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Tip</th></tr><tr><td align="left" valign="top"><p>You need to have <a class="link" href="https://maven.apache.org/download.cgi" target="_top">Maven installed locally</a></p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_producer" href="#_producer"></a>3.5.4&nbsp;Producer</h3></div></div></div><p>As a <span class="strong"><strong>producer</strong></span> it&#8217;s enough to alter the Spring Cloud Contract Verifier to provide the URL and the dependency
of the JAR containing the contracts:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;plugin&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>spring-cloud-contract-maven-plugin<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;configuration&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;contractsRepositoryUrl&gt;</span>http://link/to/your/nexus/or/artifactory/or/sth<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/contractsRepositoryUrl&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;contractDependency&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>com.example.standalone<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>contracts<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/contractDependency&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/configuration&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/plugin&gt;</span></pre><p>With this setup the JAR with groupid <code class="literal">com.example.standalone</code> and artifactid <code class="literal">contracts</code> will be downloaded
from <code class="literal"><a class="link" href="http://link/to/your/nexus/or/artifactory/or/sth" target="_top">http://link/to/your/nexus/or/artifactory/or/sth</a></code>. It will be then unpacked in a local temporary folder
and contracts present under the <code class="literal">com/example/server</code> will be picked as the ones used to generate the
tests and the stubs. Due to this convention the producer team will know which consumer teams will be broken
when some incompatible changes are done.</p><p>The rest of the flow looks the same.</p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_can_i_have_multiple_base_classes_for_tests" href="#_can_i_have_multiple_base_classes_for_tests"></a>3.6&nbsp;Can I have multiple base classes for tests?</h2></div></div></div><p>Yes! Check out the <a class="link" href="https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html#_different_base_classes_for_contracts" target="_top">Different base classes for contracts</a> sections
of either Gradle or Maven plugins.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_how_can_i_debug_the_request_response_being_sent_by_the_generated_tests_client" href="#_how_can_i_debug_the_request_response_being_sent_by_the_generated_tests_client"></a>3.7&nbsp;How can I debug the request/response being sent by the generated tests client?</h2></div></div></div><p>The generated tests all boil down to RestAssured in some form or fashion which relies on <a class="link" href="https://hc.apache.org/httpcomponents-client-ga/" target="_top">Apache HttpClient</a>. HttpClient has a facility called <a class="link" href="https://hc.apache.org/httpcomponents-client-ga/logging.html#Wire_Logging" target="_top">wire logging</a> which logs the entire request and response to HttpClient. Spring Boot has a logging <a class="link" href="https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html" target="_top">common application property</a> for doing this sort of thing, just add this to your application properties</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">logging.level.org.apache.http.wire</span>=DEBUG</pre><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_how_can_i_debug_the_mapping_request_response_being_sent_by_wiremock" href="#_how_can_i_debug_the_mapping_request_response_being_sent_by_wiremock"></a>3.7.1&nbsp;How can I debug the mapping/request/response being sent by WireMock?</h3></div></div></div><p>Starting from version <code class="literal">1.2.0</code> we turn on WireMock logging to
info and the WireMock notifier to being verbose. Now you will
exactly know what request was received by WireMock server and which
matching response definition was picked.</p><p>To turn off this feature just bump WireMock logging to <code class="literal">ERROR</code></p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">logging.level.com.github.tomakehurst.wiremock</span>=ERROR</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_how_can_i_see_what_got_registered_in_the_http_server_stub" href="#_how_can_i_see_what_got_registered_in_the_http_server_stub"></a>3.7.2&nbsp;How can I see what got registered in the HTTP server stub?</h3></div></div></div><p>You can use the <code class="literal">mappingsOutputFolder</code> property on <code class="literal">@AutoConfigureStubRunner</code> or <code class="literal">StubRunnerRule</code>
to dump all mappings per artifact id. Also the port at which the given stub server was
started will be attached.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_can_i_reference_the_request_from_the_response" href="#_can_i_reference_the_request_from_the_response"></a>3.7.3&nbsp;Can I reference the request from the response?</h3></div></div></div><p>Yes! With version 1.1.0 we&#8217;ve added such a possibility. On the HTTP stub server side we&#8217;re providing support
for this for WireMock. In case of other HTTP server stubs you&#8217;ll have to implement the approach yourself.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_can_i_reference_text_from_file" href="#_can_i_reference_text_from_file"></a>3.7.4&nbsp;Can I reference text from file?</h3></div></div></div><p>Yes! With version 1.2.0 we&#8217;ve added such a possibility. It&#8217;s enough to call <code class="literal">file(&#8230;&#8203;)</code> method in the
DSL and provide a path relative to where the contract lays.
If you&#8217;re using YAML just use the <code class="literal">bodyFromFile</code> property.</p></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__spring_cloud_contract_verifier_introduction.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi__spring_cloud_contract_verifier_setup.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">2.&nbsp;Spring Cloud Contract Verifier Introduction&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-contract.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;4.&nbsp;Spring Cloud Contract Verifier Setup</td></tr></table></div></body></html>

View File

@@ -0,0 +1,710 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>6.&nbsp;Spring Cloud Contract Stub Runner</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud-contract.html" title="Spring Cloud Contract"><link rel="up" href="multi_spring-cloud-contract.html" title="Spring Cloud Contract"><link rel="prev" href="multi__spring_cloud_contract_verifier_messaging.html" title="5.&nbsp;Spring Cloud Contract Verifier Messaging"><link rel="next" href="multi__stub_runner_for_messaging.html" title="7.&nbsp;Stub Runner for Messaging"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">6.&nbsp;Spring Cloud Contract Stub Runner</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__spring_cloud_contract_verifier_messaging.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi__stub_runner_for_messaging.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_spring_cloud_contract_stub_runner" href="#_spring_cloud_contract_stub_runner"></a>6.&nbsp;Spring Cloud Contract Stub Runner</h1></div></div></div><p>One of the issues that you might encounter while using Spring Cloud Contract Verifier is
passing the generated WireMock JSON stubs from the server side to the client side (or to
various clients). The same takes place in terms of client-side generation for messaging.</p><p>Copying the JSON files and setting the client side for messaging manually is out of the
question. That is why we introduced Spring Cloud Contract Stub Runner. It can
automatically download and run the stubs for you.</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_snapshot_versions" href="#_snapshot_versions"></a>6.1&nbsp;Snapshot versions</h2></div></div></div><p>Add the additional snapshot repository to your <code class="literal">build.gradle</code> file to use snapshot
versions, which are automatically uploaded after every successful build:</p><p class="primary"><b>Maven.&nbsp;</b>
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;repositories&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;repository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;id&gt;</span>spring-snapshots<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/id&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;name&gt;</span>Spring Snapshots<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/name&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;url&gt;</span>https://repo.spring.io/snapshot<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/url&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;enabled&gt;</span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/enabled&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/repository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;repository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;id&gt;</span>spring-milestones<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/id&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;name&gt;</span>Spring Milestones<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/name&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;url&gt;</span>https://repo.spring.io/milestone<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/url&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;enabled&gt;</span>false<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/enabled&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/repository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;repository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;id&gt;</span>spring-releases<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/id&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;name&gt;</span>Spring Releases<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/name&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;url&gt;</span>https://repo.spring.io/release<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/url&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;enabled&gt;</span>false<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/enabled&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/repository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/repositories&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;pluginRepositories&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;pluginRepository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;id&gt;</span>spring-snapshots<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/id&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;name&gt;</span>Spring Snapshots<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/name&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;url&gt;</span>https://repo.spring.io/snapshot<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/url&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;enabled&gt;</span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/enabled&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/pluginRepository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;pluginRepository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;id&gt;</span>spring-milestones<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/id&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;name&gt;</span>Spring Milestones<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/name&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;url&gt;</span>https://repo.spring.io/milestone<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/url&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;enabled&gt;</span>false<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/enabled&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/pluginRepository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;pluginRepository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;id&gt;</span>spring-releases<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/id&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;name&gt;</span>Spring Releases<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/name&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;url&gt;</span>https://repo.spring.io/release<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/url&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;enabled&gt;</span>false<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/enabled&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/pluginRepository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/pluginRepositories&gt;</span></pre><p class="primary">
</p><p class="secondary"><b>Gradle.&nbsp;</b>
</p><pre class="programlisting">buildscript {
repositories {
mavenCentral()
mavenLocal()
maven { url <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"https://repo.spring.io/snapshot"</span> }
maven { url <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"https://repo.spring.io/milestone"</span> }
maven { url <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"https://repo.spring.io/release"</span> }
}</pre><p class="secondary">
</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_publishing_stubs_as_jars" href="#_publishing_stubs_as_jars"></a>6.2&nbsp;Publishing Stubs as JARs</h2></div></div></div><p>The easiest approach would be to centralize the way stubs are kept. For example, you can
keep them as jars in a Maven repository.</p><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Tip</th></tr><tr><td align="left" valign="top"><p>For both Maven and Gradle, the setup comes ready to work. However, you can customize
it if you want to.</p></td></tr></table></div><p class="primary"><b>Maven.&nbsp;</b>
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">&lt;!-- First disable the default jar setup in the properties section --&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">&lt;!-- we don't want the verifier to do a jar for us --&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;spring.cloud.contract.verifier.skip&gt;</span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/spring.cloud.contract.verifier.skip&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">&lt;!-- Next add the assembly plugin to your build --&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">&lt;!-- we want the assembly plugin to generate the JAR --&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;plugin&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>org.apache.maven.plugins<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>maven-assembly-plugin<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;executions&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;execution&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;id&gt;</span>stub<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/id&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;phase&gt;</span>prepare-package<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/phase&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;goals&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;goal&gt;</span>single<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/goal&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/goals&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;inherited&gt;</span>false<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/inherited&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;configuration&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;attach&gt;</span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/attach&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;descriptors&gt;</span>
${basedir}/src/assembly/stub.xml
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/descriptors&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/configuration&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/execution&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/executions&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/plugin&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">&lt;!-- Finally setup your assembly. Below you can find the contents of src/main/assembly/stub.xml --&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;assembly</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">xmlns</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">xmlns:xsi</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"http://www.w3.org/2001/XMLSchema-instance"</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">xsi:schemaLocation</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 https://maven.apache.org/xsd/assembly-1.1.3.xsd"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;id&gt;</span>stubs<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/id&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;formats&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;format&gt;</span>jar<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/format&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/formats&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;includeBaseDirectory&gt;</span>false<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/includeBaseDirectory&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;fileSets&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;fileSet&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;directory&gt;</span>src/main/java<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/directory&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;outputDirectory&gt;</span>/<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/outputDirectory&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;includes&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;include&gt;</span>**com/example/model/*.*<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/include&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/includes&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/fileSet&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;fileSet&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;directory&gt;</span>${project.build.directory}/classes<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/directory&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;outputDirectory&gt;</span>/<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/outputDirectory&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;includes&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;include&gt;</span>**com/example/model/*.*<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/include&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/includes&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/fileSet&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;fileSet&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;directory&gt;</span>${project.build.directory}/snippets/stubs<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/directory&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;outputDirectory&gt;</span>META-INF/${project.groupId}/${project.artifactId}/${project.version}/mappings<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/outputDirectory&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;includes&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;include&gt;</span>**/*<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/include&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/includes&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/fileSet&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;fileSet&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;directory&gt;</span>${basedir}/src/test/resources/contracts<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/directory&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;outputDirectory&gt;</span>META-INF/${project.groupId}/${project.artifactId}/${project.version}/contracts<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/outputDirectory&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;includes&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;include&gt;</span>**/*.groovy<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/include&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/includes&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/fileSet&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/fileSets&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/assembly&gt;</span></pre><p class="primary">
</p><p class="secondary"><b>Gradle.&nbsp;</b>
</p><pre class="programlisting">ext {
contractsDir = file(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"mappings"</span>)
stubsOutputDirRoot = file(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"${project.buildDir}/production/${project.name}-stubs/"</span>)
}
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Automatically added by plugin:</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// copyContracts - copies contracts to the output folder from which JAR will be created</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// verifierStubsJar - JAR with a provided stub suffix</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// the presented publication is also added by the plugin but you can modify it as you wish</span>
publishing {
publications {
stubs(MavenPublication) {
artifactId <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"${project.name}-stubs"</span>
artifact verifierStubsJar
}
}
}</pre><p class="secondary">
</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_stub_runner_core" href="#_stub_runner_core"></a>6.3&nbsp;Stub Runner Core</h2></div></div></div><p>Runs stubs for service collaborators. Treating stubs as contracts of services allows to use stub-runner as an implementation of
<a class="link" href="https://martinfowler.com/articles/consumerDrivenContracts.html" target="_top">Consumer Driven Contracts</a>.</p><p>Stub Runner allows you to automatically download the stubs of the provided dependencies (or pick those from the classpath), start WireMock servers for them and feed them with proper stub definitions.
For messaging, special stub routes are defined.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_retrieving_stubs" href="#_retrieving_stubs"></a>6.3.1&nbsp;Retrieving stubs</h3></div></div></div><p>You can pick the following options of acquiring stubs</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Aether based solution that downloads JARs with stubs from Artifactory / Nexus</li><li class="listitem">Classpath scanning solution that searches classpath via pattern to retrieve stubs</li><li class="listitem">Write your own implementation of the <code class="literal">org.springframework.cloud.contract.stubrunner.StubDownloaderBuilder</code> for full customization</li></ul></div><p>The latter example is described in the <a class="link" href="">Custom Stub Runner</a> section.</p><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_stub_downloading" href="#_stub_downloading"></a>Stub downloading</h4></div></div></div><p>If you provide the <code class="literal">stubrunner.repositoryRoot</code> or <code class="literal">stubrunner.workOffline</code> flag will be set
to <code class="literal">true</code> then Stub Runner will connect to the given server and download the required jars.
It will then unpack the JAR to a temporary folder and reference those files in further
contract processing.</p><p>Example:</p><pre class="programlisting">@AutoConfigureStubRunner(repositoryRoot=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"https://foo.bar"</span>, ids = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"com.example:beer-api-producer:+:stubs:8095"</span>)</pre></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_classpath_scanning" href="#_classpath_scanning"></a>Classpath scanning</h4></div></div></div><p>If you <span class="strong"><strong>DON&#8217;T</strong></span> provide the <code class="literal">stubrunner.repositoryRoot</code> and <code class="literal">stubrunner.workOffline</code> flag will
be set to <code class="literal">false</code> (that&#8217;s the default) then classpath will get scanned. Let&#8217;s look at the
following example:</p><pre class="programlisting">@AutoConfigureStubRunner(ids = {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"com.example:beer-api-producer:+:stubs:8095"</span>,
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"com.example.foo:bar:1.0.0:superstubs:8096"</span>
})</pre><p>If you&#8217;ve added the dependencies to your classpath</p><p class="primary"><b>Maven.&nbsp;</b>
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;dependency&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>com.example<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>beer-api-producer-restdocs<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;classifier&gt;</span>stubs<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/classifier&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;version&gt;</span>0.0.1-SNAPSHOT<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/version&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;scope&gt;</span>test<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/scope&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;exclusions&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;exclusion&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>*<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>*<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/exclusion&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/exclusions&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/dependency&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;dependency&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>com.example.foo<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>bar<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;classifier&gt;</span>superstubs<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/classifier&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;version&gt;</span>1.0.0<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/version&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;scope&gt;</span>test<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/scope&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;exclusions&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;exclusion&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>*<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>*<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/exclusion&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/exclusions&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/dependency&gt;</span></pre><p class="primary">
</p><p class="secondary"><b>Gradle.&nbsp;</b>
</p><pre class="programlisting">testCompile(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"com.example:beer-api-producer-restdocs:0.0.1-SNAPSHOT:stubs"</span>) {
transitive = false
}
testCompile(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"com.example.foo:bar:1.0.0:superstubs"</span>) {
transitive = false
}</pre><p class="secondary">
</p><p>Then the following locations on your classpath will get scanned. For <code class="literal">com.example:beer-api-producer-restdocs</code></p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">/META-INF/com.example/beer-api-producer-restdocs/<span class="strong"><strong>*/</strong></span>.*</li><li class="listitem">/contracts/com.example/beer-api-producer-restdocs/<span class="strong"><strong>*/</strong></span>.*</li><li class="listitem">/mappings/com.example/beer-api-producer-restdocs/<span class="strong"><strong>*/</strong></span>.*</li></ul></div><p>and <code class="literal">com.example.foo:bar</code></p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">/META-INF/com.example.foo/bar/<span class="strong"><strong>*/</strong></span>.*</li><li class="listitem">/contracts/com.example.foo/bar/<span class="strong"><strong>*/</strong></span>.*</li><li class="listitem">/mappings/com.example.foo/bar/<span class="strong"><strong>*/</strong></span>.*</li></ul></div><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Tip</th></tr><tr><td align="left" valign="top"><p>As you can see you have to explicitly provide the group and artifact ids when packaging the
producer stubs.</p></td></tr></table></div><p>The producer would setup the contracts like this:</p><pre class="programlisting">&#9492;&#9472;&#9472; src
&#9492;&#9472;&#9472; <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">test</span>
&#9492;&#9472;&#9472; resources
&#9492;&#9472;&#9472; contracts
&nbsp;&nbsp; &#9492;&#9472;&#9472; com.example
&nbsp;&nbsp; &nbsp;&nbsp; &#9492;&#9472;&#9472; beer-api-producer-restdocs
&nbsp;&nbsp; &nbsp;&nbsp; &#9492;&#9472;&#9472; nested
&nbsp;&nbsp; &nbsp;&nbsp; &#9492;&#9472;&#9472; contract3.groovy</pre><p>To achieve proper stub packaging.</p><p>Or using the <a class="link" href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples/blob/master/producer_with_restdocs/pom.xml" target="_top">Maven <code class="literal">assembly</code> plugin</a> or
<a class="link" href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples/blob/master/producer_with_restdocs/build.gradle" target="_top">Gradle Jar</a> task you have to create the following
structure in your stubs jar.</p><pre class="programlisting">&#9492;&#9472;&#9472; META-INF
&#9492;&#9472;&#9472; com.example
&#9492;&#9472;&#9472; beer-api-producer-restdocs
&#9492;&#9472;&#9472; <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>
&#9500;&#9472;&#9472; contracts
&#9474;&nbsp;&nbsp; &#9492;&#9472;&#9472; nested
&nbsp;&nbsp; &#9474; &#9492;&#9472;&#9472; contract2.groovy
&nbsp;&nbsp; &#9492;&#9472;&#9472; mappings
&nbsp;&nbsp; &#9492;&#9472;&#9472; mapping.json</pre><p>By maintaining this structure classpath gets scanned and you can profit from the messaging /
HTTP stubs without the need to download artifacts.</p></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_running_stubs" href="#_running_stubs"></a>6.3.2&nbsp;Running stubs</h3></div></div></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_running_using_main_app" href="#_running_using_main_app"></a>Running using main app</h4></div></div></div><p>You can set the following options to the main class:</p><pre class="programlisting">-c, --classifier Suffix <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">for</span> the jar containing stubs (e.
g. <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'stubs'</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">if</span> the stub jar would
have a <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'stubs'</span> classifier <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">for</span> stubs:
foobar-stubs ). Defaults to <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'stubs'</span>
(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">default</span>: stubs)
--maxPort, --maxp &lt;Integer&gt; Maximum port value to be assigned to
the WireMock instance. Defaults to
<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">15000</xslthl:number> (<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">default</span>: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">15000</xslthl:number>)
--minPort, --minp &lt;Integer&gt; Minimum port value to be assigned to
the WireMock instance. Defaults to
<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">10000</xslthl:number> (<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">default</span>: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">10000</xslthl:number>)
-p, --password Password to user when connecting to
repository
--phost, --proxyHost Proxy host to use <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">for</span> repository
requests
--pport, --proxyPort [Integer] Proxy port to use <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">for</span> repository
requests
-r, --root Location of a Jar containing server
where you keep your stubs (e.g. http:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//nexus.</span>
net/content/repositories/repository)
-s, --stubs Comma separated list of Ivy
representation of jars with stubs.
Eg. groupid:artifactid1,groupid2:
artifactid2:classifier
-u, --username Username to user when connecting to
repository
--wo, --workOffline Switch to work offline. Defaults to
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'false'</span></pre></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_http_stubs" href="#_http_stubs"></a>HTTP Stubs</h4></div></div></div><p>Stubs are defined in JSON documents, whose syntax is defined in <a class="link" href="https://wiremock.org/stubbing.html" target="_top">WireMock documentation</a></p><p>Example:</p><pre class="programlisting">{
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"request"</span>: {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"method"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"GET"</span>,
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"url"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/ping"</span>
},
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"response"</span>: {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"status"</span>: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>,
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"body"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"pong"</span>,
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"headers"</span>: {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Content-Type"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"text/plain"</span>
}
}
}</pre></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_viewing_registered_mappings" href="#_viewing_registered_mappings"></a>Viewing registered mappings</h4></div></div></div><p>Every stubbed collaborator exposes list of defined mappings under <code class="literal">__/admin/</code> endpoint.</p><p>You can also use the <code class="literal">mappingsOutputFolder</code> property to dump the mappings to files.
For annotation based approach it would look like this</p><pre class="programlisting">@AutoConfigureStubRunner(ids=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"a.b.c:loanIssuance,a.b.c:fraudDetectionServer"</span>,
mappingsOutputFolder = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"target/outputmappings/"</span>)</pre><p>and for the JUnit approach like this:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@ClassRule</xslthl:annotation> <xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Shared</xslthl:annotation> StubRunnerRule rule = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> StubRunnerRule()
.repoRoot(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"http://some_url"</span>)
.downloadStub(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"a.b.c"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"loanIssuance"</span>)
.downloadStub(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"a.b.c:fraudDetectionServer"</span>)
.withMappingsOutputFolder(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"target/outputmappings"</span>)</pre><p>Then if you check out the folder <code class="literal">target/outputmappings</code> you would see the following structure</p><pre class="programlisting">.
&#9500;&#9472;&#9472; fraudDetectionServer_<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">13705</xslthl:number>
&#9492;&#9472;&#9472; loanIssuance_<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">12255</xslthl:number></pre><p>That means that there were two stubs registered. <code class="literal">fraudDetectionServer</code> was registered at port <code class="literal">13705</code>
and <code class="literal">loanIssuance</code> at port <code class="literal">12255</code>. If we take a look at one of the files we would see (for WireMock)
mappings available for the given server:</p><pre class="programlisting">[<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"id"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"f9152eb9-bf77-4c38-8289-90be7d10d0d7"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"request"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"url"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/name"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"method"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"GET"</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"response"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"status"</span> : <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"body"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"fraudDetectionServer"</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"uuid"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"f9152eb9-bf77-4c38-8289-90be7d10d0d7"</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span>
...
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">]</span></pre></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_messaging_stubs" href="#_messaging_stubs"></a>Messaging Stubs</h4></div></div></div><p>Depending on the provided Stub Runner dependency and the DSL the messaging routes are automatically set up.</p></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_stub_runner_junit_rule" href="#_stub_runner_junit_rule"></a>6.4&nbsp;Stub Runner JUnit Rule</h2></div></div></div><p>Stub Runner comes with a JUnit rule thanks to which you can very easily download and run stubs for given group and artifact id:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@ClassRule</xslthl:annotation> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> StubRunnerRule rule = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> StubRunnerRule()
.repoRoot(repoRoot())
.downloadStub(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud.contract.verifier.stubs"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"loanIssuance"</span>)
.downloadStub(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer"</span>);</pre><p>After that rule gets executed Stub Runner connects to your Maven repository and for the given list of dependencies tries to:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">download them</li><li class="listitem">cache them locally</li><li class="listitem">unzip them to a temporary folder</li><li class="listitem">start a WireMock server for each Maven dependency on a random port from the provided range of ports / provided port</li><li class="listitem">feed the WireMock server with all JSON files that are valid WireMock definitions</li><li class="listitem">can also send messages (remember to pass an implementation of <code class="literal">MessageVerifier</code> interface)</li></ul></div><p>Stub Runner uses <a class="link" href="https://wiki.eclipse.org/Aether" target="_top">Eclipse Aether</a> mechanism to download the Maven dependencies.
Check their <a class="link" href="https://wiki.eclipse.org/Aether" target="_top">docs</a> for more information.</p><p>Since the <code class="literal">StubRunnerRule</code> implements the <code class="literal">StubFinder</code> it allows you to find the started stubs:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">package</span> org.springframework.cloud.contract.stubrunner;
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> java.net.URL;
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> java.util.Collection;
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> java.util.Map;
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.cloud.contract.spec.Contract;
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">interface</span> StubFinder <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">extends</span> StubTrigger {
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
* For the given groupId and artifactId tries to find the matching
* URL of the running stub.
*
* @param groupId - might be null. In that case a search only via artifactId takes place
* @return URL of a running stub or throws exception if not found
*/</xslthl:doccomment>
URL findStubUrl(String groupId, String artifactId) <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> StubNotFoundException;
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
* For the given Ivy notation {@code [groupId]:artifactId:[version]:[classifier]} tries to
* find the matching URL of the running stub. You can also pass only {@code artifactId}.
*
* @param ivyNotation - Ivy representation of the Maven artifact
* @return URL of a running stub or throws exception if not found
*/</xslthl:doccomment>
URL findStubUrl(String ivyNotation) <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> StubNotFoundException;
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
* Returns all running stubs
*/</xslthl:doccomment>
RunningStubs findAllRunningStubs();
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
* Returns the list of Contracts
*/</xslthl:doccomment>
Map&lt;StubConfiguration, Collection&lt;Contract&gt;&gt; getContracts();
}</pre><p>Example of usage in Spock tests:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@ClassRule</xslthl:annotation> <xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Shared</xslthl:annotation> StubRunnerRule rule = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> StubRunnerRule()
.repoRoot(StubRunnerRuleSpec.getResource(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/m2repo/repository"</span>).toURI().toString())
.downloadStub(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud.contract.verifier.stubs"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"loanIssuance"</span>)
.downloadStub(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer"</span>)
.withMappingsOutputFolder(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"target/outputmappingsforrule"</span>)
def <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'should start WireMock servers'</span>() {
expect: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'WireMocks are running'</span>
rule.findStubUrl(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'org.springframework.cloud.contract.verifier.stubs'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'loanIssuance'</span>) != null
rule.findStubUrl(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'loanIssuance'</span>) != null
rule.findStubUrl(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'loanIssuance'</span>) == rule.findStubUrl(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'org.springframework.cloud.contract.verifier.stubs'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'loanIssuance'</span>)
rule.findStubUrl(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer'</span>) != null
and:
rule.findAllRunningStubs().isPresent(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'loanIssuance'</span>)
rule.findAllRunningStubs().isPresent(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'org.springframework.cloud.contract.verifier.stubs'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'fraudDetectionServer'</span>)
rule.findAllRunningStubs().isPresent(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer'</span>)
and: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'Stubs were registered'</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"${rule.findStubUrl('loanIssuance').toString()}/name"</span>.toURL().text == <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'loanIssuance'</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"${rule.findStubUrl('fraudDetectionServer').toString()}/name"</span>.toURL().text == <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'fraudDetectionServer'</span>
}
def <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'should output mappings to output folder'</span>() {
when:
def url = rule.findStubUrl(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'fraudDetectionServer'</span>)
then:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> File(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"target/outputmappingsforrule"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"fraudDetectionServer_${url.port}"</span>).exists()
}</pre><p>Example of usage in JUnit tests:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Test</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> should_start_wiremock_servers() <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> Exception {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// expect: 'WireMocks are running'</span>
then(rule.findStubUrl(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud.contract.verifier.stubs"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"loanIssuance"</span>)).isNotNull();
then(rule.findStubUrl(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"loanIssuance"</span>)).isNotNull();
then(rule.findStubUrl(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"loanIssuance"</span>)).isEqualTo(rule.findStubUrl(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud.contract.verifier.stubs"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"loanIssuance"</span>));
then(rule.findStubUrl(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer"</span>)).isNotNull();
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// and:</span>
then(rule.findAllRunningStubs().isPresent(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"loanIssuance"</span>)).isTrue();
then(rule.findAllRunningStubs().isPresent(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud.contract.verifier.stubs"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"fraudDetectionServer"</span>)).isTrue();
then(rule.findAllRunningStubs().isPresent(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer"</span>)).isTrue();
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// and: 'Stubs were registered'</span>
then(httpGet(rule.findStubUrl(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"loanIssuance"</span>).toString() + <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/name"</span>)).isEqualTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"loanIssuance"</span>);
then(httpGet(rule.findStubUrl(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"fraudDetectionServer"</span>).toString() + <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/name"</span>)).isEqualTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"fraudDetectionServer"</span>);
}</pre><p>Check the <span class="strong"><strong>Common properties for JUnit and Spring</strong></span> for more information on how to apply global configuration of Stub Runner.</p><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>To use the JUnit rule together with messaging you have to provide an implementation of the
<code class="literal">MessageVerifier</code> interface to the rule builder (e.g. <code class="literal">rule.messageVerifier(new MyMessageVerifier())</code>).
If you don&#8217;t do this then whenever you try to send a message an exception will be thrown.</p></td></tr></table></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_maven_settings" href="#_maven_settings"></a>6.4.1&nbsp;Maven settings</h3></div></div></div><p>The stub downloader honors Maven settings for a different local repository folder.
Authentication details for repositories and profiles are currently not taken into account, so you need to specify it using the properties mentioned above.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_providing_fixed_ports" href="#_providing_fixed_ports"></a>6.4.2&nbsp;Providing fixed ports</h3></div></div></div><p>You can also run your stubs on fixed ports. You can do it in two different ways. One is to pass it in the properties, and the other via fluent API of
JUnit rule.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_fluent_api" href="#_fluent_api"></a>6.4.3&nbsp;Fluent API</h3></div></div></div><p>When using the <code class="literal">StubRunnerRule</code> you can add a stub to download and then pass the port for the last downloaded stub.</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@ClassRule</xslthl:annotation> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> StubRunnerRule rule = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> StubRunnerRule()
.repoRoot(repoRoot())
.downloadStub(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud.contract.verifier.stubs"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"loanIssuance"</span>)
.withPort(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">12345</xslthl:number>)
.downloadStub(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer:12346"</span>);</pre><p>You can see that for this example the following test is valid:</p><pre class="programlisting">then(rule.findStubUrl(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"loanIssuance"</span>)).isEqualTo(URI.create(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"http://localhost:12345"</span>).toURL());
then(rule.findStubUrl(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"fraudDetectionServer"</span>)).isEqualTo(URI.create(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"http://localhost:12346"</span>).toURL());</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_stub_runner_with_spring" href="#_stub_runner_with_spring"></a>6.4.4&nbsp;Stub Runner with Spring</h3></div></div></div><p>Sets up Spring configuration of the Stub Runner project.</p><p>By providing a list of stubs inside your configuration file the Stub Runner automatically downloads
and registers in WireMock the selected stubs.</p><p>If you want to find the URL of your stubbed dependency you can autowire the <code class="literal">StubFinder</code> interface and use
its methods as presented below:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@ContextConfiguration(classes = Config, loader = SpringBootContextLoader)</xslthl:annotation>
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootTest(properties = [" stubrunner.cloud.enabled=false",
"stubrunner.camel.enabled=false",
'foo=${stubrunner.runningstubs.fraudDetectionServer.port}'])</xslthl:annotation>
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@AutoConfigureStubRunner(mappingsOutputFolder = "target/outputmappings/")</xslthl:annotation>
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@ActiveProfiles("test")</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> StubRunnerConfigurationSpec <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">extends</span> Specification {
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Autowired</xslthl:annotation> StubFinder stubFinder
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Autowired</xslthl:annotation> Environment environment
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Value('${foo}')</xslthl:annotation> Integer foo
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@BeforeClass</xslthl:annotation>
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@AfterClass</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> setupProps() {
System.clearProperty(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"stubrunner.repository.root"</span>)
System.clearProperty(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"stubrunner.classifier"</span>)
}
def <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'should start WireMock servers'</span>() {
expect: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'WireMocks are running'</span>
stubFinder.findStubUrl(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'org.springframework.cloud.contract.verifier.stubs'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'loanIssuance'</span>) != null
stubFinder.findStubUrl(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'loanIssuance'</span>) != null
stubFinder.findStubUrl(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'loanIssuance'</span>) == stubFinder.findStubUrl(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'org.springframework.cloud.contract.verifier.stubs'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'loanIssuance'</span>)
stubFinder.findStubUrl(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'loanIssuance'</span>) == stubFinder.findStubUrl(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'org.springframework.cloud.contract.verifier.stubs:loanIssuance'</span>)
stubFinder.findStubUrl(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'org.springframework.cloud.contract.verifier.stubs:loanIssuance:0.0.1-SNAPSHOT'</span>) == stubFinder.findStubUrl(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'org.springframework.cloud.contract.verifier.stubs:loanIssuance:0.0.1-SNAPSHOT:stubs'</span>)
stubFinder.findStubUrl(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer'</span>) != null
and:
stubFinder.findAllRunningStubs().isPresent(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'loanIssuance'</span>)
stubFinder.findAllRunningStubs().isPresent(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'org.springframework.cloud.contract.verifier.stubs'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'fraudDetectionServer'</span>)
stubFinder.findAllRunningStubs().isPresent(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer'</span>)
and: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'Stubs were registered'</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"${stubFinder.findStubUrl('loanIssuance').toString()}/name"</span>.toURL().text == <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'loanIssuance'</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"${stubFinder.findStubUrl('fraudDetectionServer').toString()}/name"</span>.toURL().text == <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'fraudDetectionServer'</span>
}
def <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'should throw an exception when stub is not found'</span>() {
when:
stubFinder.findStubUrl(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'nonExistingService'</span>)
then:
thrown(StubNotFoundException)
when:
stubFinder.findStubUrl(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'nonExistingGroupId'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'nonExistingArtifactId'</span>)
then:
thrown(StubNotFoundException)
}
def <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'should register started servers as environment variables'</span>() {
expect:
environment.getProperty(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"stubrunner.runningstubs.loanIssuance.port"</span>) != null
stubFinder.findAllRunningStubs().getPort(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"loanIssuance"</span>) == (environment.getProperty(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"stubrunner.runningstubs.loanIssuance.port"</span>) as Integer)
and:
environment.getProperty(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"stubrunner.runningstubs.fraudDetectionServer.port"</span>) != null
stubFinder.findAllRunningStubs().getPort(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"fraudDetectionServer"</span>) == (environment.getProperty(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"stubrunner.runningstubs.fraudDetectionServer.port"</span>) as Integer)
}
def <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'should be able to interpolate a running stub in the passed test property'</span>() {
given:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">int</span> fraudPort = stubFinder.findAllRunningStubs().getPort(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"fraudDetectionServer"</span>)
expect:
fraudPort &gt; <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>
environment.getProperty(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"foo"</span>, Integer) == fraudPort
foo == fraudPort
}
def <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'should dump all mappings to a file'</span>() {
when:
def url = stubFinder.findStubUrl(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"fraudDetectionServer"</span>)
then:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> File(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"target/outputmappings/"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"fraudDetectionServer_${url.port}"</span>).exists()
}
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Configuration</xslthl:annotation>
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@EnableAutoConfiguration</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> Config {}
}</pre><p>for the following configuration file:</p><pre class="programlisting">stubrunner:
repositoryRoot: classpath:m2repo/repository/
ids:
- org.springframework.cloud.contract.verifier.stubs:loanIssuance
- org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer
- org.springframework.cloud.contract.verifier.stubs:bootService</pre><p>Instead of using the properties you can also use the properties inside the <code class="literal">@AutoConfigureStubRunner</code>.
Below you can find an example of achieving the same result by setting values on the annotation.</p><pre class="programlisting">@AutoConfigureStubRunner(
ids = [<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud.contract.verifier.stubs:loanIssuance"</span>,
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer"</span>,
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud.contract.verifier.stubs:bootService"</span>],
repositoryRoot = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"classpath:m2repo/repository/"</span>)</pre><p>Stub Runner Spring registers environment variables in the following manner
for every registered WireMock server. Example for Stub Runner ids
<code class="literal">com.example:foo</code>, <code class="literal">com.example:bar</code>.</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">stubrunner.runningstubs.foo.port</code></li><li class="listitem"><code class="literal">stubrunner.runningstubs.bar.port</code></li></ul></div><p>Which you can reference in your code.</p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_stub_runner_spring_cloud" href="#_stub_runner_spring_cloud"></a>6.5&nbsp;Stub Runner Spring Cloud</h2></div></div></div><p>Stub Runner can integrate with Spring Cloud.</p><p>For real life examples you can check the</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a class="link" href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/master/producer" target="_top">producer app sample</a></li><li class="listitem"><a class="link" href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/master/consumer_with_discovery" target="_top">consumer app sample</a></li></ul></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_stubbing_service_discovery" href="#_stubbing_service_discovery"></a>6.5.1&nbsp;Stubbing Service Discovery</h3></div></div></div><p>The most important feature of <code class="literal">Stub Runner Spring Cloud</code> is the fact that it&#8217;s stubbing</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">DiscoveryClient</code></li><li class="listitem"><code class="literal">Ribbon</code> <code class="literal">ServerList</code></li></ul></div><p>that means that regardless of the fact whether you&#8217;re using Zookeeper, Consul, Eureka or anything else, you don&#8217;t need that in your tests.
We&#8217;re starting WireMock instances of your dependencies and we&#8217;re telling your application whenever you&#8217;re using <code class="literal">Feign</code>, load balanced <code class="literal">RestTemplate</code>
or <code class="literal">DiscoveryClient</code> directly, to call those stubbed servers instead of calling the real Service Discovery tool.</p><p>For example this test will pass</p><pre class="programlisting">def <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'should make service discovery work'</span>() {
expect: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'WireMocks are running'</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"${stubFinder.findStubUrl('loanIssuance').toString()}/name"</span>.toURL().text == <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'loanIssuance'</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"${stubFinder.findStubUrl('fraudDetectionServer').toString()}/name"</span>.toURL().text == <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'fraudDetectionServer'</span>
and: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'Stubs can be reached via load service discovery'</span>
restTemplate.getForObject(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'http://loanIssuance/name'</span>, String) == <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'loanIssuance'</span>
restTemplate.getForObject(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'http://someNameThatShouldMapFraudDetectionServer/name'</span>, String) == <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'fraudDetectionServer'</span>
}</pre><p>for the following configuration file</p><pre class="programlisting">stubrunner:
idsToServiceIds:
ivyNotation: someValueInsideYourCode
fraudDetectionServer: someNameThatShouldMapFraudDetectionServer</pre><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_test_profiles_and_service_discovery" href="#_test_profiles_and_service_discovery"></a>Test profiles and service discovery</h4></div></div></div><p>In your integration tests you typically don&#8217;t want to call neither a discovery service (e.g. Eureka)
or Config Server. That&#8217;s why you create an additional test configuration in which you want to disable
these features.</p><p>Due to certain limitations of <a class="link" href="https://github.com/spring-cloud/spring-cloud-commons/issues/156" target="_top"><code class="literal">spring-cloud-commons</code></a> to achieve this you have disable these properties
via a static block like presented below (example for Eureka)</p><pre class="programlisting"> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//Hack to work around https://github.com/spring-cloud/spring-cloud-commons/issues/156</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> {
System.setProperty(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"eureka.client.enabled"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"false"</span>);
System.setProperty(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"spring.cloud.config.failFast"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"false"</span>);
}</pre></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_additional_configuration" href="#_additional_configuration"></a>6.5.2&nbsp;Additional Configuration</h3></div></div></div><p>You can match the artifactId of the stub with the name of your app by using the <code class="literal">stubrunner.idsToServiceIds:</code> map.
You can disable Stub Runner Ribbon support by providing: <code class="literal">stubrunner.cloud.ribbon.enabled</code> equal to <code class="literal">false</code>
You can disable Stub Runner support by providing: <code class="literal">stubrunner.cloud.enabled</code> equal to <code class="literal">false</code></p><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Tip</th></tr><tr><td align="left" valign="top"><p>By default all service discovery will be stubbed. That means that regardless of the fact if you have
an existing <code class="literal">DiscoveryClient</code> its results will be ignored. However, if you want to reuse it, just set
<code class="literal">stubrunner.cloud.delegate.enabled</code> to <code class="literal">true</code> and then your existing <code class="literal">DiscoveryClient</code> results will be
merged with the stubbed ones.</p></td></tr></table></div><p>The default Maven configuration used by Stub Runner can be tweaked either
via the following system properties or environment variables</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">maven.repo.local</code> - path to the custom maven local repository location</li><li class="listitem"><code class="literal">org.apache.maven.user-settings</code> - path to custom maven user settings location</li><li class="listitem"><code class="literal">org.apache.maven.global-settings</code> - path to maven global settings location</li></ul></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_stub_runner_boot_application" href="#_stub_runner_boot_application"></a>6.6&nbsp;Stub Runner Boot Application</h2></div></div></div><p>Spring Cloud Contract Stub Runner Boot is a Spring Boot application that exposes REST endpoints to
trigger the messaging labels and to access started WireMock servers.</p><p>One of the use-cases is to run some smoke (end to end) tests on a deployed application.
You can check out the <a class="link" href="https://github.com/spring-cloud/spring-cloud-pipelines" target="_top">Spring Cloud Pipelines</a>
project for more information.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_how_to_use_it" href="#_how_to_use_it"></a>6.6.1&nbsp;How to use it?</h3></div></div></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_stub_runner_server" href="#_stub_runner_server"></a>Stub Runner Server</h4></div></div></div><p>Just add the</p><pre class="programlisting">compile <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud:spring-cloud-starter-stub-runner"</span></pre><p>Annotate a class with <code class="literal">@EnableStubRunnerServer</code>, build a fat-jar and you&#8217;re ready to go!</p><p>For the properties check the <span class="strong"><strong>Stub Runner Spring</strong></span> section.</p></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_stub_runner_server_fat_jar" href="#_stub_runner_server_fat_jar"></a>Stub Runner Server Fat Jar</h4></div></div></div><p>You can download a standalone JAR from Maven (for example, for version 1.2.3.RELEASE), as follows:</p><pre class="programlisting">$ wget -O stub-runner.jar <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'https://search.maven.org/remote_content?g=org.springframework.cloud&amp;a=spring-cloud-contract-stub-runner-boot&amp;v=1.2.3.RELEASE'</span>
$ java -jar stub-runner.jar --stubrunner.ids=... --stubrunner.repositoryRoot=...</pre></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_spring_cloud_cli" href="#_spring_cloud_cli"></a>Spring Cloud CLI</h4></div></div></div><p>Starting from <code class="literal">1.4.0.RELEASE</code> version of the <a class="link" href="https://cloud.spring.io/spring-cloud-cli" target="_top">Spring Cloud CLI</a>
project you can start Stub Runner Boot by executing <code class="literal">spring cloud stubrunner</code>.</p><p>In order to pass the configuration just create a <code class="literal">stubrunner.yml</code> file in the current working directory
or a subdirectory called <code class="literal">config</code> or in <code class="literal">~/.spring-cloud</code>. The file could look like this
(example for running stubs installed locally)</p><p><b>stubrunner.yml.&nbsp;</b>
</p><pre class="programlisting">stubrunner:
workOffline: true
ids:
- com.example:beer-api-producer:+:9876</pre><p>
</p><p>and then just call <code class="literal">spring cloud stubrunner</code> from your terminal window to start
the Stub Runner server. It will be available at port <code class="literal">8750</code>.</p></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_endpoints" href="#_endpoints"></a>6.6.2&nbsp;Endpoints</h3></div></div></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_http" href="#_http"></a>HTTP</h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">GET <code class="literal">/stubs</code> - returns a list of all running stubs in <code class="literal">ivy:integer</code> notation</li><li class="listitem">GET <code class="literal">/stubs/{ivy}</code> - returns a port for the given <code class="literal">ivy</code> notation (when calling the endpoint <code class="literal">ivy</code> can also be <code class="literal">artifactId</code> only)</li></ul></div></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_messaging" href="#_messaging"></a>Messaging</h4></div></div></div><p>For Messaging</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">GET <code class="literal">/triggers</code> - returns a list of all running labels in <code class="literal">ivy : [ label1, label2 &#8230;&#8203;]</code> notation</li><li class="listitem">POST <code class="literal">/triggers/{label}</code> - executes a trigger with <code class="literal">label</code></li><li class="listitem">POST <code class="literal">/triggers/{ivy}/{label}</code> - executes a trigger with <code class="literal">label</code> for the given <code class="literal">ivy</code> notation (when calling the endpoint <code class="literal">ivy</code> can also be <code class="literal">artifactId</code> only)</li></ul></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_example" href="#_example"></a>6.6.3&nbsp;Example</h3></div></div></div><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@ContextConfiguration(classes = StubRunnerBoot, loader = SpringBootContextLoader)</xslthl:annotation>
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootTest(properties = "spring.cloud.zookeeper.enabled=false")</xslthl:annotation>
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@ActiveProfiles("test")</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> StubRunnerBootSpec <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">extends</span> Specification {
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Autowired</xslthl:annotation> StubRunning stubRunning
def setup() {
RestAssuredMockMvc.standaloneSetup(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> HttpStubsController(stubRunning),
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> TriggerController(stubRunning))
}
def <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'should return a list of running stub servers in "full ivy:port" notation'</span>() {
when:
String response = RestAssuredMockMvc.get(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'/stubs'</span>).body.asString()
then:
def root = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> JsonSlurper().parseText(response)
root.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'org.springframework.cloud.contract.verifier.stubs:bootService:0.0.1-SNAPSHOT:stubs'</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">instanceof</span> Integer
}
def <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'should return a port on which a [#stubId] stub is running'</span>() {
when:
def response = RestAssuredMockMvc.get(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/stubs/${stubId}"</span>)
then:
response.statusCode == <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>
response.body.as(Integer) &gt; <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>
where:
stubId &lt;&lt; [<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'org.springframework.cloud.contract.verifier.stubs:bootService:+:stubs'</span>,
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'org.springframework.cloud.contract.verifier.stubs:bootService:0.0.1-SNAPSHOT:stubs'</span>,
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'org.springframework.cloud.contract.verifier.stubs:bootService:+'</span>,
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'org.springframework.cloud.contract.verifier.stubs:bootService'</span>,
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'bootService'</span>]
}
def <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'should return 404 when missing stub was called'</span>() {
when:
def response = RestAssuredMockMvc.get(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/stubs/a:b:c:d"</span>)
then:
response.statusCode == <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">404</xslthl:number>
}
def <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'should return a list of messaging labels that can be triggered when version and classifier are passed'</span>() {
when:
String response = RestAssuredMockMvc.get(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'/triggers'</span>).body.asString()
then:
def root = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> JsonSlurper().parseText(response)
root.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'org.springframework.cloud.contract.verifier.stubs:bootService:0.0.1-SNAPSHOT:stubs'</span>?.containsAll([<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"delete_book"</span>,<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"return_book_1"</span>,<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"return_book_2"</span>])
}
def <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'should trigger a messaging label'</span>() {
given:
StubRunning stubRunning = Mock()
RestAssuredMockMvc.standaloneSetup(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> HttpStubsController(stubRunning), <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> TriggerController(stubRunning))
when:
def response = RestAssuredMockMvc.post(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/triggers/delete_book"</span>)
then:
response.statusCode == <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>
and:
<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number> * stubRunning.trigger(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'delete_book'</span>)
}
def <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'should trigger a messaging label for a stub with [#stubId] ivy notation'</span>() {
given:
StubRunning stubRunning = Mock()
RestAssuredMockMvc.standaloneSetup(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> HttpStubsController(stubRunning), <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> TriggerController(stubRunning))
when:
def response = RestAssuredMockMvc.post(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/triggers/$stubId/delete_book"</span>)
then:
response.statusCode == <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>
and:
<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number> * stubRunning.trigger(stubId, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'delete_book'</span>)
where:
stubId &lt;&lt; [<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'org.springframework.cloud.contract.verifier.stubs:bootService:stubs'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'org.springframework.cloud.contract.verifier.stubs:bootService'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'bootService'</span>]
}
def <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'should throw exception when trigger is missing'</span>() {
when:
RestAssuredMockMvc.post(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/triggers/missing_label"</span>)
then:
Exception e = thrown(Exception)
e.message.contains(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Exception occurred while trying to return [missing_label] label."</span>)
e.message.contains(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Available labels are"</span>)
e.message.contains(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud.contract.verifier.stubs:loanIssuance:0.0.1-SNAPSHOT:stubs=[]"</span>)
e.message.contains(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud.contract.verifier.stubs:bootService:0.0.1-SNAPSHOT:stubs="</span>)
}
}</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_stub_runner_boot_with_service_discovery" href="#_stub_runner_boot_with_service_discovery"></a>6.6.4&nbsp;Stub Runner Boot with Service Discovery</h3></div></div></div><p>One of the possibilities of using Stub Runner Boot is to use it as a feed of stubs for "smoke-tests". What does it mean?
Let&#8217;s assume that you don&#8217;t want to deploy 50 microservice to a test environment in order
to check if your application is working fine. You&#8217;ve already executed a suite of tests during the build process
but you would also like to ensure that the packaging of your application is fine. What you can do
is to deploy your application to an environment, start it and run a couple of tests on it to see if
it&#8217;s working fine. We can call those tests smoke-tests since their idea is to check only a handful
of testing scenarios.</p><p>The problem with this approach is such that if you&#8217;re doing microservices most likely you&#8217;re
using a service discovery tool. Stub Runner Boot allows you to solve this issue by starting the
required stubs and register them in a service discovery tool. Let&#8217;s take a look at an example of
such a setup with Eureka. Let&#8217;s assume that Eureka was already running.</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootApplication</xslthl:annotation>
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@EnableStubRunnerServer</xslthl:annotation>
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@EnableEurekaClient</xslthl:annotation>
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@AutoConfigureStubRunner</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> StubRunnerBootEurekaExample {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> main(String[] args) {
SpringApplication.run(StubRunnerBootEurekaExample.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>, args);
}
}</pre><p>As you can see we want to start a Stub Runner Boot server <code class="literal">@EnableStubRunnerServer</code>, enable Eureka client <code class="literal">@EnableEurekaClient</code>
and we want to have the stub runner feature turned on <code class="literal">@AutoConfigureStubRunner</code>.</p><p>Now let&#8217;s assume that we want to start this application so that the stubs get automatically registered.
We can do it by running the app <code class="literal">java -jar ${SYSTEM_PROPS} stub-runner-boot-eureka-example.jar</code> where
<code class="literal">${SYSTEM_PROPS}</code> would contain the following list of properties</p><pre class="programlisting">-Dstubrunner.repositoryRoot=https://repo.spring.io/snapshot (<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>)
-Dstubrunner.cloud.stubbed.discovery.enabled=false (<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2</xslthl:number>)
-Dstubrunner.ids=org.springframework.cloud.contract.verifier.stubs:loanIssuance,org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer,org.springframework.cloud.contract.verifier.stubs:bootService (<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">3</xslthl:number>)
-Dstubrunner.idsToServiceIds.fraudDetectionServer=someNameThatShouldMapFraudDetectionServer (<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">4</xslthl:number>)
(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>) - we tell Stub Runner where all the stubs reside
(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2</xslthl:number>) - we don<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'t want the default behaviour where the discovery service is stubbed. That'</span>s why the stub registration will be picked
(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">3</xslthl:number>) - we provide a list of stubs to download
(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">4</xslthl:number>) - we provide a list of artifactId to serviceId mapping</pre><p>That way your deployed application can send requests to started WireMock servers via the service
discovery. Most likely points 1-3 could be set by default in <code class="literal">application.yml</code> cause they are not
likely to change. That way you can provide only the list of stubs to download whenever you start
the Stub Runner Boot.</p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_stubs_per_consumer" href="#_stubs_per_consumer"></a>6.7&nbsp;Stubs Per Consumer</h2></div></div></div><p>There are cases in which 2 consumers of the same endpoint want to have 2 different responses.</p><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Tip</th></tr><tr><td align="left" valign="top"><p>This approach also allows you to immediately know which consumer is using which part of your API.
You can remove part of a response that your API produces and you can see which of your autogenerated tests
fails. If none fails then you can safely delete that part of the response cause nobody is using it.</p></td></tr></table></div><p>Let&#8217;s look at the following example for contract defined for the producer called <code class="literal">producer</code>.
There are 2 consumers: <code class="literal">foo-consumer</code> and <code class="literal">bar-consumer</code>.</p><p><span class="strong"><strong>Consumer <code class="literal">foo-service</code></strong></span></p><pre class="programlisting">request {
url <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'/foo'</span>
method GET()
}
response {
status <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>
body(
foo: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"foo"</span>
}
}</pre><p><span class="strong"><strong>Consumer <code class="literal">bar-service</code></strong></span></p><pre class="programlisting">request {
url <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'/foo'</span>
method GET()
}
response {
status <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>
body(
bar: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"bar"</span>
}
}</pre><p>You can&#8217;t produce for the same request 2 different responses. That&#8217;s why you can properly package the
contracts and then profit from the <code class="literal">stubsPerConsumer</code> feature.</p><p>On the producer side the consumers can have a folder that contains contracts related only to them.
By setting the <code class="literal">stubrunner.stubs-per-consumer</code> flag to <code class="literal">true</code> we no longer register all stubs but only those that
correspond to the consumer application&#8217;s name. In other words we&#8217;ll scan the path of every stub and
if it contains the subfolder with name of the consumer in the path only then will it get registered.</p><p>On the <code class="literal">foo</code> producer side the contracts would look like this</p><pre class="programlisting">.
&#9492;&#9472;&#9472; contracts
&#9500;&#9472;&#9472; bar-consumer
&#9474;&nbsp;&nbsp; &#9500;&#9472;&#9472; bookReturnedForBar.groovy
&#9474;&nbsp;&nbsp; &#9492;&#9472;&#9472; shouldCallBar.groovy
&#9492;&#9472;&#9472; foo-consumer
&#9500;&#9472;&#9472; bookReturnedForFoo.groovy
&#9492;&#9472;&#9472; shouldCallFoo.groovy</pre><p>Being the <code class="literal">bar-consumer</code> consumer you can either set the <code class="literal">spring.application.name</code> or the <code class="literal">stubrunner.consumer-name</code> to <code class="literal">bar-consumer</code>
Or set the test as follows:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@ContextConfiguration(classes = Config, loader = SpringBootContextLoader)</xslthl:annotation>
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootTest(properties = ["spring.application.name=bar-consumer"])</xslthl:annotation>
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@AutoConfigureStubRunner(ids = "org.springframework.cloud.contract.verifier.stubs:producerWithMultipleConsumers",
repositoryRoot = "classpath:m2repo/repository/",
stubsPerConsumer = true)</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> StubRunnerStubsPerConsumerSpec <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">extends</span> Specification {
...
}</pre><p>Then only the stubs registered under a path that contains the <code class="literal">bar-consumer</code> in its name (i.e. those from the
<code class="literal">src/test/resources/contracts/bar-consumer/some/contracts/&#8230;&#8203;</code> folder) will be allowed to be referenced.</p><p>Or set the consumer name explicitly</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@ContextConfiguration(classes = Config, loader = SpringBootContextLoader)</xslthl:annotation>
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootTest</xslthl:annotation>
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@AutoConfigureStubRunner(ids = "org.springframework.cloud.contract.verifier.stubs:producerWithMultipleConsumers",
repositoryRoot = "classpath:m2repo/repository/",
consumerName = "foo-consumer",
stubsPerConsumer = true)</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> StubRunnerStubsPerConsumerWithConsumerNameSpec <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">extends</span> Specification {
...
}</pre><p>Then only the stubs registered under a path that contains the <code class="literal">foo-consumer</code> in its name (i.e. those from the
<code class="literal">src/test/resources/contracts/foo-consumer/some/contracts/&#8230;&#8203;</code> folder) will be allowed to be referenced.</p><p>You can check out <a class="link" href="https://github.com/spring-cloud/spring-cloud-contract/issues/224" target="_top">issue 224</a> for more
information about the reasons behind this change.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_common" href="#_common"></a>6.8&nbsp;Common</h2></div></div></div><p>This section briefly describes common properties, including:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a class="xref" href="multi__spring_cloud_contract_stub_runner.html#common-properties-junit-spring" title="6.8.1&nbsp;Common Properties for JUnit and Spring">Section&nbsp;6.8.1, &#8220;Common Properties for JUnit and Spring&#8221;</a></li><li class="listitem"><a class="xref" href="multi__spring_cloud_contract_stub_runner.html#stub-runner-stub-ids" title="6.8.2&nbsp;Stub Runner Stubs IDs">Section&nbsp;6.8.2, &#8220;Stub Runner Stubs IDs&#8221;</a></li></ul></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="common-properties-junit-spring" href="#common-properties-junit-spring"></a>6.8.1&nbsp;Common Properties for JUnit and Spring</h3></div></div></div><p>You can set repetitive properties by using system properties or Spring configuration
properties. Here are their names with their default values:</p><div class="informaltable"><table style="border-collapse: collapse;border-top: 0.5pt solid ; border-bottom: 0.5pt solid ; "><colgroup><col class="col_1"><col class="col_2"><col class="col_3"></colgroup><thead><tr><th style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left" valign="top">Property name</th><th style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left" valign="top">Default value</th><th style="border-bottom: 0.5pt solid ; " align="left" valign="top">Description</th></tr></thead><tbody><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left" valign="top"><p>stubrunner.minPort</p></td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left" valign="top"><p>10000</p></td><td style="border-bottom: 0.5pt solid ; " align="left" valign="top"><p>Minimum value of a port for a started WireMock with stubs.</p></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left" valign="top"><p>stubrunner.maxPort</p></td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left" valign="top"><p>15000</p></td><td style="border-bottom: 0.5pt solid ; " align="left" valign="top"><p>Maximum value of a port for a started WireMock with stubs.</p></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left" valign="top"><p>stubrunner.repositoryRoot</p></td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left" valign="top">&nbsp;</td><td style="border-bottom: 0.5pt solid ; " align="left" valign="top"><p>Maven repo URL. If blank, then call the local maven repo.</p></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left" valign="top"><p>stubrunner.classifier</p></td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left" valign="top"><p>stubs</p></td><td style="border-bottom: 0.5pt solid ; " align="left" valign="top"><p>Default classifier for the stub artifacts.</p></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left" valign="top"><p>stubrunner.workOffline</p></td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left" valign="top"><p>false</p></td><td style="border-bottom: 0.5pt solid ; " align="left" valign="top"><p>If true, then do not contact any remote repositories to
download stubs.</p></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left" valign="top"><p>stubrunner.ids</p></td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left" valign="top">&nbsp;</td><td style="border-bottom: 0.5pt solid ; " align="left" valign="top"><p>Array of Ivy notation stubs to download.</p></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left" valign="top"><p>stubrunner.username</p></td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left" valign="top">&nbsp;</td><td style="border-bottom: 0.5pt solid ; " align="left" valign="top"><p>Optional username to access the tool that stores the JARs with
stubs.</p></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left" valign="top"><p>stubrunner.password</p></td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left" valign="top">&nbsp;</td><td style="border-bottom: 0.5pt solid ; " align="left" valign="top"><p>Optional password to access the tool that stores the JARs with
stubs.</p></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left" valign="top"><p>stubrunner.stubsPerConsumer</p></td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left" valign="top"><p>false</p></td><td style="border-bottom: 0.5pt solid ; " align="left" valign="top"><p>Set to <code class="literal">true</code> if you want to use different stubs for
each consumer instead of registering all stubs for every consumer.</p></td></tr><tr><td style="border-right: 0.5pt solid ; " align="left" valign="top"><p>stubrunner.consumerName</p></td><td style="border-right: 0.5pt solid ; " align="left" valign="top">&nbsp;</td><td style="" align="left" valign="top"><p>If you want to use a stub for each consumer and want to
override the consumer name just change this value.</p></td></tr></tbody></table></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="stub-runner-stub-ids" href="#stub-runner-stub-ids"></a>6.8.2&nbsp;Stub Runner Stubs IDs</h3></div></div></div><p>You can provide the stubs to download via the <code class="literal">stubrunner.ids</code> system property. They
follow this pattern:</p><pre class="programlisting">groupId:artifactId:version:classifier:port</pre><p>Note that <code class="literal">version</code>, <code class="literal">classifier</code> and <code class="literal">port</code> are optional.</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">If you do not provide the <code class="literal">port</code>, a random one will be picked.</li><li class="listitem">If you do not provide the <code class="literal">classifier</code>, the default is used. (Note that you can
pass an empty classifier this way: <code class="literal">groupId:artifactId:version:</code>).</li><li class="listitem">If you do not provide the <code class="literal">version</code>, then the <code class="literal">+</code> will be passed and the latest one is
downloaded.</li></ul></div><p><code class="literal">port</code> means the port of the WireMock server.</p><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>Starting with version 1.0.4, you can provide a range of versions that you
would like the Stub Runner to take into consideration. You can read more about the
<a class="link" href="https://wiki.eclipse.org/Aether/New_and_Noteworthy#Version_Ranges" target="_top">Aether versioning
ranges here</a>.</p></td></tr></table></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="stubrunner-docker" href="#stubrunner-docker"></a>6.9&nbsp;Stub Runner Docker</h2></div></div></div><p>We&#8217;re publishing a <code class="literal">spring-cloud/spring-cloud-contract-stub-runner</code> Docker image
that will start the standalone version of Stub Runner.</p><p>If you want to learn more about the basics of Maven, artifact ids,
group ids, classifiers and Artifact Managers, just click here <a class="xref" href="multi__spring_cloud_contract_verifier_setup.html#docker-project" title="4.6&nbsp;Docker Project">Section&nbsp;4.6, &#8220;Docker Project&#8221;</a>.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_how_to_use_it_2" href="#_how_to_use_it_2"></a>6.9.1&nbsp;How to use it</h3></div></div></div><p>Just execute the docker image. You can pass any of the <a class="xref" href="multi__spring_cloud_contract_stub_runner.html#common-properties-junit-spring" title="6.8.1&nbsp;Common Properties for JUnit and Spring">Section&nbsp;6.8.1, &#8220;Common Properties for JUnit and Spring&#8221;</a>
as environment variables. The convention is that all the
letters should be upper case. The camel case notation should
and the dot (<code class="literal">.</code>) should be separated via underscore (<code class="literal">_</code>). E.g.
the <code class="literal">stubrunner.repositoryRoot</code> property should be represented
as a <code class="literal">STUBRUNNER_REPOSITORY_ROOT</code> environment variable.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_example_of_client_side_usage_in_a_non_jvm_project" href="#_example_of_client_side_usage_in_a_non_jvm_project"></a>6.9.2&nbsp;Example of client side usage in a non JVM project</h3></div></div></div><p>We&#8217;d like to use the stubs created in this <a class="xref" href="multi__spring_cloud_contract_verifier_setup.html#docker-server-side" title="4.6.4&nbsp;Server side (nodejs)">Section&nbsp;4.6.4, &#8220;Server side (nodejs)&#8221;</a> step.
Let&#8217;s assume that we want to run the stubs on port <code class="literal">9876</code>. The NodeJS code
is available here:</p><pre class="programlisting">$ git clone https://github.com/spring-cloud-samples/spring-cloud-contract-nodejs
$ <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">cd</span> bookstore</pre><p>Let&#8217;s run the Stub Runner Boot application with the stubs.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"># Provide the Spring Cloud Contract Docker version</span>
$ SC_CONTRACT_DOCKER_VERSION=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"..."</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"># The IP at which the app is running and Docker container can reach it</span>
$ APP_IP=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"192.168.0.100"</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"># Spring Cloud Contract Stub Runner properties</span>
$ STUBRUNNER_PORT=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"8083"</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"># Stub coordinates 'groupId:artifactId:version:classifier:port'</span>
$ STUBRUNNER_IDS=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"com.example:bookstore:0.0.1.RELEASE:stubs:9876"</span>
$ STUBRUNNER_REPOSITORY_ROOT=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"http://${APP_IP}:8081/artifactory/libs-release-local"</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"># Run the docker with Stub Runner Boot</span>
$ docker run --rm -e <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"STUBRUNNER_IDS=${STUBRUNNER_IDS}"</span> -e <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"STUBRUNNER_REPOSITORY_ROOT=${STUBRUNNER_REPOSITORY_ROOT}"</span> -p <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"${STUBRUNNER_PORT}:${STUBRUNNER_PORT}"</span> -p <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"9876:9876"</span> springcloud/spring-cloud-contract-stub-runner:<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"${SC_CONTRACT_DOCKER_VERSION}"</span></pre><p>What&#8217;s happening is that</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">a standalone Stub Runner application got started</li><li class="listitem">it downloaded the stub with coordinates <code class="literal">com.example:bookstore:0.0.1.RELEASE:stubs</code> on port <code class="literal">9876</code></li><li class="listitem">it got downloaded from Artifactory running at <code class="literal"><a class="link" href="http://192.168.0.100:8081/artifactory/libs-release-local" target="_top">http://192.168.0.100:8081/artifactory/libs-release-local</a></code></li><li class="listitem">after a while Stub Runner will be running on port <code class="literal">8083</code></li><li class="listitem">and the stubs will be running at port <code class="literal">9876</code></li></ul></div><p>On the server side we built a stateful stub. Let&#8217;s use curl to assert
that the stubs are setup properly.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"># let's execute the first request (no response is returned)</span>
$ curl -H <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Content-Type:application/json"</span> -X POST --data <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'{ "title" : "Title", "genre" : "Genre", "description" : "Description", "author" : "Author", "publisher" : "Publisher", "pages" : 100, "image_url" : "https://d213dhlpdb53mu.cloudfront.net/assets/pivotal-square-logo-41418bd391196c3022f3cd9f3959b3f6d7764c47873d858583384e759c7db435.svg", "buy_url" : "https://pivotal.io" }'</span> http://localhost:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">9876</xslthl:number>/api/books
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"># Now time for the second request</span>
$ curl -X GET http://localhost:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">9876</xslthl:number>/api/books
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"># You will receive contents of the JSON</span></pre></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__spring_cloud_contract_verifier_messaging.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi__stub_runner_for_messaging.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">5.&nbsp;Spring Cloud Contract Verifier Messaging&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-contract.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;7.&nbsp;Stub Runner for Messaging</td></tr></table></div></body></html>

View File

@@ -0,0 +1,559 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>2.&nbsp;Spring Cloud Contract Verifier Introduction</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud-contract.html" title="Spring Cloud Contract"><link rel="up" href="multi_spring-cloud-contract.html" title="Spring Cloud Contract"><link rel="prev" href="multi__spring_cloud_contract.html" title="1.&nbsp;Spring Cloud Contract"><link rel="next" href="multi__spring_cloud_contract_faq.html" title="3.&nbsp;Spring Cloud Contract FAQ"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">2.&nbsp;Spring Cloud Contract Verifier Introduction</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__spring_cloud_contract.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi__spring_cloud_contract_faq.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_spring_cloud_contract_verifier_introduction" href="#_spring_cloud_contract_verifier_introduction"></a>2.&nbsp;Spring Cloud Contract Verifier Introduction</h1></div></div></div><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Tip</th></tr><tr><td align="left" valign="top"><p>The Accurest project was initially started by Marcin Grzejszczak and Jakub Kubrynski
(<a class="link" href="https://github.com/Codearte" target="_top">Codearte</a>)</p></td></tr></table></div><p>Spring Cloud Contract Verifier enables Consumer Driven Contract (CDC) development of
JVM-based applications. It moves TDD to the level of software architecture.</p><p>Spring Cloud Contract Verifier ships with <span class="emphasis"><em>Contract Definition Language</em></span> (CDL). Contract
definitions are used to produce the following resources:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">JSON stub definitions to be used by WireMock when doing integration testing on the
client code (<span class="emphasis"><em>client tests</em></span>). Test code must still be written by hand, and test data is
produced by Spring Cloud Contract Verifier.</li><li class="listitem">Messaging routes, if you&#8217;re using a messaging service. We integrate with Spring
Integration, Spring Cloud Stream, Spring AMQP, and Apache Camel. You can also set your
own integrations.</li><li class="listitem">Acceptance tests (in JUnit or Spock) are used to verify if server-side implementation
of the API is compliant with the contract (<span class="emphasis"><em>server tests</em></span>). A full test is generated by
Spring Cloud Contract Verifier.</li></ul></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_why_a_contract_verifier" href="#_why_a_contract_verifier"></a>2.1&nbsp;Why a Contract Verifier?</h2></div></div></div><p>Assume that we have a system consisting of multiple microservices:</p><div class="informalfigure"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/1.2.x/docs/src/main/asciidoc/images/Deps.png" alt="Microservices Architecture"></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_testing_issues" href="#_testing_issues"></a>2.1.1&nbsp;Testing issues</h3></div></div></div><p>If we wanted to test the application in top left corner to determine whether it can
communicate with other services, we could do one of two things:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Deploy all microservices and perform end-to-end tests.</li><li class="listitem">Mock other microservices in unit/integration tests.</li></ul></div><p>Both have their advantages but also a lot of disadvantages.</p><p><span class="strong"><strong>Deploy all microservices and perform end to end tests</strong></span></p><p>Advantages:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Simulates production.</li><li class="listitem">Tests real communication between services.</li></ul></div><p>Disadvantages:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">To test one microservice, we have to deploy 6 microservices, a couple of databases,
etc.</li><li class="listitem">The environment where the tests run is locked for a single suite of tests (nobody else
would be able to run the tests in the meantime).</li><li class="listitem">They take a long time to run.</li><li class="listitem">The feedback comes very late in the process.</li><li class="listitem">They are extremely hard to debug.</li></ul></div><p><span class="strong"><strong>Mock other microservices in unit/integration tests</strong></span></p><p>Advantages:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">They provide very fast feedback.</li><li class="listitem">They have no infrastructure requirements.</li></ul></div><p>Disadvantages:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">The implementor of the service creates stubs that might have nothing to do with
reality.</li><li class="listitem">You can go to production with passing tests and failing production.</li></ul></div><p>To solve the aforementioned issues, Spring Cloud Contract Verifier with Stub Runner was
created. The main idea is to give you very fast feedback, without the need to set up the
whole world of microservices. If you work on stubs, then the only applications you need
are those that your application directly uses.</p><div class="informalfigure"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/1.2.x/docs/src/main/asciidoc/images/Stubs2.png" alt="Stubbed Services"></div></div><p>Spring Cloud Contract Verifier gives you the certainty that the stubs that you use were
created by the service that you&#8217;re calling. Also, if you can use them, it means that they
were tested against the producer&#8217;s side. In short, you can trust those stubs.</p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_purposes" href="#_purposes"></a>2.2&nbsp;Purposes</h2></div></div></div><p>The main purposes of Spring Cloud Contract Verifier with Stub Runner are:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">To ensure that WireMock/Messaging stubs (used when developing the client) do exactly
what the actual server-side implementation does.</li><li class="listitem">To promote ATDD method and Microservices architectural style.</li><li class="listitem">To provide a way to publish changes in contracts that are immediately visible on both
sides.</li><li class="listitem">To generate boilerplate test code to be used on the server side.</li></ul></div><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>Spring Cloud Contract Verifier&#8217;s purpose is NOT to start writing business
features in the contracts. Assume that we have a business use case of fraud check. If a
user can be a fraud for 100 different reasons, we would assume that you would create 2
contracts, one for the positive case and one for the negative case. Contract tests are
used to test contracts between applications and not to simulate full behavior.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_how_it_works" href="#_how_it_works"></a>2.3&nbsp;How It Works</h2></div></div></div><p>This section explores how Spring Cloud Contract Verifier with Stub Runner works.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_defining_the_contract" href="#_defining_the_contract"></a>2.3.1&nbsp;Defining the contract</h3></div></div></div><p>As consumers of services, we need to define what exactly we want to achieve. We need to
formulate our expectations. That is why we write contracts.</p><p>Assume that you want to send a request containing the ID of a client company and the
amount it wants to borrow from us. You also want to send it to the /fraudcheck url via
the PUT method.</p><p><b>Groovy DSL.&nbsp;</b>
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">package</span> contracts
org.springframework.cloud.contract.spec.Contract.make {
request { <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// (1)</span>
method <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'PUT'</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// (2)</span>
url <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'/fraudcheck'</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// (3)</span>
body([ <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// (4)</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"client.id"</span>: $(regex(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'[0-9]{10}'</span>)),
loanAmount: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">99999</xslthl:number>
])
headers { <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// (5)</span>
contentType(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'application/json'</span>)
}
}
response { <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// (6)</span>
status <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// (7)</span>
body([ <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// (8)</span>
fraudCheckStatus: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"FRAUD"</span>,
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"rejection.reason"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Amount too high"</span>
])
headers { <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// (9)</span>
contentType(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'application/json'</span>)
}
}
}
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">/*
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.*`
*/</span></pre><p>
</p><p><b>YAML.&nbsp;</b>
</p><pre class="programlisting">request: # (1)
method: PUT # (2)
url: /fraudcheck # (3)
body: # (4)
"client.id": 1234567890
loanAmount: 99999
headers: # (5)
Content-Type: application/json
matchers:
body:
- path: $.['client.id'] # (6)
type: by_regex
value: "[0-9]{10}"
response: # (7)
status: 200 # (8)
body: # (9)
fraudCheckStatus: "FRAUD"
"rejection.reason": "Amount too high"
headers: # (10)
Content-Type: application/json;charset=UTF-8
#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`
# * has a field `loanAmount` that is equal to `99999`
#(5) - with header `Content-Type` equal to `application/json`
#(6) - and a `client.id` json entry matches the regular expression `[0-9]{10}`
#(7) - then the response will be sent with
#(8) - status equal `200`
#(9) - and JSON body equal to
# { "fraudCheckStatus": "FRAUD", "rejectionReason": "Amount too high" }
#(10) - with header `Content-Type` equal to `application/json`
#
#From the Producer perspective, in the autogenerated producer-side test:
#
#(1) - A request will be sent to the producer
#(2) - With the "PUT" method
#(3) - to the URL "/fraudcheck"
#(4) - with the JSON body that
# * has a field `client.id` `1234567890`
# * has a field `loanAmount` that is equal to `99999`
#(5) - with header `Content-Type` equal to `application/json`
#(7) - then the test will assert if the response has been sent with
#(8) - status equal `200`
#(9) - and JSON body equal to
# { "fraudCheckStatus": "FRAUD", "rejectionReason": "Amount too high" }
#(10) - with header `Content-Type` equal to `application/json;charset=UTF-8`</pre><p>
</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_client_side" href="#_client_side"></a>2.3.2&nbsp;Client Side</h3></div></div></div><p>Spring Cloud Contract generates stubs, which you can use during client-side testing.
You get a running WireMock instance/Messaging route that simulates the service.
You would like to feed that instance with a proper stub definition.</p><p>At some point in time, you need to send a request to the Fraud Detection service.</p><pre class="programlisting">ResponseEntity&lt;FraudServiceResponse&gt; response =
restTemplate.exchange(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"http://localhost:"</span> + port + <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/fraudcheck"</span>, HttpMethod.PUT,
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> HttpEntity&lt;&gt;(request, httpHeaders),
FraudServiceResponse.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>);</pre><p>Annotate your test class with <code class="literal">@AutoConfigureStubRunner</code>. In the annotation provide the group id and artifact id for the Stub Runner to download stubs of your collaborators.</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RunWith(SpringRunner.class)</xslthl:annotation>
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootTest(webEnvironment=WebEnvironment.NONE)</xslthl:annotation>
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@AutoConfigureStubRunner(ids = {"com.example:http-server-dsl:+:stubs:6565"}, workOffline = true)</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> LoanApplicationServiceTests {</pre><p>After that, during the tests, Spring Cloud Contract automatically finds the stubs
(simulating the real service) in the Maven repository and exposes them on a configured
(or random) port.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_server_side" href="#_server_side"></a>2.3.3&nbsp;Server Side</h3></div></div></div><p>Since you are developing your stub, you need to be sure that it actually resembles your
concrete implementation. You cannot have a situation where your stub acts in one way and
your application behaves in a different way, especially in production.</p><p>To ensure that your application behaves the way you define in your stub, tests are
generated from the stub you provide.</p><p>The autogenerated test looks, more or less, like this:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Test</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> validate_shouldMarkClientAsFraud() <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> Exception {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// given:</span>
MockMvcRequestSpecification request = given()
.header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Content-Type"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"application/vnd.fraud.v1+json"</span>)
.body(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"{\"client.id\":\"1234567890\",\"loanAmount\":99999}"</span>);
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// when:</span>
ResponseOptions response = given().spec(request)
.put(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/fraudcheck"</span>);
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// then:</span>
assertThat(response.statusCode()).isEqualTo(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>);
assertThat(response.header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Content-Type"</span>)).matches(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"application/vnd.fraud.v1.json.*"</span>);
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// and:</span>
DocumentContext parsedJson = JsonPath.parse(response.getBody().asString());
assertThatJson(parsedJson).field(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"['fraudCheckStatus']"</span>).matches(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"[A-Z]{5}"</span>);
assertThatJson(parsedJson).field(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"['rejection.reason']"</span>).isEqualTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Amount too high"</span>);
}</pre></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_step_by_step_guide_to_consumer_driven_contracts_cdc" href="#_step_by_step_guide_to_consumer_driven_contracts_cdc"></a>2.4&nbsp;Step-by-step Guide to Consumer Driven Contracts (CDC)</h2></div></div></div><p>Consider an example of Fraud Detection and the Loan Issuance process. The business
scenario is such that we want to issue loans to people but do not want them to steal from
us. The current implementation of our system grants loans to everybody.</p><p>Assume that <code class="literal">Loan Issuance</code> is a client to the <code class="literal">Fraud Detection</code> server. In the current
sprint, we must develop a new feature: if a client wants to borrow too much money, then
we mark the client as a fraud.</p><p>Technical remark - Fraud Detection has an <code class="literal">artifact-id</code> of <code class="literal">http-server</code>, while Loan
Issuance has an artifact-id of <code class="literal">http-client</code>, and both have a <code class="literal">group-id</code> of <code class="literal">com.example</code>.</p><p>Social remark - both client and server development teams need to communicate directly and
discuss changes while going through the process. CDC is all about communication.</p><p>The <a class="link" href="https://github.com/spring-cloud/spring-cloud-contract/tree/1.2.x/samples/standalone/dsl/http-server" target="_top">server
side code is available here</a> and <a class="link" href="https://github.com/spring-cloud/spring-cloud-contract/tree/1.2.x/samples/standalone/dsl/http-client" target="_top">the
client code here</a>.</p><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Tip</th></tr><tr><td align="left" valign="top"><p>In this case, the producer owns the contracts. Physically, all the contract are
in the producer&#8217;s repository.</p></td></tr></table></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_technical_note" href="#_technical_note"></a>2.4.1&nbsp;Technical note</h3></div></div></div><p>If using the <span class="strong"><strong>SNAPSHOT</strong></span> / <span class="strong"><strong>Milestone</strong></span> / <span class="strong"><strong>Release Candidate</strong></span> versions please add the
following section to your build:</p><p class="primary"><b>Maven.&nbsp;</b>
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;repositories&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;repository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;id&gt;</span>spring-snapshots<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/id&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;name&gt;</span>Spring Snapshots<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/name&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;url&gt;</span>https://repo.spring.io/snapshot<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/url&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;enabled&gt;</span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/enabled&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/repository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;repository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;id&gt;</span>spring-milestones<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/id&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;name&gt;</span>Spring Milestones<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/name&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;url&gt;</span>https://repo.spring.io/milestone<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/url&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;enabled&gt;</span>false<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/enabled&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/repository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;repository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;id&gt;</span>spring-releases<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/id&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;name&gt;</span>Spring Releases<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/name&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;url&gt;</span>https://repo.spring.io/release<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/url&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;enabled&gt;</span>false<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/enabled&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/repository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/repositories&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;pluginRepositories&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;pluginRepository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;id&gt;</span>spring-snapshots<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/id&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;name&gt;</span>Spring Snapshots<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/name&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;url&gt;</span>https://repo.spring.io/snapshot<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/url&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;enabled&gt;</span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/enabled&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/pluginRepository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;pluginRepository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;id&gt;</span>spring-milestones<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/id&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;name&gt;</span>Spring Milestones<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/name&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;url&gt;</span>https://repo.spring.io/milestone<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/url&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;enabled&gt;</span>false<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/enabled&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/pluginRepository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;pluginRepository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;id&gt;</span>spring-releases<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/id&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;name&gt;</span>Spring Releases<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/name&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;url&gt;</span>https://repo.spring.io/release<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/url&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;enabled&gt;</span>false<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/enabled&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/pluginRepository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/pluginRepositories&gt;</span></pre><p class="primary">
</p><p class="secondary"><b>Gradle.&nbsp;</b>
</p><pre class="programlisting">repositories {
mavenCentral()
mavenLocal()
maven { url <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"https://repo.spring.io/snapshot"</span> }
maven { url <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"https://repo.spring.io/milestone"</span> }
maven { url <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"https://repo.spring.io/release"</span> }
}</pre><p class="secondary">
</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_consumer_side_loan_issuance" href="#_consumer_side_loan_issuance"></a>2.4.2&nbsp;Consumer side (Loan Issuance)</h3></div></div></div><p>As a developer of the Loan Issuance service (a consumer of the Fraud Detection server), you might do the following steps:</p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem">Start doing TDD by writing a test for your feature.</li><li class="listitem">Write the missing implementation.</li><li class="listitem">Clone the Fraud Detection service repository locally.</li><li class="listitem">Define the contract locally in the repo of Fraud Detection service.</li><li class="listitem">Add the Spring Cloud Contract Verifier plugin.</li><li class="listitem">Run the integration tests.</li><li class="listitem">File a pull request.</li><li class="listitem">Create an initial implementation.</li><li class="listitem">Take over the pull request.</li><li class="listitem">Write the missing implementation.</li><li class="listitem">Deploy your app.</li><li class="listitem">Work online.</li></ol></div><p><span class="strong"><strong>Start doing TDD by writing a test for your feature.</strong></span></p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Test</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> shouldBeRejectedDueToAbnormalLoanAmount() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// given:</span>
LoanApplication application = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> LoanApplication(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> Client(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"1234567890"</span>),
<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">99999</xslthl:number>);
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// when:</span>
LoanApplicationResult loanApplication = service.loanApplication(application);
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// then:</span>
assertThat(loanApplication.getLoanApplicationStatus())
.isEqualTo(LoanApplicationStatus.LOAN_APPLICATION_REJECTED);
assertThat(loanApplication.getRejectionReason()).isEqualTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Amount too high"</span>);
}</pre><p>Assume that you have written a test of your new feature. If a loan application for a big
amount is received, the system should reject that loan application with some description.</p><p><span class="strong"><strong>Write the missing implementation.</strong></span></p><p>At some point in time, you need to send a request to the Fraud Detection service. Assume
that you need to send the request containing the ID of the client and the amount the
client wants to borrow. You want to send it to the <code class="literal">/fraudcheck</code> url via the <code class="literal">PUT</code> method.</p><pre class="programlisting">ResponseEntity&lt;FraudServiceResponse&gt; response =
restTemplate.exchange(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"http://localhost:"</span> + port + <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/fraudcheck"</span>, HttpMethod.PUT,
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> HttpEntity&lt;&gt;(request, httpHeaders),
FraudServiceResponse.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>);</pre><p>For simplicity, the port of the Fraud Detection service is set to <code class="literal">8080</code>, and the
application runs on <code class="literal">8090</code>.</p><p>If you start the test at this point, it breaks, because no service currently runs on port
<code class="literal">8080</code>.</p><p><span class="strong"><strong>Clone the Fraud Detection service repository locally.</strong></span></p><p>You can start by playing around with the server side contract. To do so, you must first
clone it.</p><pre class="programlisting">$ git clone https://your-git-server.com/server-side.git local-http-server-repo</pre><p><span class="strong"><strong>Define the contract locally in the repo of Fraud Detection service.</strong></span></p><p>As a consumer, you need to define what exactly you want to achieve. You need to formulate
your expectations. To do so, write the following contract:</p><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>Place the contract under <code class="literal">src/test/resources/contracts/fraud</code> folder. The <code class="literal">fraud</code> folder
is important because the producer&#8217;s test base class name references that folder.</p></td></tr></table></div><p><b>Groovy DSL.&nbsp;</b>
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">package</span> contracts
org.springframework.cloud.contract.spec.Contract.make {
request { <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// (1)</span>
method <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'PUT'</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// (2)</span>
url <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'/fraudcheck'</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// (3)</span>
body([ <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// (4)</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"client.id"</span>: $(regex(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'[0-9]{10}'</span>)),
loanAmount: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">99999</xslthl:number>
])
headers { <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// (5)</span>
contentType(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'application/json'</span>)
}
}
response { <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// (6)</span>
status <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// (7)</span>
body([ <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// (8)</span>
fraudCheckStatus: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"FRAUD"</span>,
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"rejection.reason"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Amount too high"</span>
])
headers { <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// (9)</span>
contentType(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'application/json'</span>)
}
}
}
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">/*
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.*`
*/</span></pre><p>
</p><p><b>YAML.&nbsp;</b>
</p><pre class="programlisting">request: # (1)
method: PUT # (2)
url: /fraudcheck # (3)
body: # (4)
"client.id": 1234567890
loanAmount: 99999
headers: # (5)
Content-Type: application/json
matchers:
body:
- path: $.['client.id'] # (6)
type: by_regex
value: "[0-9]{10}"
response: # (7)
status: 200 # (8)
body: # (9)
fraudCheckStatus: "FRAUD"
"rejection.reason": "Amount too high"
headers: # (10)
Content-Type: application/json;charset=UTF-8
#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`
# * has a field `loanAmount` that is equal to `99999`
#(5) - with header `Content-Type` equal to `application/json`
#(6) - and a `client.id` json entry matches the regular expression `[0-9]{10}`
#(7) - then the response will be sent with
#(8) - status equal `200`
#(9) - and JSON body equal to
# { "fraudCheckStatus": "FRAUD", "rejectionReason": "Amount too high" }
#(10) - with header `Content-Type` equal to `application/json`
#
#From the Producer perspective, in the autogenerated producer-side test:
#
#(1) - A request will be sent to the producer
#(2) - With the "PUT" method
#(3) - to the URL "/fraudcheck"
#(4) - with the JSON body that
# * has a field `client.id` `1234567890`
# * has a field `loanAmount` that is equal to `99999`
#(5) - with header `Content-Type` equal to `application/json`
#(7) - then the test will assert if the response has been sent with
#(8) - status equal `200`
#(9) - and JSON body equal to
# { "fraudCheckStatus": "FRAUD", "rejectionReason": "Amount too high" }
#(10) - with header `Content-Type` equal to `application/json;charset=UTF-8`</pre><p>
</p><p>The YML contract is quite straight-forward. However when you take a look at the Contract
written using a statically typed Groovy DSL - you might wonder what the
<code class="literal">value(client(&#8230;&#8203;), server(&#8230;&#8203;))</code> parts are. By using this notation, Spring Cloud
Contract lets you define parts of a JSON block, a URL, etc., which are dynamic. In case
of an identifier or a timestamp, you need not hardcode a value. You want to allow some
different ranges of values. To enable ranges of values, you can set regular expressions
matching those values for the consumer side. You can provide the body by means of either
a map notation or String with interpolations.
<a class="link" href="https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html#_contract_dsl" target="_top">Consult the docs
for more information.</a> We highly recommend using the map notation!</p><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Tip</th></tr><tr><td align="left" valign="top"><p>You must understand the map notation in order to set up contracts. Please read the
<a class="link" href="https://groovy-lang.org/json.html" target="_top">Groovy docs regarding JSON</a>.</p></td></tr></table></div><p>The previously shown contract is an agreement between two sides that:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p class="simpara">if an HTTP request is sent with all of</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem">a <code class="literal">PUT</code> method on the <code class="literal">/fraudcheck</code> endpoint,</li><li class="listitem">a JSON body with a <code class="literal">client.id</code> that matches the regular expression <code class="literal">[0-9]{10}</code> and
<code class="literal">loanAmount</code> equal to <code class="literal">99999</code>,</li><li class="listitem">and a <code class="literal">Content-Type</code> header with a value of <code class="literal">application/vnd.fraud.v1+json</code>,</li></ul></div></li><li class="listitem"><p class="simpara">then an HTTP response is sent to the consumer that</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem">has status <code class="literal">200</code>,</li><li class="listitem">contains a JSON body with the <code class="literal">fraudCheckStatus</code> field containing a value <code class="literal">FRAUD</code> and
the <code class="literal">rejectionReason</code> field having value <code class="literal">Amount too high</code>,</li><li class="listitem">and a <code class="literal">Content-Type</code> header with a value of <code class="literal">application/vnd.fraud.v1+json</code>.</li></ul></div></li></ul></div><p>Once you are ready to check the API in practice in the integration tests, you need to
install the stubs locally.</p><p><span class="strong"><strong>Add the Spring Cloud Contract Verifier plugin.</strong></span></p><p>We can add either a Maven or a Gradle plugin. In this example, you see how to add Maven.
First, add the <code class="literal">Spring Cloud Contract</code> BOM.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;dependencyManagement&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;dependencies&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;dependency&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>spring-cloud-dependencies<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;version&gt;</span>${spring-cloud-dependencies.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/version&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;type&gt;</span>pom<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/type&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;scope&gt;</span>import<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/scope&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/dependency&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/dependencies&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/dependencyManagement&gt;</span></pre><p>Next, add the <code class="literal">Spring Cloud Contract Verifier</code> Maven plugin</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;plugin&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>spring-cloud-contract-maven-plugin<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;version&gt;</span>${spring-cloud-contract.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/version&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;extensions&gt;</span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/extensions&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;configuration&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;packageWithBaseClasses&gt;</span>com.example.fraud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/packageWithBaseClasses&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/configuration&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/plugin&gt;</span></pre><p>Since the plugin was added, you get the <code class="literal">Spring Cloud Contract Verifier</code> features which,
from the provided contracts:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">generate and run tests</li><li class="listitem">produce and install stubs</li></ul></div><p>You do not want to generate tests since you, as the consumer, want only to play with the
stubs. You need to skip the test generation and execution. When you execute:</p><pre class="programlisting">$ <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">cd</span> local-http-server-repo
$ ./mvnw clean install -DskipTests</pre><p>In the logs, you see something like this:</p><pre class="programlisting">[INFO] --- spring-cloud-contract-maven-plugin:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.</xslthl:number>BUILD-SNAPSHOT:generateStubs (default-generateStubs) @ http-server ---
[INFO] Building jar: /some/path/http-server/target/http-server-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT-stubs.jar
[INFO]
[INFO] --- maven-jar-plugin:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2.6</xslthl:number>:jar (default-jar) @ http-server ---
[INFO] Building jar: /some/path/http-server/target/http-server-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT.jar
[INFO]
[INFO] --- spring-boot-maven-plugin:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1.5</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">5.</xslthl:number>BUILD-SNAPSHOT:repackage (default) @ http-server ---
[INFO]
[INFO] --- maven-install-plugin:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2.5</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2</xslthl:number>:install (default-install) @ http-server ---
[INFO] Installing /some/path/http-server/target/http-server-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT.jar to /path/to/your/.m2/repository/com/example/http-server/<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT/http-server-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT.jar
[INFO] Installing /some/path/http-server/pom.xml to /path/to/your/.m2/repository/com/example/http-server/<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT/http-server-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT.pom
[INFO] Installing /some/path/http-server/target/http-server-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT-stubs.jar to /path/to/your/.m2/repository/com/example/http-server/<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT/http-server-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT-stubs.jar</pre><p>The following line is extremely important:</p><pre class="programlisting">[INFO] Installing /some/path/http-server/target/http-server-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT-stubs.jar to /path/to/your/.m2/repository/com/example/http-server/<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT/http-server-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT-stubs.jar</pre><p>It confirms that the stubs of the <code class="literal">http-server</code> have been installed in the local
repository.</p><p><span class="strong"><strong>Run the integration tests.</strong></span></p><p>In order to profit from the Spring Cloud Contract Stub Runner functionality of automatic
stub downloading, you must do the following in your consumer side project (<code class="literal">Loan
Application service</code>):</p><p>Add the <code class="literal">Spring Cloud Contract</code> BOM:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;dependencyManagement&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;dependencies&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;dependency&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>spring-cloud-dependencies<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;version&gt;</span>${spring-cloud-dependencies.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/version&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;type&gt;</span>pom<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/type&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;scope&gt;</span>import<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/scope&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/dependency&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/dependencies&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/dependencyManagement&gt;</span></pre><p>Add the dependency to <code class="literal">Spring Cloud Contract Stub Runner</code>:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;dependency&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>spring-cloud-starter-contract-stub-runner<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;scope&gt;</span>test<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/scope&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/dependency&gt;</span></pre><p>Annotate your test class with <code class="literal">@AutoConfigureStubRunner</code>. In the annotation, provide the
<code class="literal">group-id</code> and <code class="literal">artifact-id</code> for the Stub Runner to download the stubs of your
collaborators. (Optional step) Because you&#8217;re playing with the collaborators offline, you
can also provide the offline work switch.</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RunWith(SpringRunner.class)</xslthl:annotation>
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootTest(webEnvironment=WebEnvironment.NONE)</xslthl:annotation>
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@AutoConfigureStubRunner(ids = {"com.example:http-server-dsl:+:stubs:6565"}, workOffline = true)</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> LoanApplicationServiceTests {</pre><p>Now, when you run your tests, you see something like this:</p><pre class="programlisting"><xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2016</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">07</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">19</xslthl:number> <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">14</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">22</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">25.403</xslthl:number> INFO <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">41050</xslthl:number> --- [ main] o.s.c.c.stubrunner.AetherStubDownloader : Desired version is + - will try to resolve the latest version
<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2016</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">07</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">19</xslthl:number> <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">14</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">22</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">25.438</xslthl:number> INFO <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">41050</xslthl:number> --- [ main] o.s.c.c.stubrunner.AetherStubDownloader : Resolved version is <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT
<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2016</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">07</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">19</xslthl:number> <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">14</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">22</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">25.439</xslthl:number> INFO <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">41050</xslthl:number> --- [ main] o.s.c.c.stubrunner.AetherStubDownloader : Resolving artifact com.example:http-server:jar:stubs:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT using remote repositories []
<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2016</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">07</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">19</xslthl:number> <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">14</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">22</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">25.451</xslthl:number> INFO <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">41050</xslthl:number> --- [ main] o.s.c.c.stubrunner.AetherStubDownloader : Resolved artifact com.example:http-server:jar:stubs:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT to /path/to/your/.m2/repository/com/example/http-server/<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT/http-server-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT-stubs.jar
<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2016</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">07</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">19</xslthl:number> <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">14</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">22</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">25.465</xslthl:number> INFO <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">41050</xslthl:number> --- [ main] o.s.c.c.stubrunner.AetherStubDownloader : Unpacking stub from JAR [URI: file:/path/to/your/.m2/repository/com/example/http-server/<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT/http-server-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT-stubs.jar]
<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2016</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">07</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">19</xslthl:number> <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">14</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">22</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">25.475</xslthl:number> INFO <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">41050</xslthl:number> --- [ main] o.s.c.c.stubrunner.AetherStubDownloader : Unpacked file to [/var/folders/<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>p/xwq47sq106x1_g3dtv6qfm940000gq/T/contracts100276532569594265]
<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2016</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">07</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">19</xslthl:number> <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">14</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">22</xslthl:number>:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">27.737</xslthl:number> INFO <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">41050</xslthl:number> --- [ main] o.s.c.c.stubrunner.StubRunnerExecutor : All stubs are now running RunningStubs [namesAndPorts={com.example:http-server:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT:stubs=<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">8080</xslthl:number>}]</pre><p>This output means that Stub Runner has found your stubs and started a server for your app
with group id <code class="literal">com.example</code>, artifact id <code class="literal">http-server</code> with version <code class="literal">0.0.1-SNAPSHOT</code> of
the stubs and with <code class="literal">stubs</code> classifier on port <code class="literal">8080</code>.</p><p><span class="strong"><strong>File a pull request.</strong></span></p><p>What you have done until now is an iterative process. You can play around with the
contract, install it locally, and work on the consumer side until the contract works as
you wish.</p><p>Once you are satisfied with the results and the test passes, publish a pull request to
the server side. Currently, the consumer side work is done.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_producer_side_fraud_detection_server" href="#_producer_side_fraud_detection_server"></a>2.4.3&nbsp;Producer side (Fraud Detection server)</h3></div></div></div><p>As a developer of the Fraud Detection server (a server to the Loan Issuance service):</p><p><span class="strong"><strong>Create an initial implementation.</strong></span></p><p>As a reminder, you can see the initial implementation here:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RequestMapping(value = "/fraudcheck", method = PUT)</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> FraudCheckResult fraudCheck(<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RequestBody</xslthl:annotation> FraudCheck fraudCheck) {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> FraudCheckResult(FraudCheckStatus.OK, NO_REASON);
}</pre><p><span class="strong"><strong>Take over the pull request.</strong></span></p><pre class="programlisting">$ git checkout -b contract-change-pr master
$ git pull https://your-git-server.com/server-side-fork.git contract-change-pr</pre><p>You must add the dependencies needed by the autogenerated tests:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;dependency&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>spring-cloud-starter-contract-verifier<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;scope&gt;</span>test<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/scope&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/dependency&gt;</span></pre><p>In the configuration of the Maven plugin, pass the <code class="literal">packageWithBaseClasses</code> property</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;plugin&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>spring-cloud-contract-maven-plugin<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;version&gt;</span>${spring-cloud-contract.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/version&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;extensions&gt;</span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/extensions&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;configuration&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;packageWithBaseClasses&gt;</span>com.example.fraud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/packageWithBaseClasses&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/configuration&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/plugin&gt;</span></pre><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>This example uses "convention based" naming by setting the
<code class="literal">packageWithBaseClasses</code> property. Doing so means that the two last packages combine to
make the name of the base test class. In our case, the contracts were placed under
<code class="literal">src/test/resources/contracts/fraud</code>. Since you do not have two packages starting from
the <code class="literal">contracts</code> folder, pick only one, which should be <code class="literal">fraud</code>. Add the <code class="literal">Base</code> suffix and
capitalize <code class="literal">fraud</code>. That gives you the <code class="literal">FraudBase</code> test class name.</p></td></tr></table></div><p>All the generated tests extend that class. Over there, you can set up your Spring Context
or whatever is necessary. In this case, use <a class="link" href="https://github.com/rest-assured/rest-assured" target="_top">Rest Assured MVC</a> to
start the server side <code class="literal">FraudDetectionController</code>.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">package</span> com.example.fraud;
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.junit.Before;
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> io.restassured.module.mockmvc.RestAssuredMockMvc;
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> FraudBase {
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Before</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> setup() {
RestAssuredMockMvc.standaloneSetup(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> FraudDetectionController(),
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> FraudStatsController(stubbedStatsProvider()));
}
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> StatsProvider stubbedStatsProvider() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> fraudType -&gt; {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">switch</span> (fraudType) {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">case</span> DRUNKS:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">100</xslthl:number>;
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">case</span> ALL:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>;
}
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>;
};
}
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> assertThatRejectionReasonIsNull(Object rejectionReason) {
assert rejectionReason == null;
}
}</pre><p>Now, if you run the <code class="literal">./mvnw clean install</code>, you get something like this:</p><pre class="programlisting">Results :
Tests in error:
ContractVerifierTest.validate_shouldMarkClientAsFraud:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">32</xslthl:number> &raquo; IllegalState Parsed...</pre><p>This error occurs because you have a new contract from which a test was generated and it
failed since you have not implemented the feature. The auto-generated test would look
like this:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Test</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> validate_shouldMarkClientAsFraud() <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> Exception {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// given:</span>
MockMvcRequestSpecification request = given()
.header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Content-Type"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"application/vnd.fraud.v1+json"</span>)
.body(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"{\"client.id\":\"1234567890\",\"loanAmount\":99999}"</span>);
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// when:</span>
ResponseOptions response = given().spec(request)
.put(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/fraudcheck"</span>);
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// then:</span>
assertThat(response.statusCode()).isEqualTo(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>);
assertThat(response.header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Content-Type"</span>)).matches(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"application/vnd.fraud.v1.json.*"</span>);
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// and:</span>
DocumentContext parsedJson = JsonPath.parse(response.getBody().asString());
assertThatJson(parsedJson).field(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"['fraudCheckStatus']"</span>).matches(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"[A-Z]{5}"</span>);
assertThatJson(parsedJson).field(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"['rejection.reason']"</span>).isEqualTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Amount too high"</span>);
}</pre><p>If you used the Groovy DSL, you can see, all the <code class="literal">producer()</code> parts of the Contract that were present in the
<code class="literal">value(consumer(&#8230;&#8203;), producer(&#8230;&#8203;))</code> blocks got injected into the test.
In case of using YAML, the same applied for the <code class="literal">matchers</code> sections of the <code class="literal">response</code>.</p><p>Note that, on the producer side, you are also doing TDD. The expectations are expressed
in the form of a test. This test sends a request to our own application with the URL,
headers, and body defined in the contract. It also is expecting precisely defined values
in the response. In other words, you have the <code class="literal">red</code> part of <code class="literal">red</code>, <code class="literal">green</code>, and
<code class="literal">refactor</code>. It is time to convert the <code class="literal">red</code> into the <code class="literal">green</code>.</p><p><span class="strong"><strong>Write the missing implementation.</strong></span></p><p>Because you know the expected input and expected output, you can write the missing
implementation:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RequestMapping(value = "/fraudcheck", method = PUT)</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> FraudCheckResult fraudCheck(<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RequestBody</xslthl:annotation> FraudCheck fraudCheck) {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">if</span> (amountGreaterThanThreshold(fraudCheck)) {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> FraudCheckResult(FraudCheckStatus.FRAUD, AMOUNT_TOO_HIGH);
}
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> FraudCheckResult(FraudCheckStatus.OK, NO_REASON);
}</pre><p>When you execute <code class="literal">./mvnw clean install</code> again, the tests pass. Since the <code class="literal">Spring Cloud
Contract Verifier</code> plugin adds the tests to the <code class="literal">generated-test-sources</code>, you can
actually run those tests from your IDE.</p><p><span class="strong"><strong>Deploy your app.</strong></span></p><p>Once you finish your work, you can deploy your change. First, merge the branch:</p><pre class="programlisting">$ git checkout master
$ git merge --no-ff contract-change-pr
$ git push origin master</pre><p>Your CI might run something like <code class="literal">./mvnw clean deploy</code>, which would publish both the
application and the stub artifacts.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_consumer_side_loan_issuance_final_step" href="#_consumer_side_loan_issuance_final_step"></a>2.4.4&nbsp;Consumer Side (Loan Issuance) Final Step</h3></div></div></div><p>As a developer of the Loan Issuance service (a consumer of the Fraud Detection server):</p><p><span class="strong"><strong>Merge branch to master.</strong></span></p><pre class="programlisting">$ git checkout master
$ git merge --no-ff contract-change-pr</pre><p><span class="strong"><strong>Work online.</strong></span></p><p>Now you can disable the offline work for Spring Cloud Contract Stub Runner and indicate
where the repository with your stubs is located. At this moment the stubs of the server
side are automatically downloaded from Nexus/Artifactory. You can switch off the value of
the <code class="literal">workOffline</code> parameter in your annotation. The following code shows an example of
achieving the same thing by changing the properties.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">stubrunner</span>:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> ids</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'com.example:http-server-dsl:+:stubs:8080'</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> repositoryRoot</span>: https://repo.spring.io/libs-snapshot</pre><p>That&#8217;s it!</p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_dependencies" href="#_dependencies"></a>2.5&nbsp;Dependencies</h2></div></div></div><p>The best way to add dependencies is to use the proper <code class="literal">starter</code> dependency.</p><p>For <code class="literal">stub-runner</code>, use <code class="literal">spring-cloud-starter-stub-runner</code>. When you use a plugin, add
<code class="literal">spring-cloud-starter-contract-verifier</code>.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_additional_links" href="#_additional_links"></a>2.6&nbsp;Additional Links</h2></div></div></div><p>Here are some resources related to Spring Cloud Contract Verifier and Stub Runner. Note
that some may be outdated, because the Spring Cloud Contract Verifier project is under
constant development.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_spring_cloud_contract_video" href="#_spring_cloud_contract_video"></a>2.6.1&nbsp;Spring Cloud Contract video</h3></div></div></div><p>You can check out the video from the Warsaw JUG about Spring Cloud Contract:</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_readings" href="#_readings"></a>2.6.2&nbsp;Readings</h3></div></div></div><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a class="link" href="https://www.slideshare.net/MarcinGrzejszczak/stick-to-the-rules-consumer-driven-contracts-201507-confitura" target="_top">Slides from Marcin Grzejszczak&#8217;s talk about Accurest</a></li><li class="listitem"><a class="link" href="https://toomuchcoding.com/blog/categories/accurest/" target="_top">Accurest related articles from Marcin Grzejszczak&#8217;s blog</a></li><li class="listitem"><a class="link" href="https://toomuchcoding.com/blog/categories/spring-cloud-contract/" target="_top">Spring Cloud Contract related articles from Marcin Grzejszczak&#8217;s blog</a></li><li class="listitem"><a class="link" href="https://groovy-lang.org/json.html" target="_top">Groovy docs regarding JSON</a></li></ul></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_samples" href="#_samples"></a>2.7&nbsp;Samples</h2></div></div></div><p>You can find some samples at
<a class="link" href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples" target="_top">samples</a>.</p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__spring_cloud_contract.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi__spring_cloud_contract_faq.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">1.&nbsp;Spring Cloud Contract&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-contract.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;3.&nbsp;Spring Cloud Contract FAQ</td></tr></table></div></body></html>

View File

@@ -0,0 +1,262 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>5.&nbsp;Spring Cloud Contract Verifier Messaging</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud-contract.html" title="Spring Cloud Contract"><link rel="up" href="multi_spring-cloud-contract.html" title="Spring Cloud Contract"><link rel="prev" href="multi__spring_cloud_contract_verifier_setup.html" title="4.&nbsp;Spring Cloud Contract Verifier Setup"><link rel="next" href="multi__spring_cloud_contract_stub_runner.html" title="6.&nbsp;Spring Cloud Contract Stub Runner"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">5.&nbsp;Spring Cloud Contract Verifier Messaging</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__spring_cloud_contract_verifier_setup.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi__spring_cloud_contract_stub_runner.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_spring_cloud_contract_verifier_messaging" href="#_spring_cloud_contract_verifier_messaging"></a>5.&nbsp;Spring Cloud Contract Verifier Messaging</h1></div></div></div><p>Spring Cloud Contract Verifier lets you verify applications that uses messaging as a
means of communication. All of the integrations shown in this document work with Spring,
but you can also create one of your own and use that.</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_integrations" href="#_integrations"></a>5.1&nbsp;Integrations</h2></div></div></div><p>You can use one of the following four integration configurations:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Apache Camel</li><li class="listitem">Spring Integration</li><li class="listitem">Spring Cloud Stream</li><li class="listitem">Spring AMQP</li></ul></div><p>Since we use Spring Boot, if you have added one of these libraries to the classpath, all
the messaging configuration is automatically set up.</p><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>Remember to put <code class="literal">@AutoConfigureMessageVerifier</code> on the base class of your
generated tests. Otherwise, messaging part of Spring Cloud Contract Verifier does not
work.</p></td></tr></table></div><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>If you want to use Spring Cloud Stream, remember to add a dependency on
<code class="literal">org.springframework.cloud:spring-cloud-stream-test-support</code>, as shown here:</p></td></tr></table></div><p class="primary"><b>Maven.&nbsp;</b>
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;dependency&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>spring-cloud-stream-test-support<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;scope&gt;</span>test<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/scope&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/dependency&gt;</span></pre><p class="primary">
</p><p class="secondary"><b>Gradle.&nbsp;</b>
</p><pre class="programlisting">testCompile <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud:spring-cloud-stream-test-support"</span></pre><p class="secondary">
</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_manual_integration_testing" href="#_manual_integration_testing"></a>5.2&nbsp;Manual Integration Testing</h2></div></div></div><p>The main interface used by the tests is
<code class="literal">org.springframework.cloud.contract.verifier.messaging.MessageVerifier</code>.
It defines how to send and receive messages. You can create your own implementation to
achieve the same goal.</p><p>In a test, you can inject a <code class="literal">ContractVerifierMessageExchange</code> to send and receive
messages that follow the contract. Then add <code class="literal">@AutoConfigureMessageVerifier</code> to your test.
Here&#8217;s an example:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RunWith(SpringTestRunner.class)</xslthl:annotation>
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootTest</xslthl:annotation>
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@AutoConfigureMessageVerifier</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> MessagingContractTests {
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Autowired</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> MessageVerifier verifier;
...
}</pre><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>If your tests require stubs as well, then <code class="literal">@AutoConfigureStubRunner</code> includes the
messaging configuration, so you only need the one annotation.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_publisher_side_test_generation" href="#_publisher_side_test_generation"></a>5.3&nbsp;Publisher-Side Test Generation</h2></div></div></div><p>Having the <code class="literal">input</code> or <code class="literal">outputMessage</code> sections in your DSL results in creation of tests
on the publisher&#8217;s side. By default, JUnit tests are created. However, there is also a
possibility to create Spock tests.</p><p>There are 3 main scenarios that we should take into consideration:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Scenario 1: There is no input message that produces an output message. The output
message is triggered by a component inside the application (for example, scheduler).</li><li class="listitem">Scenario 2: The input message triggers an output message.</li><li class="listitem">Scenario 3: The input message is consumed and there is no output message.</li></ul></div><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>The destination passed to <code class="literal">messageFrom</code> or <code class="literal">sentTo</code> can have different
meanings for different messaging implementations. For <span class="strong"><strong>Stream</strong></span> and <span class="strong"><strong>Integration</strong></span> it is
first resolved as a <code class="literal">destination</code> of a channel. Then, if there is no such <code class="literal">destination</code>
it is resolved as a channel name. For <span class="strong"><strong>Camel</strong></span>, that&#8217;s a certain component (for example,
<code class="literal">jms</code>).</p></td></tr></table></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_scenario_1_no_input_message" href="#_scenario_1_no_input_message"></a>5.3.1&nbsp;Scenario 1: No Input Message</h3></div></div></div><p>Here is an example for Camel. For the given contract:</p><p><b>Groovy DSL.&nbsp;</b>
</p><pre class="programlisting">def contractDsl = Contract.make {
label <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'some_label'</span>
input {
triggeredBy(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'bookReturnedTriggered()'</span>)
}
outputMessage {
sentTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'activemq:output'</span>)
body(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'{ "bookName" : "foo" }'</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span>)
headers {
header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'BOOK-NAME'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span>)
messagingContentType(applicationJson())
}
}
}</pre><p>
</p><p><b>YAML.&nbsp;</b>
</p><pre class="programlisting">label: some_label
input:
triggeredBy: bookReturnedTriggered
outputMessage:
sentTo: activemq:output
body:
bookName: foo
headers:
BOOK-NAME: foo
contentType: application/json</pre><p>
</p><p>The following JUnit test is created:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'
</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// when:</span>
bookReturnedTriggered();
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// then:</span>
ContractVerifierMessage response = contractVerifierMessaging.receive(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"activemq:output"</span>);
assertThat(response).isNotNull();
assertThat(response.getHeader(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"BOOK-NAME"</span>)).isNotNull();
assertThat(response.getHeader(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"BOOK-NAME"</span>).toString()).isEqualTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"foo"</span>);
assertThat(response.getHeader(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"contentType"</span>)).isNotNull();
assertThat(response.getHeader(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"contentType"</span>).toString()).isEqualTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"application/json"</span>);
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// and:</span>
DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload()));
assertThatJson(parsedJson).field(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"bookName"</span>).isEqualTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"foo"</span>);
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'</span></pre><p>And the following Spock test would be created:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'
</span> when:
bookReturnedTriggered()
then:
ContractVerifierMessage response = contractVerifierMessaging.receive(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'activemq:output'</span>)
assert response != null
response.getHeader(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'BOOK-NAME'</span>)?.toString() == <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span>
response.getHeader(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'contentType'</span>)?.toString() == <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'application/json'</span>
and:
DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.payload))
assertThatJson(parsedJson).field(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"bookName"</span>).isEqualTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"foo"</span>)
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'</span></pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_scenario_2_output_triggered_by_input" href="#_scenario_2_output_triggered_by_input"></a>5.3.2&nbsp;Scenario 2: Output Triggered by Input</h3></div></div></div><p>Here is an example for Camel. For the given contract:</p><p><b>Groovy DSL.&nbsp;</b>
</p><pre class="programlisting">def contractDsl = Contract.make {
label <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'some_label'</span>
input {
messageFrom(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'jms:input'</span>)
messageBody([
bookName: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span>
])
messageHeaders {
header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'sample'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'header'</span>)
}
}
outputMessage {
sentTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'jms:output'</span>)
body([
bookName: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span>
])
headers {
header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'BOOK-NAME'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span>)
}
}
}</pre><p>
</p><p><b>YAML.&nbsp;</b>
</p><pre class="programlisting">label: some_label
input:
messageFrom: jms:input
messageBody:
bookName: 'foo'
messageHeaders:
sample: header
outputMessage:
sentTo: jms:output
body:
bookName: foo
headers:
BOOK-NAME: foo</pre><p>
</p><p>The following JUnit test is created:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'
</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// given:</span>
ContractVerifierMessage inputMessage = contractVerifierMessaging.create(
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"{\\"</span>bookName\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":\\"</span>foo\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"}"</span>
, headers()
.header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"sample"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"header"</span>));
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// when:</span>
contractVerifierMessaging.send(inputMessage, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"jms:input"</span>);
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// then:</span>
ContractVerifierMessage response = contractVerifierMessaging.receive(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"jms:output"</span>);
assertThat(response).isNotNull();
assertThat(response.getHeader(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"BOOK-NAME"</span>)).isNotNull();
assertThat(response.getHeader(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"BOOK-NAME"</span>).toString()).isEqualTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"foo"</span>);
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// and:</span>
DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload()));
assertThatJson(parsedJson).field(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"bookName"</span>).isEqualTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"foo"</span>);
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'</span></pre><p>And the following Spock test would be created:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">""</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"\
</span>given:
ContractVerifierMessage inputMessage = contractVerifierMessaging.create(
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'{"bookName":"foo"}'</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span>,
[<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'sample'</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'header'</span>]
)
when:
contractVerifierMessaging.send(inputMessage, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'jms:input'</span>)
then:
ContractVerifierMessage response = contractVerifierMessaging.receive(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'jms:output'</span>)
assert response !- null
response.getHeader(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'BOOK-NAME'</span>)?.toString() == <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span>
and:
DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.payload))
assertThatJson(parsedJson).field(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"bookName"</span>).isEqualTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"foo"</span>)
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">""</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"</span></pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_scenario_3_no_output_message" href="#_scenario_3_no_output_message"></a>5.3.3&nbsp;Scenario 3: No Output Message</h3></div></div></div><p>Here is an example for Camel. For the given contract:</p><p><b>Groovy DSL.&nbsp;</b>
</p><pre class="programlisting">def contractDsl = Contract.make {
label <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'some_label'</span>
input {
messageFrom(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'jms:delete'</span>)
messageBody([
bookName: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span>
])
messageHeaders {
header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'sample'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'header'</span>)
}
assertThat(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'bookWasDeleted()'</span>)
}
}</pre><p>
</p><p><b>YAML.&nbsp;</b>
</p><pre class="programlisting">label: some_label
input:
messageFrom: jms:delete
messageBody:
bookName: 'foo'
messageHeaders:
sample: header
assertThat: bookWasDeleted()</pre><p>
</p><p>The following JUnit test is created:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'
</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// given:</span>
ContractVerifierMessage inputMessage = contractVerifierMessaging.create(
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"{\\"</span>bookName\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">":\\"</span>foo\\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"}"</span>
, headers()
.header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"sample"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"header"</span>));
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// when:</span>
contractVerifierMessaging.send(inputMessage, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"jms:delete"</span>);
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// then:</span>
bookWasDeleted();
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'</span></pre><p>And the following Spock test would be created:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'
</span>given:
ContractVerifierMessage inputMessage = contractVerifierMessaging.create(
\<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'\'\'{"bookName":"foo"}\'\'\',
</span> [<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'sample'</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'header'</span>]
)
when:
contractVerifierMessaging.send(inputMessage, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'jms:delete'</span>)
then:
noExceptionThrown()
bookWasDeleted()
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'</span></pre></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_consumer_stub_generation" href="#_consumer_stub_generation"></a>5.4&nbsp;Consumer Stub Generation</h2></div></div></div><p>Unlike the HTTP part, in messaging, we need to publish the Groovy DSL inside the JAR with
a stub. Then it is parsed on the consumer side and proper stubbed routes are created.</p><p>For more information, see
<a class="link" href="https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html/#stub-runner-for-messaging" target="_top">the
Stub Runner Messaging sections</a>.</p><p class="primary"><b>Maven.&nbsp;</b>
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;dependencies&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;dependency&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>spring-cloud-starter-stream-rabbit<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/dependency&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;dependency&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>spring-cloud-starter-contract-stub-runner<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;scope&gt;</span>test<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/scope&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/dependency&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;dependency&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>spring-cloud-stream-test-support<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;scope&gt;</span>test<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/scope&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/dependency&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/dependencies&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;dependencyManagement&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;dependencies&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;dependency&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>spring-cloud-dependencies<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;version&gt;</span>Edgware.BUILD-SNAPSHOT<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/version&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;type&gt;</span>pom<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/type&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;scope&gt;</span>import<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/scope&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/dependency&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/dependencies&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/dependencyManagement&gt;</span></pre><p class="primary">
</p><p class="secondary"><b>Gradle.&nbsp;</b>
</p><pre class="programlisting">ext {
contractsDir = file(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"mappings"</span>)
stubsOutputDirRoot = file(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"${project.buildDir}/production/${project.name}-stubs/"</span>)
}
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Automatically added by plugin:</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// copyContracts - copies contracts to the output folder from which JAR will be created</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// verifierStubsJar - JAR with a provided stub suffix</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// the presented publication is also added by the plugin but you can modify it as you wish</span>
publishing {
publications {
stubs(MavenPublication) {
artifactId <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"${project.name}-stubs"</span>
artifact verifierStubsJar
}
}
}</pre><p class="secondary">
</p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__spring_cloud_contract_verifier_setup.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi__spring_cloud_contract_stub_runner.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">4.&nbsp;Spring Cloud Contract Verifier Setup&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-contract.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;6.&nbsp;Spring Cloud Contract Stub Runner</td></tr></table></div></body></html>

View File

@@ -0,0 +1,606 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>4.&nbsp;Spring Cloud Contract Verifier Setup</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud-contract.html" title="Spring Cloud Contract"><link rel="up" href="multi_spring-cloud-contract.html" title="Spring Cloud Contract"><link rel="prev" href="multi__spring_cloud_contract_faq.html" title="3.&nbsp;Spring Cloud Contract FAQ"><link rel="next" href="multi__spring_cloud_contract_verifier_messaging.html" title="5.&nbsp;Spring Cloud Contract Verifier Messaging"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">4.&nbsp;Spring Cloud Contract Verifier Setup</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__spring_cloud_contract_faq.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi__spring_cloud_contract_verifier_messaging.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_spring_cloud_contract_verifier_setup" href="#_spring_cloud_contract_verifier_setup"></a>4.&nbsp;Spring Cloud Contract Verifier Setup</h1></div></div></div><p>You can set up Spring Cloud Contract Verifier in the following ways:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a class="link" href="multi__spring_cloud_contract_verifier_setup.html#gradle-project" title="4.1&nbsp;Gradle Project">As a Gradle project</a></li><li class="listitem"><a class="link" href="multi__spring_cloud_contract_verifier_setup.html#maven-project" title="4.2&nbsp;Maven Project">As a Maven project</a></li><li class="listitem"><a class="link" href="multi__spring_cloud_contract_verifier_setup.html#docker-project" title="4.6&nbsp;Docker Project">As a Docker project</a></li></ul></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="gradle-project" href="#gradle-project"></a>4.1&nbsp;Gradle Project</h2></div></div></div><p>To learn how to set up the Gradle project for Spring Cloud Contract Verifier, read the
following sections:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a class="xref" href="multi__spring_cloud_contract_verifier_setup.html#gradle-prerequisites" title="4.1.1&nbsp;Prerequisites">Section&nbsp;4.1.1, &#8220;Prerequisites&#8221;</a></li><li class="listitem"><a class="xref" href="multi__spring_cloud_contract_verifier_setup.html#gradle-add-gradle-plugin" title="4.1.2&nbsp;Add Gradle Plugin with Dependencies">Section&nbsp;4.1.2, &#8220;Add Gradle Plugin with Dependencies&#8221;</a></li><li class="listitem"><a class="xref" href="multi__spring_cloud_contract_verifier_setup.html#gradle-and-rest-assured" title="4.1.3&nbsp;Gradle and Rest Assured 2.0">Section&nbsp;4.1.3, &#8220;Gradle and Rest Assured 2.0&#8221;</a></li><li class="listitem"><a class="xref" href="multi__spring_cloud_contract_verifier_setup.html#gradle-snapshot-versions" title="4.1.4&nbsp;Snapshot Versions for Gradle">Section&nbsp;4.1.4, &#8220;Snapshot Versions for Gradle&#8221;</a></li><li class="listitem"><a class="xref" href="multi__spring_cloud_contract_verifier_setup.html#gradle-add-stubs" title="4.1.5&nbsp;Add stubs">Section&nbsp;4.1.5, &#8220;Add stubs&#8221;</a></li><li class="listitem"><a class="xref" href="multi__spring_cloud_contract_verifier_setup.html#gradle-default-setup" title="4.1.7&nbsp;Default Setup">Section&nbsp;4.1.7, &#8220;Default Setup&#8221;</a></li><li class="listitem"><a class="xref" href="multi__spring_cloud_contract_verifier_setup.html#gradle-configure-plugin" title="4.1.8&nbsp;Configure Plugin">Section&nbsp;4.1.8, &#8220;Configure Plugin&#8221;</a></li><li class="listitem"><a class="xref" href="multi__spring_cloud_contract_verifier_setup.html#gradle-configuration-options" title="4.1.9&nbsp;Configuration Options">Section&nbsp;4.1.9, &#8220;Configuration Options&#8221;</a></li><li class="listitem"><a class="xref" href="multi__spring_cloud_contract_verifier_setup.html#gradle-single-base-class" title="4.1.10&nbsp;Single Base Class for All Tests">Section&nbsp;4.1.10, &#8220;Single Base Class for All Tests&#8221;</a></li><li class="listitem"><a class="xref" href="multi__spring_cloud_contract_verifier_setup.html#gradle-different-base-classes" title="4.1.11&nbsp;Different Base Classes for Contracts">Section&nbsp;4.1.11, &#8220;Different Base Classes for Contracts&#8221;</a></li><li class="listitem"><a class="xref" href="multi__spring_cloud_contract_verifier_setup.html#gradle-invoking-generated-tests" title="4.1.12&nbsp;Invoking Generated Tests">Section&nbsp;4.1.12, &#8220;Invoking Generated Tests&#8221;</a></li><li class="listitem"><a class="xref" href="multi__spring_cloud_contract_verifier_setup.html#gradle-consumer" title="4.1.13&nbsp;Spring Cloud Contract Verifier on the Consumer Side">Section&nbsp;4.1.13, &#8220;Spring Cloud Contract Verifier on the Consumer Side&#8221;</a></li></ul></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="gradle-prerequisites" href="#gradle-prerequisites"></a>4.1.1&nbsp;Prerequisites</h3></div></div></div><p>In order to use Spring Cloud Contract Verifier with WireMock, you muse use either a
Gradle or a Maven plugin.</p><div class="warning" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Warning"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Warning]" src="images/warning.png"></td><th align="left">Warning</th></tr><tr><td align="left" valign="top"><p>If you want to use Spock in your projects, you must add separately the
<code class="literal">spock-core</code> and <code class="literal">spock-spring</code> modules. Check <a class="link" href="https://spockframework.github.io/" target="_top">Spock
docs for more information</a></p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="gradle-add-gradle-plugin" href="#gradle-add-gradle-plugin"></a>4.1.2&nbsp;Add Gradle Plugin with Dependencies</h3></div></div></div><p>To add a Gradle plugin with dependencies, use code similar to this:</p><pre class="programlisting">buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.boot:spring-boot-gradle-plugin:${springboot_version}"</span>
classpath <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud:spring-cloud-contract-gradle-plugin:${verifier_version}"</span>
}
}
apply plugin: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'groovy'</span>
apply plugin: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'spring-cloud-contract'</span>
dependencyManagement {
imports {
mavenBom <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud:spring-cloud-contract-dependencies:${verifier_version}"</span>
}
}
dependencies {
testCompile <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'org.codehaus.groovy:groovy-all:2.4.6'</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// example with adding Spock core and Spock Spring</span>
testCompile <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'org.spockframework:spock-core:1.0-groovy-2.4'</span>
testCompile <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'org.spockframework:spock-spring:1.0-groovy-2.4'</span>
testCompile <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'org.springframework.cloud:spring-cloud-starter-contract-verifier'</span>
}</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="gradle-and-rest-assured" href="#gradle-and-rest-assured"></a>4.1.3&nbsp;Gradle and Rest Assured 2.0</h3></div></div></div><p>By default, Rest Assured 3.x is added to the classpath. However, to use Rest Assured 2.x
you can add it to the plugins classpath, as shown here:</p><pre class="programlisting">buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.boot:spring-boot-gradle-plugin:${springboot_version}"</span>
classpath <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud:spring-cloud-contract-gradle-plugin:${verifier_version}"</span>
classpath <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"com.jayway.restassured:rest-assured:2.5.0"</span>
classpath <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"com.jayway.restassured:spring-mock-mvc:2.5.0"</span>
}
}
depenendencies {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// all dependencies</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// you can exclude rest-assured from spring-cloud-contract-verifier</span>
testCompile <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"com.jayway.restassured:rest-assured:2.5.0"</span>
testCompile <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"com.jayway.restassured:spring-mock-mvc:2.5.0"</span>
}</pre><p>That way, the plugin automatically sees that Rest Assured 2.x is present on the classpath
and modifies the imports accordingly.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="gradle-snapshot-versions" href="#gradle-snapshot-versions"></a>4.1.4&nbsp;Snapshot Versions for Gradle</h3></div></div></div><p>Add the additional snapshot repository to your build.gradle to use snapshot versions,
which are automatically uploaded after every successful build, as shown here:</p><pre class="programlisting">buildscript {
repositories {
mavenCentral()
mavenLocal()
maven { url <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"https://repo.spring.io/snapshot"</span> }
maven { url <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"https://repo.spring.io/milestone"</span> }
maven { url <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"https://repo.spring.io/release"</span> }
}
}</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="gradle-add-stubs" href="#gradle-add-stubs"></a>4.1.5&nbsp;Add stubs</h3></div></div></div><p>By default, Spring Cloud Contract Verifier is looking for stubs in the
<code class="literal">src/test/resources/contracts</code> directory.</p><p>The directory containing stub definitions is treated as a class name, and each stub
definition is treated as a single test. Spring Cloud Contract Verifier assumes that it
contains at least one level of directories that are to be used as the test class name.
If more than one level of nested directories is present, all except the last one is used
as the package name. For example, with following structure:</p><pre class="programlisting">src/test/resources/contracts/myservice/shouldCreateUser.groovy
src/test/resources/contracts/myservice/shouldReturnUser.groovy</pre><p>Spring Cloud Contract Verifier creates a test class named <code class="literal">defaultBasePackage.MyService</code>
with two methods:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">shouldCreateUser()</code></li><li class="listitem"><code class="literal">shouldReturnUser()</code></li></ul></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="gradle-run-plugin" href="#gradle-run-plugin"></a>4.1.6&nbsp;Run the Plugin</h3></div></div></div><p>The plugin registers itself to be invoked before a <code class="literal">check</code> task. If you want it to be
part of your build process, you need to do nothing more. If you just want to generate
tests, invoke the <code class="literal">generateContractTests</code> task.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="gradle-default-setup" href="#gradle-default-setup"></a>4.1.7&nbsp;Default Setup</h3></div></div></div><p>The default Gradle Plugin setup creates the following Gradle part of the build (in
pseudocode):</p><pre class="programlisting">contracts {
targetFramework = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'JUNIT'</span>
testMode = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'MockMvc'</span>
generatedTestSourcesDir = project.file(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"${project.buildDir}/generated-test-sources/contracts"</span>)
contractsDslDir = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"${project.rootDir}/src/test/resources/contracts"</span>
basePackageForTests = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'org.springframework.cloud.verifier.tests'</span>
stubsOutputDir = project.file(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"${project.buildDir}/stubs"</span>)
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// the following properties are used when you want to provide where the JAR with contract lays</span>
contractDependency {
stringNotation = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span>
}
contractsPath = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span>
contractsWorkOffline = false
contractRepository {
cacheDownloadedContracts(true)
}
}
tasks.create(type: Jar, name: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'verifierStubsJar'</span>, dependsOn: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'generateClientStubs'</span>) {
baseName = project.name
classifier = contracts.stubsSuffix
from contractVerifier.stubsOutputDir
}
project.artifacts {
archives task
}
tasks.create(type: Copy, name: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'copyContracts'</span>) {
from contracts.contractsDslDir
into contracts.stubsOutputDir
}
verifierStubsJar.dependsOn <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'copyContracts'</span>
publishing {
publications {
stubs(MavenPublication) {
artifactId project.name
artifact verifierStubsJar
}
}
}</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="gradle-configure-plugin" href="#gradle-configure-plugin"></a>4.1.8&nbsp;Configure Plugin</h3></div></div></div><p>To change the default configuration, add a <code class="literal">contracts</code> snippet to your Gradle config, as
shown here:</p><pre class="programlisting">contracts {
testMode = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'MockMvc'</span>
baseClassForTests = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'org.mycompany.tests'</span>
generatedTestSourcesDir = project.file(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'src/generatedContract'</span>)
}</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="gradle-configuration-options" href="#gradle-configuration-options"></a>4.1.9&nbsp;Configuration Options</h3></div></div></div><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><span class="strong"><strong>testMode</strong></span>: Defines the mode for acceptance tests. By default, the mode is MockMvc,
which is based on Spring&#8217;s MockMvc. It can also be changed to <span class="strong"><strong>JaxRsClient</strong></span> or to
<span class="strong"><strong>Explicit</strong></span> for real HTTP calls.</li><li class="listitem"><span class="strong"><strong>imports</strong></span>: Creates an array with imports that should be included in generated tests
(for example ['org.myorg.Matchers']). By default, it creates an empty array.</li><li class="listitem"><span class="strong"><strong>staticImports</strong></span>: Creates an array with static imports that should be included in
generated tests(for example ['org.myorg.Matchers.*']). By default, it creates an empty
array.</li><li class="listitem"><span class="strong"><strong>basePackageForTests</strong></span>: Specifies the base package for all generated tests. If not set,
the value is picked from <code class="literal">baseClassForTests&#8217;s package and from `packageWithBaseClasses</code>.
If neither of these values are set, then the value is set to
<code class="literal">org.springframework.cloud.contract.verifier.tests</code>.</li><li class="listitem"><span class="strong"><strong>baseClassForTests</strong></span>: Creates a base class for all generated tests. By default, if you
use Spock classes, the class is <code class="literal">spock.lang.Specification</code>.</li><li class="listitem"><span class="strong"><strong>packageWithBaseClasses</strong></span>: Defines a package where all the base classes reside. This
setting takes precedence over <span class="strong"><strong>baseClassForTests</strong></span>.</li><li class="listitem"><span class="strong"><strong>baseClassMappings</strong></span>: Explicitly maps a contract package to a FQN of a base class. This
setting takes precedence over <span class="strong"><strong>packageWithBaseClasses</strong></span> and <span class="strong"><strong>baseClassForTests</strong></span>.</li><li class="listitem"><span class="strong"><strong>ruleClassForTests</strong></span>: Specifies a rule that should be added to the generated test
classes.</li><li class="listitem"><span class="strong"><strong>ignoredFiles</strong></span>: Uses an <code class="literal">Antmatcher</code> to allow defining stub files for which processing
should be skipped. By default, it is an empty array.</li><li class="listitem"><span class="strong"><strong>contractsDslDir</strong></span>: Specifies the directory containing contracts written using the
GroovyDSL. By default, its value is <code class="literal">$rootDir/src/test/resources/contracts</code>.</li><li class="listitem"><span class="strong"><strong>generatedTestSourcesDir</strong></span>: Specifies the test source directory where tests generated
from the Groovy DSL should be placed. By default its value is
<code class="literal">$buildDir/generated-test-sources/contractVerifier</code>.</li><li class="listitem"><span class="strong"><strong>stubsOutputDir</strong></span>: Specifies the directory where the generated WireMock stubs from
the Groovy DSL should be placed.</li><li class="listitem"><span class="strong"><strong>targetFramework</strong></span>: Specifies the target test framework to be used. Currently, Spock and
JUnit are supported with JUnit being the default framework.</li></ul></div><p>The following properties are used when you want to specify the location of the JAR
containing the contracts:
* <span class="strong"><strong>contractDependency</strong></span>: Specifies the Dependency that provides
<code class="literal">groupid:artifactid:version:classifier</code> coordinates. You can use the <code class="literal">contractDependency</code>
closure to set it up.
* <span class="strong"><strong>contractsPath</strong></span>: Specifies the path to the jar. If contract dependencies are
downloaded, the path defaults to <code class="literal">groupid/artifactid</code> where <code class="literal">groupid</code> is slash
separated. Otherwise, it scans contracts under the provided directory.
* <span class="strong"><strong>contractsWorkOffline</strong></span>: Specifies whether to download the dependencies each time, so
that you can work online. In other words, it specifies whether to reuses the local Maven
repo.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="gradle-single-base-class" href="#gradle-single-base-class"></a>4.1.10&nbsp;Single Base Class for All Tests</h3></div></div></div><p>When using Spring Cloud Contract Verifier in default MockMvc, you need to create a base
specification for all generated acceptance tests. In this class, you need to point to an
endpoint, which should be verified.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">abstract</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> BaseMockMvcSpec <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">extends</span> Specification {
def setup() {
RestAssuredMockMvc.standaloneSetup(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> PairIdController())
}
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> isProperCorrelationId(Integer correlationId) {
assert correlationId == <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">123456</xslthl:number>
}
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> isEmpty(String value) {
assert value == null
}
}</pre><p>If you use <code class="literal">Explicit</code> mode, you can use a base class to initialize the whole tested app
as you might see in regular integration tests. If you use the <code class="literal">JAXRSCLIENT</code> mode, this
base class should also contain a <code class="literal">protected WebTarget webTarget</code> field. Right now, the
only option to test the JAX-RS API is to start a web server.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="gradle-different-base-classes" href="#gradle-different-base-classes"></a>4.1.11&nbsp;Different Base Classes for Contracts</h3></div></div></div><p>If your base classes differ between contracts, you can tell the Spring Cloud Contract
plugin which class should get extended by the autogenerated tests. You have two options:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Follow a convention by providing the <code class="literal">packageWithBaseClasses</code></li><li class="listitem">Provide explicit mapping via <code class="literal">baseClassMappings</code></li></ul></div><p><span class="strong"><strong>By Convention</strong></span></p><p>The convention is such that if you have a contract under (for example)
<code class="literal">src/test/resources/contract/foo/bar/baz/</code> and set the value of the
<code class="literal">packageWithBaseClasses</code> property to <code class="literal">com.example.base</code>, then Spring Cloud Contract
Verifier assumes that there is a <code class="literal">BarBazBase</code> class under the <code class="literal">com.example.base</code> package.
In other words, the system takes the last two parts of the package, if they exist, and
forms a class with a <code class="literal">Base</code> suffix. This rule takes precedence over <span class="strong"><strong>baseClassForTests</strong></span>.
Here is an example of how it works in the <code class="literal">contracts</code> closure:</p><pre class="programlisting">packageWithBaseClasses = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'com.example.base'</span></pre><p><span class="strong"><strong>By Mapping</strong></span></p><p>You can manually map a regular expression of the contract&#8217;s package to fully qualified
name of the base class for the matched contract. You have to provide a list called
<code class="literal">baseClassMappings</code> that consists <code class="literal">baseClassMapping</code> objects that takes a
<code class="literal">contractPackageRegex</code> to <code class="literal">baseClassFQN</code> mapping. Consider the following example:</p><pre class="programlisting">baseClassForTests = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"com.example.FooBase"</span>
baseClassMappings {
baseClassMapping(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'.*/com/.*'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'com.example.ComBase'</span>)
baseClassMapping(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'.*/bar/.*'</span>:<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'com.example.BarBase'</span>)
}</pre><p>Let&#8217;s assume that you have contracts under
- <code class="literal">src/test/resources/contract/com/</code>
- <code class="literal">src/test/resources/contract/foo/</code></p><p>By providing the <code class="literal">baseClassForTests</code>, we have a fallback in case mapping did not succeed.
(You could also provide the <code class="literal">packageWithBaseClasses</code> as a fallback.) That way, the tests
generated from <code class="literal">src/test/resources/contract/com/</code> contracts extend the
<code class="literal">com.example.ComBase</code>, whereas the rest of the tests extend <code class="literal">com.example.FooBase</code>.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="gradle-invoking-generated-tests" href="#gradle-invoking-generated-tests"></a>4.1.12&nbsp;Invoking Generated Tests</h3></div></div></div><p>To ensure that the provider side is compliant with defined contracts, you need to invoke:</p><pre class="programlisting">./gradlew generateContractTests <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">test</span></pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="gradle-consumer" href="#gradle-consumer"></a>4.1.13&nbsp;Spring Cloud Contract Verifier on the Consumer Side</h3></div></div></div><p>In a consuming service, you need to configure the Spring Cloud Contract Verifier plugin
in exactly the same way as in case of provider. If you do not want to use Stub Runner
then you need to copy contracts stored in <code class="literal">src/test/resources/contracts</code> and generate
WireMock JSON stubs using:</p><pre class="programlisting">./gradlew generateClientStubs</pre><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>The <code class="literal">stubsOutputDir</code> option has to be set for stub generation to work.</p></td></tr></table></div><p>When present, JSON stubs can be used in automated tests of consuming a service.</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@ContextConfiguration(loader == SpringApplicationContextLoader, classes == Application)</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> LoanApplicationServiceSpec <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">extends</span> Specification {
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@ClassRule</xslthl:annotation>
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Shared</xslthl:annotation>
WireMockClassRule wireMockRule == <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> WireMockClassRule()
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Autowired</xslthl:annotation>
LoanApplicationService sut
def <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'should successfully apply for loan'</span>() {
given:
LoanApplication application =
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> LoanApplication(client: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> Client(clientPesel: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'12345678901'</span>), amount: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">123.123</xslthl:number>)
when:
LoanApplicationResult loanApplication == sut.loanApplication(application)
then:
loanApplication.loanApplicationStatus == LoanApplicationStatus.LOAN_APPLIED
loanApplication.rejectionReason == null
}
}</pre><p><code class="literal">LoanApplication</code> makes a call to <code class="literal">FraudDetection</code> service. This request is handled by a
WireMock server configured with stubs generated by Spring Cloud Contract Verifier.</p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="maven-project" href="#maven-project"></a>4.2&nbsp;Maven Project</h2></div></div></div><p>To learn how to set up the Maven project for Spring Cloud Contract Verifier, read the
following sections:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a class="xref" href="multi__spring_cloud_contract_verifier_setup.html#maven-add-plugin" title="4.2.1&nbsp;Add maven plugin">Section&nbsp;4.2.1, &#8220;Add maven plugin&#8221;</a></li><li class="listitem"><a class="xref" href="multi__spring_cloud_contract_verifier_setup.html#maven-rest-assured" title="4.2.2&nbsp;Maven and Rest Assured 2.0">Section&nbsp;4.2.2, &#8220;Maven and Rest Assured 2.0&#8221;</a></li><li class="listitem"><a class="xref" href="multi__spring_cloud_contract_verifier_setup.html#maven-snapshot-versions" title="4.2.3&nbsp;Snapshot versions for Maven">Section&nbsp;4.2.3, &#8220;Snapshot versions for Maven&#8221;</a></li><li class="listitem"><a class="xref" href="multi__spring_cloud_contract_verifier_setup.html#maven-add-stubs" title="4.2.4&nbsp;Add stubs">Section&nbsp;4.2.4, &#8220;Add stubs&#8221;</a></li><li class="listitem"><a class="xref" href="multi__spring_cloud_contract_verifier_setup.html#maven-run-plugin" title="4.2.5&nbsp;Run plugin">Section&nbsp;4.2.5, &#8220;Run plugin&#8221;</a></li><li class="listitem"><a class="xref" href="multi__spring_cloud_contract_verifier_setup.html#maven-configure-plugin" title="4.2.6&nbsp;Configure plugin">Section&nbsp;4.2.6, &#8220;Configure plugin&#8221;</a></li><li class="listitem"><a class="xref" href="multi__spring_cloud_contract_verifier_setup.html#maven-configuration-options" title="4.2.7&nbsp;Configuration Options">Section&nbsp;4.2.7, &#8220;Configuration Options&#8221;</a></li><li class="listitem"><a class="xref" href="multi__spring_cloud_contract_verifier_setup.html#maven-single-base" title="4.2.8&nbsp;Single Base Class for All Tests">Section&nbsp;4.2.8, &#8220;Single Base Class for All Tests&#8221;</a></li><li class="listitem"><a class="xref" href="multi__spring_cloud_contract_verifier_setup.html#maven-different-base" title="4.2.9&nbsp;Different base classes for contracts">Section&nbsp;4.2.9, &#8220;Different base classes for contracts&#8221;</a></li><li class="listitem"><a class="xref" href="multi__spring_cloud_contract_verifier_setup.html#maven-invoking-generated-tests" title="4.2.10&nbsp;Invoking generated tests">Section&nbsp;4.2.10, &#8220;Invoking generated tests&#8221;</a></li><li class="listitem"><a class="xref" href="multi__spring_cloud_contract_verifier_setup.html#maven-sts" title="4.2.11&nbsp;Maven Plugin and STS">Section&nbsp;4.2.11, &#8220;Maven Plugin and STS&#8221;</a></li></ul></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="maven-add-plugin" href="#maven-add-plugin"></a>4.2.1&nbsp;Add maven plugin</h3></div></div></div><p>Add the Spring Cloud Contract BOM in a fashion similar to this:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;dependencyManagement&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;dependencies&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;dependency&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>spring-cloud-dependencies<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;version&gt;</span>${spring-cloud-dependencies.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/version&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;type&gt;</span>pom<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/type&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;scope&gt;</span>import<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/scope&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/dependency&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/dependencies&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/dependencyManagement&gt;</span></pre><p>Next, add the <code class="literal">Spring Cloud Contract Verifier</code> Maven plugin:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;plugin&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>spring-cloud-contract-maven-plugin<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;version&gt;</span>${spring-cloud-contract.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/version&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;extensions&gt;</span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/extensions&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;configuration&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;packageWithBaseClasses&gt;</span>com.example.fraud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/packageWithBaseClasses&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/configuration&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/plugin&gt;</span></pre><p>You can read more in the
<a class="link" href="https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract-maven-plugin/" target="_top">Spring
Cloud Contract Maven Plugin Documentation</a>.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="maven-rest-assured" href="#maven-rest-assured"></a>4.2.2&nbsp;Maven and Rest Assured 2.0</h3></div></div></div><p>By default, Rest Assured 3.x is added to the classpath. However, you can use Rest
Assured 2.x by adding it to the plugins classpath, as shown here:</p><pre class="programlisting">&lt;plugin&gt;
&lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
&lt;artifactId&gt;spring-cloud-contract-maven-plugin&lt;/artifactId&gt;
&lt;version&gt;${spring-cloud-contract.version}&lt;/version&gt;
&lt;extensions&gt;true&lt;/extensions&gt;
&lt;configuration&gt;
&lt;packageWithBaseClasses&gt;com.example&lt;/packageWithBaseClasses&gt;
&lt;/configuration&gt;
&lt;dependencies&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
&lt;artifactId&gt;spring-cloud-contract-verifier&lt;/artifactId&gt;
&lt;version&gt;${spring-cloud-contract.version}&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;com.jayway.restassured&lt;/groupId&gt;
&lt;artifactId&gt;rest-assured&lt;/artifactId&gt;
&lt;version&gt;<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2.5</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>&lt;/version&gt;
&lt;scope&gt;compile&lt;/scope&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;com.jayway.restassured&lt;/groupId&gt;
&lt;artifactId&gt;spring-mock-mvc&lt;/artifactId&gt;
&lt;version&gt;<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2.5</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>&lt;/version&gt;
&lt;scope&gt;compile&lt;/scope&gt;
&lt;/dependency&gt;
&lt;/dependencies&gt;
&lt;/plugin&gt;
&lt;dependencies&gt;
&lt;!-- all dependencies --&gt;
&lt;!-- you can exclude rest-assured from spring-cloud-contract-verifier --&gt;
&lt;dependency&gt;
&lt;groupId&gt;com.jayway.restassured&lt;/groupId&gt;
&lt;artifactId&gt;rest-assured&lt;/artifactId&gt;
&lt;version&gt;<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2.5</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>&lt;/version&gt;
&lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;com.jayway.restassured&lt;/groupId&gt;
&lt;artifactId&gt;spring-mock-mvc&lt;/artifactId&gt;
&lt;version&gt;<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2.5</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>&lt;/version&gt;
&lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;
&lt;/dependencies&gt;</pre><p>That way, the plugin automatically sees that Rest Assured 3.x is present on the classpath
and modifies the imports accordingly.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="maven-snapshot-versions" href="#maven-snapshot-versions"></a>4.2.3&nbsp;Snapshot versions for Maven</h3></div></div></div><p>For Snapshot and Milestone versions, you have to add the following section to your
<code class="literal">pom.xml</code>, as shown here:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;repositories&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;repository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;id&gt;</span>spring-snapshots<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/id&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;name&gt;</span>Spring Snapshots<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/name&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;url&gt;</span>https://repo.spring.io/snapshot<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/url&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;enabled&gt;</span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/enabled&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/repository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;repository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;id&gt;</span>spring-milestones<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/id&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;name&gt;</span>Spring Milestones<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/name&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;url&gt;</span>https://repo.spring.io/milestone<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/url&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;enabled&gt;</span>false<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/enabled&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/repository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;repository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;id&gt;</span>spring-releases<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/id&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;name&gt;</span>Spring Releases<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/name&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;url&gt;</span>https://repo.spring.io/release<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/url&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;enabled&gt;</span>false<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/enabled&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/repository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/repositories&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;pluginRepositories&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;pluginRepository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;id&gt;</span>spring-snapshots<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/id&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;name&gt;</span>Spring Snapshots<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/name&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;url&gt;</span>https://repo.spring.io/snapshot<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/url&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;enabled&gt;</span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/enabled&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/pluginRepository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;pluginRepository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;id&gt;</span>spring-milestones<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/id&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;name&gt;</span>Spring Milestones<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/name&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;url&gt;</span>https://repo.spring.io/milestone<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/url&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;enabled&gt;</span>false<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/enabled&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/pluginRepository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;pluginRepository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;id&gt;</span>spring-releases<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/id&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;name&gt;</span>Spring Releases<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/name&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;url&gt;</span>https://repo.spring.io/release<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/url&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;enabled&gt;</span>false<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/enabled&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/snapshots&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/pluginRepository&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/pluginRepositories&gt;</span></pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="maven-add-stubs" href="#maven-add-stubs"></a>4.2.4&nbsp;Add stubs</h3></div></div></div><p>By default, Spring Cloud Contract Verifier is looking for stubs in the
<code class="literal">src/test/resources/contracts</code> directory. The directory containing stub definitions is
treated as a class name, and each stub definition is treated as a single test. We assume
that it contains at least one directory to be used as test class name. If there is more
than one level of nested directories, all except the last one is used as package name.
For example, with following structure:</p><pre class="programlisting">src/test/resources/contracts/myservice/shouldCreateUser.groovy
src/test/resources/contracts/myservice/shouldReturnUser.groovy</pre><p>Spring Cloud Contract Verifier creates a test class named <code class="literal">defaultBasePackage.MyService</code>
with two methods</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">shouldCreateUser()</code></li><li class="listitem"><code class="literal">shouldReturnUser()</code></li></ul></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="maven-run-plugin" href="#maven-run-plugin"></a>4.2.5&nbsp;Run plugin</h3></div></div></div><p>The plugin goal <code class="literal">generateTests</code> is assigned to be invoked in the phase called
<code class="literal">generate-test-sources</code>. If you want it to be part of your build process, you need not do
anything. If you just want to generate tests, invoke the <code class="literal">generateTests</code> goal.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="maven-configure-plugin" href="#maven-configure-plugin"></a>4.2.6&nbsp;Configure plugin</h3></div></div></div><p>To change the default configuration, just add a <code class="literal">configuration</code> section to the plugin
definition or the <code class="literal">execution</code> definition, as shown here:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;plugin&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>spring-cloud-contract-maven-plugin<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;executions&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;execution&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;goals&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;goal&gt;</span>convert<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/goal&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;goal&gt;</span>generateStubs<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/goal&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;goal&gt;</span>generateTests<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/goal&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/goals&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/execution&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/executions&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;configuration&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;basePackageForTests&gt;</span>org.springframework.cloud.verifier.twitter.place<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/basePackageForTests&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;baseClassForTests&gt;</span>org.springframework.cloud.verifier.twitter.place.BaseMockMvcSpec<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/baseClassForTests&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/configuration&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/plugin&gt;</span></pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="maven-configuration-options" href="#maven-configuration-options"></a>4.2.7&nbsp;Configuration Options</h3></div></div></div><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><span class="strong"><strong>testMode</strong></span>: Defines the mode for acceptance tests. By default, the mode is MockMvc,
which is based on Spring&#8217;s MockMvc. It can also be changed to <span class="strong"><strong>JaxRsClient</strong></span> or to
<span class="strong"><strong>Explicit</strong></span> for real HTTP calls.</li><li class="listitem"><span class="strong"><strong>basePackageForTests</strong></span>: Specifies the base package for all generated tests. If not set,
the value is picked from <code class="literal">baseClassForTests&#8217;s package and from `packageWithBaseClasses</code>.
If neither of these values are set, then the value is set to
<code class="literal">org.springframework.cloud.contract.verifier.tests</code>.</li><li class="listitem"><span class="strong"><strong>ruleClassForTests</strong></span>: Specifies a rule that should be added to the generated test
classes.</li><li class="listitem"><span class="strong"><strong>baseClassForTests</strong></span>: Creates a base class for all generated tests. By default, if you
use Spock classes, the class is <code class="literal">spock.lang.Specification</code>.</li><li class="listitem"><span class="strong"><strong>contractsDirectory</strong></span>: Specifies a directory containing contracts written with the
GroovyDSL. The default directory is <code class="literal">/src/test/resources/contracts</code>.</li><li class="listitem"><span class="strong"><strong>testFramework</strong></span>: Specifies the target test framework to be used. Currently, Spock and
JUnit are supported with JUnit being the default framework</li><li class="listitem"><span class="strong"><strong>packageWithBaseClasses</strong></span>: Defines a package where all the base classes reside. This
setting takes precedence over <span class="strong"><strong>baseClassForTests</strong></span>. The convention is such that, if you
have a contract under (for example) <code class="literal">src/test/resources/contract/foo/bar/baz/</code> and set
the value of the <code class="literal">packageWithBaseClasses</code> property to <code class="literal">com.example.base</code>, then Spring
Cloud Contract Verifier assumes that there is a <code class="literal">BarBazBase</code> class under the
<code class="literal">com.example.base</code> package. In other words, the system takes the last two parts of the
package, if they exist, and forms a class with a <code class="literal">Base</code> suffix.</li><li class="listitem"><span class="strong"><strong>baseClassMappings</strong></span>: Specifies a list of base class mappings that provide
<code class="literal">contractPackageRegex</code>, which is checked against the package where the contract is
located, and <code class="literal">baseClassFQN</code>, which maps to the fully qualified name of the base class for
the matched contract. For example, if you have a contract under
<code class="literal">src/test/resources/contract/foo/bar/baz/</code> and map the property
<code class="literal">.* &#8594; com.example.base.BaseClass</code>, then the test class generated from these contracts
extends <code class="literal">com.example.base.BaseClass</code>. This setting takes precedence over
<span class="strong"><strong>packageWithBaseClasses</strong></span> and <span class="strong"><strong>baseClassForTests</strong></span>.</li></ul></div><p>If you want to download your contract definitions from a Maven repository, you can use
the following options:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><span class="strong"><strong>contractDependency</strong></span>: The contract dependency that contains all the packaged contracts.</li><li class="listitem"><span class="strong"><strong>contractsPath</strong></span>: The path to the concrete contracts in the JAR with packaged contracts.
Defaults to <code class="literal">groupid/artifactid</code> where <code class="literal">gropuid</code> is slash separated.</li><li class="listitem"><span class="strong"><strong>contractsWorkOffline</strong></span>: Dictates whether the dependencies should be downloaded or the
local Maven artifacts should be reused.</li><li class="listitem"><span class="strong"><strong>contractsRepositoryUrl</strong></span>: URL to a repo with the artifacts that have contracts. If it is not provided,
use the current Maven ones.</li><li class="listitem"><span class="strong"><strong>contractsRepositoryUsername</strong></span>: The user name to be used to connect to the repo with contracts.</li><li class="listitem"><span class="strong"><strong>contractsRepositoryPassword</strong></span>: The password to be used to connect to the repo with contracts.</li><li class="listitem"><span class="strong"><strong>contractsRepositoryProxyHost</strong></span>: The proxy host to be used to connect to the repo with contracts.</li><li class="listitem"><span class="strong"><strong>contractsRepositoryProxyPort</strong></span>: The proxy port to be used to connect to the repo with contracts.</li></ul></div><p>We cache only non-snapshot, explicitly provided versions (for example
<code class="literal">+</code> or <code class="literal">1.0.0.BUILD-SNAPSHOT</code> won&#8217;t get cached). By default, this feature is turned on.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="maven-single-base" href="#maven-single-base"></a>4.2.8&nbsp;Single Base Class for All Tests</h3></div></div></div><p>When using Spring Cloud Contract Verifier in default MockMvc, you need to create a base
specification for all generated acceptance tests. In this class, you need to point to an
endpoint, which should be verified.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">package</span> org.mycompany.tests
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.mycompany.ExampleSpringController
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> com.jayway.restassured.module.mockmvc.RestAssuredMockMvc
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> spock.lang.Specification
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> MvcSpec <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">extends</span> Specification {
def setup() {
RestAssuredMockMvc.standaloneSetup(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> ExampleSpringController())
}
}</pre><p>If you use <code class="literal">Explicit</code> mode, you can use a base class to initialize the whole tested app
similarly, as you might find in regular integration tests. If you use the <code class="literal">JAXRSCLIENT</code>
mode, this base class should also contain a <code class="literal">protected WebTarget webTarget</code> field. Right
now, the only option to test the JAX-RS API is to start a web server.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="maven-different-base" href="#maven-different-base"></a>4.2.9&nbsp;Different base classes for contracts</h3></div></div></div><p>If your base classes differ between contracts, you can tell the Spring Cloud Contract
plugin which class should get extended by the autogenerated tests. You have two options:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Follow a convention by providing the <code class="literal">packageWithBaseClasses</code></li><li class="listitem">provide explicit mapping via <code class="literal">baseClassMappings</code></li></ul></div><p><span class="strong"><strong>By Convention</strong></span></p><p>The convention is such that if you have a contract under (for example)
<code class="literal">src/test/resources/contract/foo/bar/baz/</code> and set the value of the
<code class="literal">packageWithBaseClasses</code> property to <code class="literal">com.example.base</code>, then Spring Cloud Contract
Verifier assumes that there is a <code class="literal">BarBazBase</code> class under the <code class="literal">com.example.base</code> package.
In other words, the system takes the last two parts of the package, if they exist, and
forms a class with a <code class="literal">Base</code> suffix. This rule takes precedence over <span class="strong"><strong>baseClassForTests</strong></span>.
Here is an example of how it works in the <code class="literal">contracts</code> closure:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;plugin&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>spring-cloud-contract-maven-plugin<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;configuration&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;packageWithBaseClasses&gt;</span>hello<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/packageWithBaseClasses&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/configuration&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/plugin&gt;</span></pre><p><span class="strong"><strong>By Mapping</strong></span></p><p>You can manually map a regular expression of the contract&#8217;s package to fully qualified
name of the base class for the matched contract. You have to provide a list called
<code class="literal">baseClassMappings</code> that consists <code class="literal">baseClassMapping</code> objects that takes a
<code class="literal">contractPackageRegex</code> to <code class="literal">baseClassFQN</code> mapping. Consider the following example:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;plugin&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>spring-cloud-contract-maven-plugin<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;configuration&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;baseClassForTests&gt;</span>com.example.FooBase<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/baseClassForTests&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;baseClassMappings&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;baseClassMapping&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;contractPackageRegex&gt;</span>.*com.*<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/contractPackageRegex&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;baseClassFQN&gt;</span>com.example.TestBase<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/baseClassFQN&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/baseClassMapping&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/baseClassMappings&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/configuration&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/plugin&gt;</span></pre><p>Assume that you have contracts under these two locations:
* <code class="literal">src/test/resources/contract/com/</code>
* <code class="literal">src/test/resources/contract/foo/</code></p><p>By providing the <code class="literal">baseClassForTests</code>, we have a fallback in case mapping did not succeed.
(You can also provide the <code class="literal">packageWithBaseClasses</code> as a fallback.) That way, the tests
generated from <code class="literal">src/test/resources/contract/com/</code> contracts extend the
<code class="literal">com.example.ComBase</code>, whereas the rest of the tests extend <code class="literal">com.example.FooBase</code>.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="maven-invoking-generated-tests" href="#maven-invoking-generated-tests"></a>4.2.10&nbsp;Invoking generated tests</h3></div></div></div><p>The Spring Cloud Contract Maven Plugin generates verification code in a directory called
<code class="literal">/generated-test-sources/contractVerifier</code> and attaches this directory to <code class="literal">testCompile</code>
goal.</p><p>For Groovy Spock code, use the following:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;plugin&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>org.codehaus.gmavenplus<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>gmavenplus-plugin<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;version&gt;</span>1.5<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/version&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;executions&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;execution&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;goals&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;goal&gt;</span>testCompile<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/goal&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/goals&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/execution&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/executions&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;configuration&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;testSources&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;testSource&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;directory&gt;</span>${project.basedir}/src/test/groovy<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/directory&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;includes&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;include&gt;</span>**/*.groovy<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/include&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/includes&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/testSource&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;testSource&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;directory&gt;</span>${project.build.directory}/generated-test-sources/contractVerifier<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/directory&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;includes&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;include&gt;</span>**/*.groovy<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/include&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/includes&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/testSource&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/testSources&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/configuration&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/plugin&gt;</span></pre><p>To ensure that provider side is compliant with defined contracts, you need to invoke
<code class="literal">mvn generateTest test</code>.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="maven-sts" href="#maven-sts"></a>4.2.11&nbsp;Maven Plugin and STS</h3></div></div></div><p>If you see the following exception while using STS:</p><div class="informalfigure"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/1.2.x/docs/src/main/asciidoc/images/sts_exception.png" alt="STS Exception"></div></div><p>When you click on the error marker you should see something like this:</p><pre class="programlisting"> plugin:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1.1</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.</xslthl:number>M1:convert:default-convert:process-<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">test</span>-resources) org.apache.maven.plugin.PluginExecutionException: Execution default-convert of goal org.springframework.cloud:spring-
cloud-contract-maven-plugin:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1.1</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.</xslthl:number>M1:convert failed. at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">145</xslthl:number>) at
org.eclipse.m2e.core.internal.embedder.MavenImpl.execute(MavenImpl.java:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">331</xslthl:number>) at org.eclipse.m2e.core.internal.embedder.MavenImpl$<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">11.</xslthl:number>call(MavenImpl.java:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1362</xslthl:number>) at
...
org.eclipse.core.internal.jobs.Worker.run(Worker.java:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">55</xslthl:number>) Caused by: java.lang.NullPointerException at
org.eclipse.m2e.core.internal.builder.plexusbuildapi.EclipseIncrementalBuildContext.hasDelta(EclipseIncrementalBuildContext.java:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">53</xslthl:number>) at
org.sonatype.plexus.build.incremental.ThreadBuildContext.hasDelta(ThreadBuildContext.java:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">59</xslthl:number>) at</pre><p>In order to fix this issue, provide the following section in your <code class="literal">pom.xml</code>:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;build&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;pluginManagement&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;plugins&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">&lt;!--This plugin's configuration is used to store Eclipse m2e settings
only. It has no influence on the Maven build itself. --&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;plugin&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>org.eclipse.m2e<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>lifecycle-mapping<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;version&gt;</span>1.0.0<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/version&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;configuration&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;lifecycleMappingMetadata&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;pluginExecutions&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;pluginExecution&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;pluginExecutionFilter&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>spring-cloud-contract-maven-plugin<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;versionRange&gt;</span>[1.0,)<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/versionRange&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;goals&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;goal&gt;</span>convert<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/goal&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/goals&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/pluginExecutionFilter&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;action&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;execute /&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/action&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/pluginExecution&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/pluginExecutions&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/lifecycleMappingMetadata&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/configuration&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/plugin&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/plugins&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/pluginManagement&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/build&gt;</span></pre></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_stubs_and_transitive_dependencies" href="#_stubs_and_transitive_dependencies"></a>4.3&nbsp;Stubs and Transitive Dependencies</h2></div></div></div><p>The Maven and Gradle plugin that add the tasks that create the stubs jar for you. One
problem that arises is that, when reusing the stubs, you can mistakenly import all of
that stub&#8217;s dependencies. When building a Maven artifact, even though you have a couple
of different jars, all of them share one pom:</p><pre class="programlisting">&#9500;&#9472;&#9472; github-webhook-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1.</xslthl:number>BUILD-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">20160903.075506</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-stubs.jar
&#9500;&#9472;&#9472; github-webhook-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1.</xslthl:number>BUILD-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">20160903.075506</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-stubs.jar.sha1
&#9500;&#9472;&#9472; github-webhook-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1.</xslthl:number>BUILD-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">20160903.075655</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2</xslthl:number>-stubs.jar
&#9500;&#9472;&#9472; github-webhook-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1.</xslthl:number>BUILD-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">20160903.075655</xslthl:number>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2</xslthl:number>-stubs.jar.sha1
&#9500;&#9472;&#9472; github-webhook-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1.</xslthl:number>BUILD-SNAPSHOT.jar
&#9500;&#9472;&#9472; github-webhook-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1.</xslthl:number>BUILD-SNAPSHOT.pom
&#9500;&#9472;&#9472; github-webhook-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1.</xslthl:number>BUILD-SNAPSHOT-stubs.jar
&#9500;&#9472;&#9472; ...
&#9492;&#9472;&#9472; ...</pre><p>There are three possibilities of working with those dependencies so as not to have any
issues with transitive dependencies:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Mark all application dependencies as optional</li><li class="listitem">Create a separate artifactid for the stubs</li><li class="listitem">Exclude dependencies on the consumer side</li></ul></div><p><span class="strong"><strong>Mark all application dependencies as optional</strong></span></p><p>If, in the <code class="literal">github-webhook</code> application, you mark all of your dependencies as optional,
when you include the <code class="literal">github-webhook</code> stubs in another application (or when that
dependency gets downloaded by Stub Runner) then, since all of the dependencies are
optional, they will not get downloaded.</p><p><span class="strong"><strong>Create a separate <code class="literal">artifactid</code> for the stubs</strong></span></p><p>If you create a separate <code class="literal">artifactid</code>, then you can set it up in whatever way you wish.
For example, you might decide to have no dependencies at all.</p><p><span class="strong"><strong>Exclude dependencies on the consumer side</strong></span></p><p>As a consumer, if you add the stub dependency to your classpath, you can explicitly
exclude the unwanted dependencies.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_ci_server_setup" href="#_ci_server_setup"></a>4.4&nbsp;CI Server setup</h2></div></div></div><p>When fetching stubs / contracts in a CI, shared environment, what might happen is that
both the producer and the consumer reuse the same local Maven repository. Due to this,
the framework, responsible for downloading a stub JAR from remote location,
can&#8217;t decide which JAR should be picked, local or remote one. That caused
the <code class="literal">"The artifact was found in the local repository but you have explicitly
stated that it should be downloaded from a remote one"</code> exception
and failed the build.</p><p>For such cases we&#8217;re introducing the property mechanism:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">via <code class="literal">stubrunner.snapshot-check-skip</code> system property</li><li class="listitem">via <code class="literal">STUBRUNNER_SNAPSHOT_CHECK_SKIP</code> environment variable</li></ul></div><p>if either of these values is set to <code class="literal">true</code>, then the stub downloader will not
verify the origin of the downloaded JAR.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_scenarios" href="#_scenarios"></a>4.5&nbsp;Scenarios</h2></div></div></div><p>You can handle scenarios with Spring Cloud Contract Verifier. All you need to do is to
stick to the proper naming convention while creating your contracts. The convention
requires including an order number followed by an underscore. This will work regardles
of whether you&#8217;re working with YAML or Groovy. Example:</p><pre class="screen">my_contracts_dir\
scenario1\
1_login.groovy
2_showCart.groovy
3_logout.groovy</pre><p>Such a tree causes Spring Cloud Contract Verifier to generate WireMock&#8217;s scenario with a
name of <code class="literal">scenario1</code> and the three following steps:</p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem">login marked as <code class="literal">Started</code> pointing to&#8230;&#8203;</li><li class="listitem">showCart marked as <code class="literal">Step1</code> pointing to&#8230;&#8203;</li><li class="listitem">logout marked as <code class="literal">Step2</code> which will close the scenario.</li></ol></div><p>More details about WireMock scenarios can be found at
<a class="link" href="https://wiremock.org/stateful-behaviour.html" target="_top">https://wiremock.org/stateful-behaviour.html</a></p><p>Spring Cloud Contract Verifier also generates tests with a guaranteed order of execution.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="docker-project" href="#docker-project"></a>4.6&nbsp;Docker Project</h2></div></div></div><p>We&#8217;re publishing a <code class="literal">springcloud/spring-cloud-contract</code> Docker image
that contains a project that will generate tests and execute them in <code class="literal">EXPLICIT</code> mode
against a running application.</p><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Tip</th></tr><tr><td align="left" valign="top"><p>The <code class="literal">EXPLICIT</code> mode means that the tests generated from contracts will send
real requests and not the mocked ones.</p></td></tr></table></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_short_intro_to_maven_jars_and_binary_storage" href="#_short_intro_to_maven_jars_and_binary_storage"></a>4.6.1&nbsp;Short intro to Maven, JARs and Binary storage</h3></div></div></div><p>Since the Docker image can be used by non JVM projects, it&#8217;s good to
explain the basic terms behind Spring Cloud Contract packaging defaults.</p><p>Part of the following definitions were taken from the <a class="link" href="https://maven.apache.org/glossary.html" target="_top">Maven Glossary</a></p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">Project</code>: Maven thinks in terms of projects. Everything that you
will build are projects. Those projects follow a well defined
&#8220;Project Object Model&#8221;. Projects can depend on other projects,
in which case the latter are called &#8220;dependencies&#8221;. A project may
consistent of several subprojects, however these subprojects are still
treated equally as projects.</li><li class="listitem"><code class="literal">Artifact</code>: An artifact is something that is either produced or used
by a project. Examples of artifacts produced by Maven for a project
include: JARs, source and binary distributions. Each artifact
is uniquely identified by a group id and an artifact ID which is
unique within a group.</li><li class="listitem"><code class="literal">JAR</code>: JAR stands for Java ARchive. It&#8217;s a format based on
the ZIP file format. Spring Cloud Contract packages the contracts and generated
stubs in a JAR file.</li><li class="listitem"><code class="literal">GroupId</code>: A group ID is a universally unique identifier for a project.
While this is often just the project name (eg. commons-collections),
it is helpful to use a fully-qualified package name to distinguish it
from other projects with a similar name (eg. org.apache.maven).
Typically, when published to the Artifact Manager, the <code class="literal">GroupId</code> will get
slash separated and form part of the URL. E.g. for group id <code class="literal">com.example</code>
and artifact id <code class="literal">application</code> would be <code class="literal">/com/example/application/</code>.</li><li class="listitem"><code class="literal">Classifier</code>: The Maven dependency notation looks as follows:
<code class="literal">groupId:artifactId:version:classifier</code>. The classifier is additional suffix
passed to the dependency. E.g. <code class="literal">stubs</code>, <code class="literal">sources</code>. The same dependency
e.g. <code class="literal">com.example:application</code> can produce multiple artifacts that
differ from each other with the classifier.</li><li class="listitem"><code class="literal">Artifact manager</code>: When you generate binaries / sources / packages, you would
like them to be available for others to download / reference or reuse. In case
of the JVM world those artifacts would be JARs, for Ruby these are gems
and for Docker those would be Docker images. You can store those artifacts
in a manager. Examples of such managers can be <a class="link" href="https://jfrog.com/artifactory/" target="_top">Artifactory</a>
or <a class="link" href="https://www.sonatype.org/nexus/" target="_top">Nexus</a>.</li></ul></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_how_it_works_2" href="#_how_it_works_2"></a>4.6.2&nbsp;How it works</h3></div></div></div><p>The image searches for contracts under the <code class="literal">/contracts</code> folder.
The output from running the tests will be available under
<code class="literal">/spring-cloud-contract/build</code> folder (it&#8217;s useful for debugging
purposes).</p><p>It&#8217;s enough for you to mount your contracts, pass the environment variables
and the image will:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">generate the contract tests</li><li class="listitem">execute the tests against the provided URL</li><li class="listitem">generate the <a class="link" href="https://github.com/tomakehurst/wiremock" target="_top">WireMock</a> stubs</li><li class="listitem">(optional - turned on by default) publish the stubs to a Artifact Manager</li></ul></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_environment_variables" href="#_environment_variables"></a>Environment Variables</h4></div></div></div><p>The Docker image requires some environment variables to point to
your running application, to the Artifact manager instance etc.</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">PROJECT_GROUP</code> - your project&#8217;s group id. Defaults to <code class="literal">com.example</code></li><li class="listitem"><code class="literal">PROJECT_VERSION</code> - your project&#8217;s version. Defaults to <code class="literal">0.0.1-SNAPSHOT</code></li><li class="listitem"><code class="literal">PROJECT_NAME</code> - artifact id. Defaults to <code class="literal">example</code></li><li class="listitem"><code class="literal">REPO_WITH_BINARIES_URL</code> - URL of your Artifact Manager. Defaults to <code class="literal"><a class="link" href="http://localhost:8081/artifactory/libs-release-local" target="_top">http://localhost:8081/artifactory/libs-release-local</a></code>
which is the default URL of <a class="link" href="https://jfrog.com/artifactory/" target="_top">Artifactory</a> running locally</li><li class="listitem"><code class="literal">REPO_WITH_BINARIES_USERNAME</code> - (optional) username when the Artifact Manager is secured</li><li class="listitem"><code class="literal">REPO_WITH_BINARIES_PASSWORD</code> - (optional) password when the Artifact Manager is secured</li><li class="listitem"><code class="literal">PUBLISH_ARTIFACTS</code> - if set to <code class="literal">true</code> then will publish artifact to binary storage. Defaults to <code class="literal">true</code>.</li></ul></div><p>These environment variables are used when contracts lay in an external repository. To enable
this feature you must set the <code class="literal">EXTERNAL_CONTRACTS_ARTIFACT_ID</code> environment variable.</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">EXTERNAL_CONTRACTS_GROUP_ID</code> - group id of the project with contracts. Defaults to <code class="literal">com.example</code></li><li class="listitem"><code class="literal">EXTERNAL_CONTRACTS_ARTIFACT_ID</code>- artifact id of the project with contracts.</li><li class="listitem"><code class="literal">EXTERNAL_CONTRACTS_CLASSIFIER</code>- classifier of the project with contracts. Empty by default</li><li class="listitem"><code class="literal">EXTERNAL_CONTRACTS_VERSION</code> - version of the project with contracts. Defaults to <code class="literal">+</code>, equivalent to picking the latest</li><li class="listitem"><code class="literal">EXTERNAL_CONTRACTS_REPO_WITH_BINARIES_URL</code> - URL of your Artifact Manager. Defaults to value of <code class="literal">REPO_WITH_BINARIES_URL</code> env var.
If that&#8217;s not set, defaults to <code class="literal"><a class="link" href="http://localhost:8081/artifactory/libs-release-local" target="_top">http://localhost:8081/artifactory/libs-release-local</a></code>
which is the default URL of <a class="link" href="https://jfrog.com/artifactory/" target="_top">Artifactory</a> running locally</li><li class="listitem"><code class="literal">EXTERNAL_CONTRACTS_PATH</code> - path to contracts for the given project, inside the project with contracts.
Defaults to slash separated <code class="literal">EXTERNAL_CONTRACTS_GROUP_ID</code> concatenated with <code class="literal">/</code> and <code class="literal">EXTERNAL_CONTRACTS_ARTIFACT_ID</code>. E.g.
for group id <code class="literal">foo.bar</code> and artifact id <code class="literal">baz</code>, would result in <code class="literal">foo/bar/baz</code> contracts path.</li><li class="listitem"><code class="literal">EXTERNAL_CONTRACTS_WORK_OFFLINE</code> - if set to <code class="literal">true</code> then will retrieve artifact with contracts
from the container&#8217;s <code class="literal">.m2</code>. Mount your local <code class="literal">.m2</code> as a volume available at the container&#8217;s <code class="literal">/root/.m2</code> path.
You must not set both <code class="literal">EXTERNAL_CONTRACTS_WORK_OFFLINE</code> and <code class="literal">EXTERNAL_CONTRACTS_REPO_WITH_BINARIES_URL</code>.</li></ul></div><p>These environment variables are used when tests are executed:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">APPLICATION_BASE_URL</code> - url against which tests should be executed.
Remember that it has to be accessible from the Docker container (e.g. <code class="literal">localhost</code>
will not work)</li><li class="listitem"><code class="literal">APPLICATION_USERNAME</code> - (optional) username for basic authentication to your application</li><li class="listitem"><code class="literal">APPLICATION_PASSWORD</code> - (optional) password for basic authentication to your application</li></ul></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_example_of_usage" href="#_example_of_usage"></a>4.6.3&nbsp;Example of usage</h3></div></div></div><p>Let&#8217;s take a look at a simple MVC application</p><pre class="programlisting">$ git clone https://github.com/spring-cloud-samples/spring-cloud-contract-nodejs
$ <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">cd</span> bookstore</pre><p>The contracts are available under <code class="literal">/contracts</code> folder.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="docker-server-side" href="#docker-server-side"></a>4.6.4&nbsp;Server side (nodejs)</h3></div></div></div><p>Since we want to run tests, we could just execute:</p><pre class="programlisting">$ npm <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">test</span></pre><p>however, for learning purposes, let&#8217;s split it into pieces:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"># Stop docker infra (nodejs, artifactory)</span>
$ ./stop_infra.sh
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"># Start docker infra (nodejs, artifactory)</span>
$ ./setup_infra.sh
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"># Kill &amp; Run app</span>
$ pkill -f <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"node app"</span>
$ nohup node app &amp;
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"># Prepare environment variables</span>
$ SC_CONTRACT_DOCKER_VERSION=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"..."</span>
$ APP_IP=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"192.168.0.100"</span>
$ APP_PORT=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"3000"</span>
$ ARTIFACTORY_PORT=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"8081"</span>
$ APPLICATION_BASE_URL=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"http://${APP_IP}:${APP_PORT}"</span>
$ ARTIFACTORY_URL=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"http://${APP_IP}:${ARTIFACTORY_PORT}/artifactory/libs-release-local"</span>
$ CURRENT_DIR=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$( pwd )"</span>
$ CURRENT_FOLDER_NAME=${PWD<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">##*/}</span>
$ PROJECT_VERSION=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"0.0.1.RELEASE"</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"># Execute contract tests</span>
$ docker run --rm -e <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"APPLICATION_BASE_URL=${APPLICATION_BASE_URL}"</span> -e <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"PUBLISH_ARTIFACTS=true"</span> -e <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"PROJECT_NAME=${CURRENT_FOLDER_NAME}"</span> -e <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"REPO_WITH_BINARIES_URL=${ARTIFACTORY_URL}"</span> -e <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"PROJECT_VERSION=${PROJECT_VERSION}"</span> -v <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"${CURRENT_DIR}/contracts/:/contracts:ro"</span> -v <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"${CURRENT_DIR}/node_modules/spring-cloud-contract/output:/spring-cloud-contract-output/"</span> springcloud/spring-cloud-contract:<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"${SC_CONTRACT_DOCKER_VERSION}"</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"># Kill app</span>
$ pkill -f <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"node app"</span></pre><p>What will happen is that via bash scripts:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">infrastructure will be set up (MongoDb, Artifactory).
In real life scenario you would just run the NodeJS application
with mocked database. In this example we want to show how we can
benefit from Spring Cloud Contract in no time.</li><li class="listitem"><p class="simpara">due to those constraints the contracts also represent the
stateful situation</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem">first request is a <code class="literal">POST</code> that causes data to get inserted to the database</li><li class="listitem">second request is a <code class="literal">GET</code> that returns a list of data with 1 previously inserted element</li></ul></div></li><li class="listitem">the NodeJS application will be started (on port <code class="literal">3000</code>)</li><li class="listitem"><p class="simpara">contract tests will be generated via Docker and tests
will be executed against the running application</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem">the contracts will be taken from <code class="literal">/contracts</code> folder.</li><li class="listitem">the output of the test execution is available under
<code class="literal">node_modules/spring-cloud-contract/output</code>.</li></ul></div></li><li class="listitem">the stubs will be uploaded to Artifactory. You can check them out
under <a class="link" href="http://localhost:8081/artifactory/libs-release-local/com/example/bookstore/0.0.1.RELEASE/" target="_top">http://localhost:8081/artifactory/libs-release-local/com/example/bookstore/0.0.1.RELEASE/</a> .
The stubs will be here <a class="link" href="http://localhost:8081/artifactory/libs-release-local/com/example/bookstore/0.0.1.RELEASE/bookstore-0.0.1.RELEASE-stubs.jar" target="_top">http://localhost:8081/artifactory/libs-release-local/com/example/bookstore/0.0.1.RELEASE/bookstore-0.0.1.RELEASE-stubs.jar</a>.</li></ul></div><p>To see how the client side looks like check out the <a class="xref" href="multi__spring_cloud_contract_stub_runner.html#stubrunner-docker" title="6.9&nbsp;Stub Runner Docker">Section&nbsp;6.9, &#8220;Stub Runner Docker&#8221;</a> section.</p></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__spring_cloud_contract_faq.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi__spring_cloud_contract_verifier_messaging.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">3.&nbsp;Spring Cloud Contract FAQ&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-contract.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;5.&nbsp;Spring Cloud Contract Verifier Messaging</td></tr></table></div></body></html>

View File

@@ -0,0 +1,290 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>11.&nbsp;Spring Cloud Contract WireMock</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud-contract.html" title="Spring Cloud Contract"><link rel="up" href="multi_spring-cloud-contract.html" title="Spring Cloud Contract"><link rel="prev" href="multi__using_the_pluggable_architecture.html" title="10.&nbsp;Using the Pluggable Architecture"><link rel="next" href="multi__migrations.html" title="12.&nbsp;Migrations"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">11.&nbsp;Spring Cloud Contract WireMock</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__using_the_pluggable_architecture.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi__migrations.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_spring_cloud_contract_wiremock" href="#_spring_cloud_contract_wiremock"></a>11.&nbsp;Spring Cloud Contract WireMock</h1></div></div></div><p>The Spring Cloud Contract WireMock modules let you use <a class="link" href="https://github.com/tomakehurst/wiremock" target="_top">WireMock</a> in a
Spring Boot application. Check out the
<a class="link" href="https://github.com/spring-cloud/spring-cloud-contract/tree/1.2.x/samples" target="_top">samples</a>
for more details.</p><p>If you have a Spring Boot application that uses Tomcat as an embedded server (which is
the default with <code class="literal">spring-boot-starter-web</code>), you can add
<code class="literal">spring-cloud-starter-contract-stub-runner</code> to your classpath and add <code class="literal">@AutoConfigureWireMock</code> in
order to be able to use Wiremock in your tests. Wiremock runs as a stub server and you
can register stub behavior using a Java API or via static JSON declarations as part of
your test. The following code shows an example:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RunWith(SpringRunner.class)</xslthl:annotation>
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)</xslthl:annotation>
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@AutoConfigureWireMock(port = 0)</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> WiremockForDocsTests {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// A service that calls out over HTTP</span>
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Autowired</xslthl:annotation> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> Service service;
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Using the WireMock APIs in the normal way:</span>
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Test</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> contextLoads() <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> Exception {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Stubbing WireMock</span>
stubFor(get(urlEqualTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/resource"</span>))
.willReturn(aResponse().withHeader(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Content-Type"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"text/plain"</span>).withBody(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Hello World!"</span>)));
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// We're asserting if WireMock responded properly</span>
assertThat(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.service.go()).isEqualTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Hello World!"</span>);
}
}</pre><p>To start the stub server on a different port use (for example),
<code class="literal">@AutoConfigureWireMock(port=9999)</code>. For a random port, use a value of <code class="literal">0</code>. The stub
server port can be bound in the test application context with the "wiremock.server.port"
property. Using <code class="literal">@AutoConfigureWireMock</code> adds a bean of type <code class="literal">WiremockConfiguration</code> to
your test application context, where it will be cached in between methods and classes
having the same context, the same as for Spring integration tests.</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_registering_stubs_automatically" href="#_registering_stubs_automatically"></a>11.1&nbsp;Registering Stubs Automatically</h2></div></div></div><p>If you use <code class="literal">@AutoConfigureWireMock</code>, it registers WireMock JSON stubs from the file
system or classpath (by default, from <code class="literal">file:src/test/resources/mappings</code>). You can
customize the locations using the <code class="literal">stubs</code> attribute in the annotation, which can be an
Ant-style resource pattern or a directory. In the case of a directory, <code class="literal"><span class="strong"><strong>*/</strong></span>.json</code> is
appended. The following code shows an example:</p><pre class="screen">@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureWireMock(stubs="classpath:/stubs")
public class WiremockImportApplicationTests {
@Autowired
private Service service;
@Test
public void contextLoads() throws Exception {
assertThat(this.service.go()).isEqualTo("Hello World!");
}
}</pre><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>Actually, WireMock always loads mappings from <code class="literal">src/test/resources/mappings</code> <span class="strong"><strong>as
well as</strong></span> the custom locations in the stubs attribute. To change this behavior, you can
also specify a files root as described in the next section of this document.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_using_files_to_specify_the_stub_bodies" href="#_using_files_to_specify_the_stub_bodies"></a>11.2&nbsp;Using Files to Specify the Stub Bodies</h2></div></div></div><p>WireMock can read response bodies from files on the classpath or the file system. In that
case, you can see in the JSON DSL that the response has a <code class="literal">bodyFileName</code> instead of a
(literal) <code class="literal">body</code>. The files are resolved relative to a root directory (by default,
<code class="literal">src/test/resources/__files</code>). To customize this location you can set the <code class="literal">files</code>
attribute in the <code class="literal">@AutoConfigureWireMock</code> annotation to the location of the parent
directory (in other words, <code class="literal">__files</code> is a subdirectory). You can use Spring resource
notation to refer to <code class="literal">file:&#8230;&#8203;</code> or <code class="literal">classpath:&#8230;&#8203;</code> locations. Generic URLs are not
supported. A list of values can be given, in which case WireMock resolves the first file
that exists when it needs to find a response body.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>When you configure the <code class="literal">files</code> root, it also affects the
automatic loading of stubs, because they come from the root location
in a subdirectory called "mappings". The value of <code class="literal">files</code> has no
effect on the stubs loaded explicitly from the <code class="literal">stubs</code> attribute.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_alternative_using_junit_rules" href="#_alternative_using_junit_rules"></a>11.3&nbsp;Alternative: Using JUnit Rules</h2></div></div></div><p>For a more conventional WireMock experience, you can use JUnit <code class="literal">@Rules</code> to start and stop
the server. To do so, use the <code class="literal">WireMockSpring</code> convenience class to obtain an <code class="literal">Options</code>
instance, as shown in the following example:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RunWith(SpringRunner.class)</xslthl:annotation>
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> WiremockForDocsClassRuleTests {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Start WireMock on some dynamic port</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// for some reason `dynamicPort()` is not working properly</span>
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@ClassRule</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> WireMockClassRule wiremock = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> WireMockClassRule(
WireMockSpring.options().dynamicPort());
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// A service that calls out over HTTP to localhost:${wiremock.port}</span>
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Autowired</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> Service service;
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Using the WireMock APIs in the normal way:</span>
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Test</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> contextLoads() <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> Exception {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Stubbing WireMock</span>
wiremock.stubFor(get(urlEqualTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/resource"</span>))
.willReturn(aResponse().withHeader(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Content-Type"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"text/plain"</span>).withBody(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Hello World!"</span>)));
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// We're asserting if WireMock responded properly</span>
assertThat(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.service.go()).isEqualTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Hello World!"</span>);
}
}</pre><p>The <code class="literal">@ClassRule</code> means that the server shuts down after all the methods in this class
have been run.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_relaxed_ssl_validation_for_rest_template" href="#_relaxed_ssl_validation_for_rest_template"></a>11.4&nbsp;Relaxed SSL Validation for Rest Template</h2></div></div></div><p>WireMock lets you stub a "secure" server with an "https" URL protocol. If your
application wants to contact that stub server in an integration test, it will find that
the SSL certificates are not valid (the usual problem with self-installed certificates).
The best option is often to re-configure the client to use "http". If that&#8217;s not an
option, you can ask Spring to configure an HTTP client that ignores SSL validation errors
(do so only for tests, of course).</p><p>To make this work with minimum fuss, you need to be using the Spring Boot
<code class="literal">RestTemplateBuilder</code> in your app, as shown in the following example:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Bean</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> RestTemplate restTemplate(RestTemplateBuilder builder) {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> builder.build();
}</pre><p>You need <code class="literal">RestTemplateBuilder</code> because the builder is passed through callbacks to
initialize it, so the SSL validation can be set up in the client at that point. This
happens automatically in your test if you are using the <code class="literal">@AutoConfigureWireMock</code>
annotation or the stub runner. If you use the JUnit <code class="literal">@Rule</code> approach, you need to add the
<code class="literal">@AutoConfigureHttpClient</code> annotation as well, as shown in the following example:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RunWith(SpringRunner.class)</xslthl:annotation>
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootTest("app.baseUrl=https://localhost:6443")</xslthl:annotation>
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@AutoConfigureHttpClient</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> WiremockHttpsServerApplicationTests {
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@ClassRule</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> WireMockClassRule wiremock = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> WireMockClassRule(
WireMockSpring.options().httpsPort(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">6443</xslthl:number>));
...
}</pre><p>If you are using <code class="literal">spring-boot-starter-test</code>, you have the Apache HTTP client on the
classpath and it is selected by the <code class="literal">RestTemplateBuilder</code> and configured to ignore SSL
errors. If you use the default <code class="literal">java.net</code> client, you do not need the annotation (but it
won&#8217;t do any harm). There is no support currently for other clients, but it may be added
in future releases.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_wiremock_and_spring_mvc_mocks" href="#_wiremock_and_spring_mvc_mocks"></a>11.5&nbsp;WireMock and Spring MVC Mocks</h2></div></div></div><p>Spring Cloud Contract provides a convenience class that can load JSON WireMock stubs into
a Spring <code class="literal">MockRestServiceServer</code>. The following code shows an example:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RunWith(SpringRunner.class)</xslthl:annotation>
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootTest(webEnvironment = WebEnvironment.NONE)</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> WiremockForDocsMockServerApplicationTests {
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Autowired</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> RestTemplate restTemplate;
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Autowired</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> Service service;
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Test</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> contextLoads() <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> Exception {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// will read stubs classpath</span>
MockRestServiceServer server = WireMockRestServiceServer.with(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.restTemplate)
.baseUrl(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"https://example.org"</span>).stubs(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"classpath:/stubs/resource.json"</span>)
.build();
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// We're asserting if WireMock responded properly</span>
assertThat(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.service.go()).isEqualTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Hello World"</span>);
server.verify();
}
}</pre><p>The <code class="literal">baseUrl</code> value is prepended to all mock calls, and the <code class="literal">stubs()</code> method takes a stub
path resource pattern as an argument. In the preceding example, the stub defined at
<code class="literal">/stubs/resource.json</code> is loaded into the mock server. If the <code class="literal">RestTemplate</code> is asked to
visit <code class="literal"><a class="link" href="https://example.org/" target="_top">https://example.org/</a></code>, it gets the responses as being declared at that URL. More
than one stub pattern can be specified, and each one can be a directory (for a recursive
list of all ".json"), a fixed filename (as in the example above), or an Ant-style
pattern. The JSON format is the normal WireMock format, which you can read about in the
<a class="link" href="https://wiremock.org/docs/stubbing/" target="_top">WireMock website</a>.</p><p>Currently, the Spring Cloud Contract Verifier supports Tomcat, Jetty, and Undertow as
Spring Boot embedded servers, and Wiremock itself has "native" support for a particular
version of Jetty (currently 9.2). To use the native Jetty, you need to add the native
Wiremock dependencies and exclude the Spring Boot container (if there is one).</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_customization_of_wiremock_configuration" href="#_customization_of_wiremock_configuration"></a>11.6&nbsp;Customization of WireMock configuration</h2></div></div></div><p>You can register a bean of <code class="literal">org.springframework.cloud.contract.wiremock.WireMockConfigurationCustomizer</code> type
in order to customize the WireMock configuration (e.g. add custom transformers).
Example:</p><pre class="programlisting"> <xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Bean</xslthl:annotation> WireMockConfigurationCustomizer optionsCustomizer() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> WireMockConfigurationCustomizer() {
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> customize(WireMockConfiguration options) {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// perform your customization here</span>
}
};
}</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_generating_stubs_using_rest_docs" href="#_generating_stubs_using_rest_docs"></a>11.7&nbsp;Generating Stubs using REST Docs</h2></div></div></div><p><a class="link" href="https://projects.spring.io/spring-restdocs" target="_top">Spring REST Docs</a> can be used to generate
documentation (for example in Asciidoctor format) for an HTTP API with Spring MockMvc or
Rest Assured. At the same time that you generate documentation for your API, you can also
generate WireMock stubs by using Spring Cloud Contract WireMock. To do so, write your
normal REST Docs test cases and use <code class="literal">@AutoConfigureRestDocs</code> to have stubs be
automatically generated in the REST Docs output directory. The following code shows an
example:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RunWith(SpringRunner.class)</xslthl:annotation>
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootTest</xslthl:annotation>
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@AutoConfigureRestDocs(outputDir = "target/snippets")</xslthl:annotation>
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@AutoConfigureMockMvc</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> ApplicationTests {
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Autowired</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> MockMvc mockMvc;
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Test</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> contextLoads() <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> Exception {
mockMvc.perform(get(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/resource"</span>))
.andExpect(content().string(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Hello World"</span>))
.andDo(document(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"resource"</span>));
}
}</pre><p>This test generates a WireMock stub at "target/snippets/stubs/resource.json". It matches
all GET requests to the "/resource" path.</p><p>Without any additional configuration, this tests creates a stub with a request matcher
for the HTTP method and all headers except "host" and "content-length". To match the
request more precisely (for example, to match the body of a POST or PUT), we need to
explicitly create a request matcher. Doing so has two effects:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Creating a stub that matches only in the way you specify.</li><li class="listitem">Asserting that the request in the test case also matches the same conditions.</li></ul></div><p>The main entry point for this feature is <code class="literal">WireMockRestDocs.verify()</code>, which can be used
as a substitute for the <code class="literal">document()</code> convenience method, as shown in the following
example:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RunWith(SpringRunner.class)</xslthl:annotation>
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootTest</xslthl:annotation>
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@AutoConfigureRestDocs(outputDir = "target/snippets")</xslthl:annotation>
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@AutoConfigureMockMvc</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> ApplicationTests {
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Autowired</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> MockMvc mockMvc;
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Test</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> contextLoads() <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> Exception {
mockMvc.perform(post(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/resource"</span>)
.content(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"{\"id\":\"123456\",\"message\":\"Hello World\"}"</span>))
.andExpect(status().isOk())
.andDo(verify().jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.id"</span>)
.stub(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"resource"</span>));
}
}</pre><p>This contract specifies that any valid POST with an "id" field receives the response
defined in this test. You can chain together calls to <code class="literal">.jsonPath()</code> to add additional
matchers. If JSON Path is unfamiliar, The <a class="link" href="https://github.com/jayway/JsonPath" target="_top">JayWay
documentation</a> can help you get up to speed.</p><p>Instead of the <code class="literal">jsonPath</code> and <code class="literal">contentType</code> convenience methods, you can also use the
WireMock APIs to verify that the request matches the created stub, as shown in the
following example:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Test</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> contextLoads() <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> Exception {
mockMvc.perform(post(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/resource"</span>)
.content(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"{\"id\":\"123456\",\"message\":\"Hello World\"}"</span>))
.andExpect(status().isOk())
.andDo(verify()
.wiremock(WireMock.post(
urlPathEquals(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/resource"</span>))
.withRequestBody(matchingJsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.id"</span>))
.stub(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"post-resource"</span>));
}</pre><p>The WireMock API is rich. You can match headers, query parameters, and request body by
regex as well as by JSON path. These features can be used to create stubs with a wider
range of parameters. The above example generates a stub resembling the following example:</p><p><b>post-resource.json.&nbsp;</b>
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"request"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"url"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/resource"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"method"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"POST"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"bodyPatterns"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">[</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matchesJsonPath"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.id"</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}]</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"response"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"status"</span> : <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"body"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Hello World"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"headers"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"X-Application-Context"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"application:-1"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Content-Type"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"text/plain"</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span></pre><p>
</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>You can use either the <code class="literal">wiremock()</code> method or the <code class="literal">jsonPath()</code> and <code class="literal">contentType()</code>
methods to create request matchers, but you can&#8217;t use both approaches.</p></td></tr></table></div><p>On the consumer side, you can make the <code class="literal">resource.json</code> generated earlier in this section
available on the classpath (by
<a class="link" href="https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html#_publishing_stubs_as_jars" target="_top">publishing
stubs as JARs</a>, for example). After that, you can create a stub using WireMock in a
number of different ways, including by using
<code class="literal">@AutoConfigureWireMock(stubs="classpath:resource.json")</code>, as described earlier in this
document.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_generating_contracts_by_using_rest_docs" href="#_generating_contracts_by_using_rest_docs"></a>11.8&nbsp;Generating Contracts by Using REST Docs</h2></div></div></div><p>You can also generate Spring Cloud Contract DSL files and documentation with Spring REST
Docs. If you do so in combination with Spring Cloud WireMock, you get both the contracts
and the stubs.</p><p>Why would you want to use this feature? Some people in the community asked questions
about a situation in which they would like to move to DSL-based contract definition,
but they already have a lot of Spring MVC tests. Using this feature lets you generate
the contract files that you can later modify and move to folders (defined in your
configuration) so that the plugin finds them.</p><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Tip</th></tr><tr><td align="left" valign="top"><p>You might wonder why this functionality is in the WireMock module. The functionality
is there because it makes sense to generate both the contracts and the stubs.</p></td></tr></table></div><p>Consider the following test:</p><pre class="programlisting"> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.mockMvc.perform(post(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/foo"</span>)
.accept(MediaType.APPLICATION_PDF)
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
.content(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"{\"foo\": 23, \"bar\" : \"baz\" }"</span>))
.andExpect(status().isOk())
.andExpect(content().string(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"bar"</span>))
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// first WireMock</span>
.andDo(WireMockRestDocs.verify()
.jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$[?(@.foo &gt;= 20)]"</span>)
.jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$[?(@.bar in ['baz','bazz','bazzz'])]"</span>)
.contentType(MediaType.valueOf(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"application/json"</span>))
.stub(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"shouldGrantABeerIfOldEnough"</span>))
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// then Contract DSL documentation</span>
.andDo(document(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"index"</span>, SpringCloudContractRestDocs.dslContract()));</pre><p>The preceding test creates the stub presented in the previous section, generating both
the contract and a documentation file.</p><p>The contract is called <code class="literal">index.groovy</code> and might look like the following example:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.cloud.contract.spec.Contract
Contract.make {
request {
method <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'POST'</span>
url <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'/foo'</span>
body(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'
</span> {<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"foo"</span>: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">23</xslthl:number> }
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">')
</span> headers {
header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'Accept'</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'application/json'</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span>)
header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'Content-Type'</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'application/json'</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span>)
}
}
response {
status <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>
body(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'
</span> bar
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">')
</span> headers {
header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'Content-Type'</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'application/json;charset=UTF-8'</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span>)
header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'Content-Length'</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'3'</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span>)
}
testMatchers {
jsonPath(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'$[?(@.foo &gt;= 20)]'</span>, byType())
}
}
}</pre><p>The generated document (formatted in Asciidoc in this case) contains a formatted
contract. The location of this file would be <code class="literal">index/dsl-contract.adoc</code>.</p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__using_the_pluggable_architecture.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi__migrations.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">10.&nbsp;Using the Pluggable Architecture&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-contract.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;12.&nbsp;Migrations</td></tr></table></div></body></html>

View File

@@ -0,0 +1,354 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>7.&nbsp;Stub Runner for Messaging</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud-contract.html" title="Spring Cloud Contract"><link rel="up" href="multi_spring-cloud-contract.html" title="Spring Cloud Contract"><link rel="prev" href="multi__spring_cloud_contract_stub_runner.html" title="6.&nbsp;Spring Cloud Contract Stub Runner"><link rel="next" href="multi__contract_dsl.html" title="8.&nbsp;Contract DSL"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">7.&nbsp;Stub Runner for Messaging</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__spring_cloud_contract_stub_runner.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi__contract_dsl.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_stub_runner_for_messaging" href="#_stub_runner_for_messaging"></a>7.&nbsp;Stub Runner for Messaging</h1></div></div></div><p>Stub Runner can run the published stubs in memory. It can integrate with the following
frameworks:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Spring Integration</li><li class="listitem">Spring Cloud Stream</li><li class="listitem">Apache Camel</li><li class="listitem">Spring AMQP</li></ul></div><p>It also provides entry points to integrate with any other solution on the market.</p><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>If you have multiple frameworks on the classpath Stub Runner will need to
define which one should be used. Let&#8217;s assume that you have both AMQP, Spring Cloud Stream and Spring Integration
on the classpath. Then you need to set <code class="literal">stubrunner.stream.enabled=false</code> and <code class="literal">stubrunner.integration.enabled=false</code>.
That way the only remaining framework is Spring AMQP.</p></td></tr></table></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_stub_triggering" href="#_stub_triggering"></a>7.1&nbsp;Stub triggering</h2></div></div></div><p>To trigger a message, use the <code class="literal">StubTrigger</code> interface:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">package</span> org.springframework.cloud.contract.stubrunner;
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> java.util.Collection;
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> java.util.Map;
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">interface</span> StubTrigger {
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
* Triggers an event by a given label for a given {@code groupid:artifactid} notation. You can use only {@code artifactId} too.
*
* Feature related to messaging.
*
* @return true - if managed to run a trigger
*/</xslthl:doccomment>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">boolean</span> trigger(String ivyNotation, String labelName);
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
* Triggers an event by a given label.
*
* Feature related to messaging.
*
* @return true - if managed to run a trigger
*/</xslthl:doccomment>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">boolean</span> trigger(String labelName);
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
* Triggers all possible events.
*
* Feature related to messaging.
*
* @return true - if managed to run a trigger
*/</xslthl:doccomment>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">boolean</span> trigger();
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
* Returns a mapping of ivy notation of a dependency to all the labels it has.
*
* Feature related to messaging.
*/</xslthl:doccomment>
Map&lt;String, Collection&lt;String&gt;&gt; labels();
}</pre><p>For convenience, the <code class="literal">StubFinder</code> interface extends <code class="literal">StubTrigger</code>, so you only need one
or the other in your tests.</p><p><code class="literal">StubTrigger</code> gives you the following options to trigger a message:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a class="xref" href="multi__stub_runner_for_messaging.html#trigger-label" title="7.1.1&nbsp;Trigger by Label">Section&nbsp;7.1.1, &#8220;Trigger by Label&#8221;</a></li><li class="listitem"><a class="xref" href="multi__stub_runner_for_messaging.html#trigger-group-artifact-ids" title="7.1.2&nbsp;Trigger by Group and Artifact Ids">Section&nbsp;7.1.2, &#8220;Trigger by Group and Artifact Ids&#8221;</a></li><li class="listitem"><a class="xref" href="multi__stub_runner_for_messaging.html#trigger-artifact-ids" title="7.1.3&nbsp;Trigger by Artifact Ids">Section&nbsp;7.1.3, &#8220;Trigger by Artifact Ids&#8221;</a></li><li class="listitem"><a class="xref" href="multi__stub_runner_for_messaging.html#trigger-all-messages" title="7.1.4&nbsp;Trigger All Messages">Section&nbsp;7.1.4, &#8220;Trigger All Messages&#8221;</a></li></ul></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="trigger-label" href="#trigger-label"></a>7.1.1&nbsp;Trigger by Label</h3></div></div></div><pre class="programlisting">stubFinder.trigger(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'return_book_1'</span>)</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="trigger-group-artifact-ids" href="#trigger-group-artifact-ids"></a>7.1.2&nbsp;Trigger by Group and Artifact Ids</h3></div></div></div><pre class="programlisting">stubFinder.trigger(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'org.springframework.cloud.contract.verifier.stubs:camelService'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'return_book_1'</span>)</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="trigger-artifact-ids" href="#trigger-artifact-ids"></a>7.1.3&nbsp;Trigger by Artifact Ids</h3></div></div></div><pre class="programlisting">stubFinder.trigger(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'camelService'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'return_book_1'</span>)</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="trigger-all-messages" href="#trigger-all-messages"></a>7.1.4&nbsp;Trigger All Messages</h3></div></div></div><pre class="programlisting">stubFinder.trigger()</pre></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_stub_runner_camel" href="#_stub_runner_camel"></a>7.2&nbsp;Stub Runner Camel</h2></div></div></div><p>Spring Cloud Contract Verifier Stub Runner&#8217;s messaging module gives you an easy way to
integrate with Apache Camel. For the provided artifacts, it automatically downloads the
stubs and registers the required routes.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_adding_the_runner_to_the_project" href="#_adding_the_runner_to_the_project"></a>7.2.1&nbsp;Adding the Runner to the Project</h3></div></div></div><p>You can have both Apache Camel and Spring Cloud Contract Stub Runner on the classpath.
Remember to annotate your test class with <code class="literal">@AutoConfigureStubRunner</code>.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_disabling_the_functionality" href="#_disabling_the_functionality"></a>7.2.2&nbsp;Disabling the functionality</h3></div></div></div><p>If you need to disable this functionality, set the <code class="literal">stubrunner.camel.enabled=false</code>
property.</p><p>Assume that you have the following Maven repository with deployed stubs for the
<code class="literal">camelService</code> application:</p><pre class="programlisting">&#9492;&#9472;&#9472; .m2
&#9492;&#9472;&#9472; repository
&#9492;&#9472;&#9472; io
&#9492;&#9472;&#9472; codearte
&#9492;&#9472;&#9472; accurest
&#9492;&#9472;&#9472; stubs
&#9492;&#9472;&#9472; camelService
&#9500;&#9472;&#9472; <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT
&#9474;&nbsp;&nbsp; &#9500;&#9472;&#9472; camelService-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT.pom
&#9474;&nbsp;&nbsp; &#9500;&#9472;&#9472; camelService-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT-stubs.jar
&#9474;&nbsp;&nbsp; &#9492;&#9472;&#9472; maven-metadata-local.xml
&#9492;&#9472;&#9472; maven-metadata-local.xml</pre><p>Further assume that the stubs contain the following structure:</p><pre class="programlisting">&#9500;&#9472;&#9472; META-INF
&#9474;&nbsp;&nbsp; &#9492;&#9472;&#9472; MANIFEST.MF
&#9492;&#9472;&#9472; repository
&#9500;&#9472;&#9472; accurest
&#9474;&nbsp;&nbsp; &#9500;&#9472;&#9472; bookDeleted.groovy
&#9474;&nbsp;&nbsp; &#9500;&#9472;&#9472; bookReturned1.groovy
&#9474;&nbsp;&nbsp; &#9492;&#9472;&#9472; bookReturned2.groovy
&#9492;&#9472;&#9472; mappings</pre><p>Consider the following contracts (numbered <span class="strong"><strong>1</strong></span>):</p><pre class="programlisting">Contract.make {
label <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'return_book_1'</span>
input {
triggeredBy(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'bookReturnedTriggered()'</span>)
}
outputMessage {
sentTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'jms:output'</span>)
body(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'{ "bookName" : "foo" }'</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span>)
headers {
header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'BOOK-NAME'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span>)
}
}
}</pre><p>Now consider <span class="strong"><strong>2</strong></span></p><pre class="programlisting">Contract.make {
label <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'return_book_2'</span>
input {
messageFrom(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'jms:input'</span>)
messageBody([
bookName: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span>
])
messageHeaders {
header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'sample'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'header'</span>)
}
}
outputMessage {
sentTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'jms:output'</span>)
body([
bookName: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span>
])
headers {
header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'BOOK-NAME'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span>)
}
}
}</pre><p>These examples lend themselves to three scenarios:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a class="xref" href="multi__stub_runner_for_messaging.html#camel-scenario-1" title="Scenario 1 (no input message)">the section called &#8220;Scenario 1 (no input message)&#8221;</a></li><li class="listitem"><a class="xref" href="multi__stub_runner_for_messaging.html#camel-scenario-2" title="Scenario 2 (output triggered by input)">the section called &#8220;Scenario 2 (output triggered by input)&#8221;</a></li><li class="listitem"><a class="xref" href="multi__stub_runner_for_messaging.html#camel-scenario-3" title="Scenario 3 (input with no output)">the section called &#8220;Scenario 3 (input with no output)&#8221;</a></li></ul></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="camel-scenario-1" href="#camel-scenario-1"></a>Scenario 1 (no input message)</h4></div></div></div><p>To trigger a message via the <code class="literal">return_book_1</code> label, use the <code class="literal">StubTigger</code> interface, as
follows:</p><pre class="programlisting">stubFinder.trigger(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'return_book_1'</span>)</pre><p>To listen to the output of the message sent to <code class="literal">jms:output</code>:</p><pre class="programlisting">Exchange receivedMessage = camelContext.createConsumerTemplate().receive(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'jms:output'</span>, <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">5000</xslthl:number>)</pre><p>The received message passes the following assertions:</p><pre class="programlisting">receivedMessage != null
assertThatBodyContainsBookNameFoo(receivedMessage.in.body)
receivedMessage.in.headers.get(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'BOOK-NAME'</span>) == <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span></pre></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="camel-scenario-2" href="#camel-scenario-2"></a>Scenario 2 (output triggered by input)</h4></div></div></div><p>Since the route is set for you, you can send a message to the <code class="literal">jms:output</code>
destination:</p><pre class="programlisting">camelContext.createProducerTemplate().sendBodyAndHeaders(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'jms:input'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> BookReturned(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span>), [sample: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'header'</span>])</pre><p>You can listen to the output of the message sent to <code class="literal">jms:output</code>:</p><pre class="programlisting">Exchange receivedMessage = camelContext.createConsumerTemplate().receive(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'jms:output'</span>, <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">5000</xslthl:number>)</pre><p>The received message passes the following assertions:</p><pre class="programlisting">receivedMessage != null
assertThatBodyContainsBookNameFoo(receivedMessage.in.body)
receivedMessage.in.headers.get(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'BOOK-NAME'</span>) == <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span></pre></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="camel-scenario-3" href="#camel-scenario-3"></a>Scenario 3 (input with no output)</h4></div></div></div><p>Since the route is set for you, you can send a message to the <code class="literal">jms:output</code>
destination:</p><pre class="programlisting">camelContext.createProducerTemplate().sendBodyAndHeaders(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'jms:delete'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> BookReturned(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span>), [sample: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'header'</span>])</pre></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_stub_runner_integration" href="#_stub_runner_integration"></a>7.3&nbsp;Stub Runner Integration</h2></div></div></div><p>Spring Cloud Contract Verifier Stub Runner&#8217;s messaging module gives you an easy way to
integrate with Spring Integration. For the provided artifacts, it automatically downloads
the stubs and registers the required routes.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_adding_the_runner_to_the_project_2" href="#_adding_the_runner_to_the_project_2"></a>7.3.1&nbsp;Adding the Runner to the Project</h3></div></div></div><p>You can have both Spring Integration and Spring Cloud Contract Stub Runner on the
classpath. Remember to annotate your test class with <code class="literal">@AutoConfigureStubRunner</code>.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_disabling_the_functionality_2" href="#_disabling_the_functionality_2"></a>7.3.2&nbsp;Disabling the functionality</h3></div></div></div><p>If you need to disable this functionality, set the
<code class="literal">stubrunner.integration.enabled=false</code> property.</p><p>Assume that you have the following Maven repository with deployed stubs for the
<code class="literal">integrationService</code> application:</p><pre class="programlisting">&#9492;&#9472;&#9472; .m2
&#9492;&#9472;&#9472; repository
&#9492;&#9472;&#9472; io
&#9492;&#9472;&#9472; codearte
&#9492;&#9472;&#9472; accurest
&#9492;&#9472;&#9472; stubs
&#9492;&#9472;&#9472; integrationService
&#9500;&#9472;&#9472; <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT
&#9474;&nbsp;&nbsp; &#9500;&#9472;&#9472; integrationService-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT.pom
&#9474;&nbsp;&nbsp; &#9500;&#9472;&#9472; integrationService-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT-stubs.jar
&#9474;&nbsp;&nbsp; &#9492;&#9472;&#9472; maven-metadata-local.xml
&#9492;&#9472;&#9472; maven-metadata-local.xml</pre><p>Further assume the stubs contain the following structure:</p><pre class="programlisting">&#9500;&#9472;&#9472; META-INF
&#9474;&nbsp;&nbsp; &#9492;&#9472;&#9472; MANIFEST.MF
&#9492;&#9472;&#9472; repository
&#9500;&#9472;&#9472; accurest
&#9474;&nbsp;&nbsp; &#9500;&#9472;&#9472; bookDeleted.groovy
&#9474;&nbsp;&nbsp; &#9500;&#9472;&#9472; bookReturned1.groovy
&#9474;&nbsp;&nbsp; &#9492;&#9472;&#9472; bookReturned2.groovy
&#9492;&#9472;&#9472; mappings</pre><p>Consider the following contracts (numbered <span class="strong"><strong>1</strong></span>):</p><pre class="programlisting">Contract.make {
label <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'return_book_1'</span>
input {
triggeredBy(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'bookReturnedTriggered()'</span>)
}
outputMessage {
sentTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'output'</span>)
body(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'{ "bookName" : "foo" }'</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span>)
headers {
header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'BOOK-NAME'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span>)
}
}
}</pre><p>Now consider <span class="strong"><strong>2</strong></span>:</p><pre class="programlisting">Contract.make {
label <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'return_book_2'</span>
input {
messageFrom(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'input'</span>)
messageBody([
bookName: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span>
])
messageHeaders {
header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'sample'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'header'</span>)
}
}
outputMessage {
sentTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'output'</span>)
body([
bookName: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span>
])
headers {
header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'BOOK-NAME'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span>)
}
}
}</pre><p>and the following Spring Integration Route:</p><pre class="programlisting"><xslthl:directive xmlns:xslthl="http://xslthl.sourceforge.net/">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</xslthl:directive>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;beans:beans</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">xmlns</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"http://www.springframework.org/schema/integration"</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">xmlns:xsi</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"http://www.w3.org/2001/XMLSchema-instance"</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">xmlns:beans</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"http://www.springframework.org/schema/beans"</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">xsi:schemaLocation</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration
https://www.springframework.org/schema/integration/spring-integration.xsd"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">&lt;!-- REQUIRED FOR TESTING --&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;bridge</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">input-channel</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"output"</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">output-channel</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"outputTest"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">/&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;channel</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">id</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"outputTest"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;queue/&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/channel&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/beans:beans&gt;</span></pre><p>These examples lend themselves to three scenarios:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a class="xref" href="multi__stub_runner_for_messaging.html#integration-scenario-1" title="Scenario 1 (no input message)">the section called &#8220;Scenario 1 (no input message)&#8221;</a></li><li class="listitem"><a class="xref" href="">???</a></li><li class="listitem"><a class="xref" href="multi__stub_runner_for_messaging.html#integration-scenario-3" title="Scenario 3 (input with no output)">the section called &#8220;Scenario 3 (input with no output)&#8221;</a></li></ul></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="integration-scenario-1" href="#integration-scenario-1"></a>Scenario 1 (no input message)</h4></div></div></div><p>To trigger a message via the <code class="literal">return_book_1</code> label, use the <code class="literal">StubTigger</code> interface, as
follows:</p><pre class="programlisting">stubFinder.trigger(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'return_book_1'</span>)</pre><p>To listen to the output of the message sent to <code class="literal">output</code>:</p><pre class="programlisting">Message&lt;?&gt; receivedMessage = messaging.receive(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'outputTest'</span>)</pre><p>The received message would pass the following assertions:</p><pre class="programlisting">receivedMessage != null
assertJsons(receivedMessage.payload)
receivedMessage.headers.get(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'BOOK-NAME'</span>) == <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span></pre></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="integration-scenario-1" href="#integration-scenario-1"></a>Scenario 2 (output triggered by input)</h4></div></div></div><p>Since the route is set for you, you can send a message to the <code class="literal">output</code>
destination:</p><pre class="programlisting">messaging.send(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> BookReturned(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span>), [sample: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'header'</span>], <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'input'</span>)</pre><p>To listen to the output of the message sent to <code class="literal">output</code>:</p><pre class="programlisting">Message&lt;?&gt; receivedMessage = messaging.receive(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'outputTest'</span>)</pre><p>The received message passes the following assertions:</p><pre class="programlisting">receivedMessage != null
assertJsons(receivedMessage.payload)
receivedMessage.headers.get(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'BOOK-NAME'</span>) == <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span></pre></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="integration-scenario-3" href="#integration-scenario-3"></a>Scenario 3 (input with no output)</h4></div></div></div><p>Since the route is set for you, you can send a message to the <code class="literal">input</code> destination:</p><pre class="programlisting">messaging.send(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> BookReturned(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span>), [sample: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'header'</span>], <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'delete'</span>)</pre></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_stub_runner_stream" href="#_stub_runner_stream"></a>7.4&nbsp;Stub Runner Stream</h2></div></div></div><p>Spring Cloud Contract Verifier Stub Runner&#8217;s messaging module gives you an easy way to
integrate with Spring Stream. For the provided artifacts, it automatically downloads the
stubs and registers the required routes.</p><div class="warning" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Warning"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Warning]" src="images/warning.png"></td><th align="left">Warning</th></tr><tr><td align="left" valign="top"><p>If Stub Runner&#8217;s integration with Stream the <code class="literal">messageFrom</code> or <code class="literal">sentTo</code> Strings
are resolved first as a <code class="literal">destination</code> of a channel and no such <code class="literal">destination</code> exists, the
destination is resolved as a channel name.</p></td></tr></table></div><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>If you want to use Spring Cloud Stream remember, to add a dependency on
<code class="literal">org.springframework.cloud:spring-cloud-stream-test-support</code>.</p></td></tr></table></div><p class="primary"><b>Maven.&nbsp;</b>
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;dependency&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>spring-cloud-stream-test-support<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;scope&gt;</span>test<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/scope&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/dependency&gt;</span></pre><p class="primary">
</p><p class="secondary"><b>Gradle.&nbsp;</b>
</p><pre class="programlisting">testCompile <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud:spring-cloud-stream-test-support"</span></pre><p class="secondary">
</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_adding_the_runner_to_the_project_3" href="#_adding_the_runner_to_the_project_3"></a>7.4.1&nbsp;Adding the Runner to the Project</h3></div></div></div><p>You can have both Spring Cloud Stream and Spring Cloud Contract Stub Runner on the
classpath. Remember to annotate your test class with <code class="literal">@AutoConfigureStubRunner</code>.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_disabling_the_functionality_3" href="#_disabling_the_functionality_3"></a>7.4.2&nbsp;Disabling the functionality</h3></div></div></div><p>If you need to disable this functionality, set the <code class="literal">stubrunner.stream.enabled=false</code>
property.</p><p>Assume that you have the following Maven repository with a deployed stubs for the
<code class="literal">streamService</code> application:</p><pre class="programlisting">&#9492;&#9472;&#9472; .m2
&#9492;&#9472;&#9472; repository
&#9492;&#9472;&#9472; io
&#9492;&#9472;&#9472; codearte
&#9492;&#9472;&#9472; accurest
&#9492;&#9472;&#9472; stubs
&#9492;&#9472;&#9472; streamService
&#9500;&#9472;&#9472; <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT
&#9474;&nbsp;&nbsp; &#9500;&#9472;&#9472; streamService-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT.pom
&#9474;&nbsp;&nbsp; &#9500;&#9472;&#9472; streamService-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT-stubs.jar
&#9474;&nbsp;&nbsp; &#9492;&#9472;&#9472; maven-metadata-local.xml
&#9492;&#9472;&#9472; maven-metadata-local.xml</pre><p>Further assume the stubs contain the following structure:</p><pre class="programlisting">&#9500;&#9472;&#9472; META-INF
&#9474;&nbsp;&nbsp; &#9492;&#9472;&#9472; MANIFEST.MF
&#9492;&#9472;&#9472; repository
&#9500;&#9472;&#9472; accurest
&#9474;&nbsp;&nbsp; &#9500;&#9472;&#9472; bookDeleted.groovy
&#9474;&nbsp;&nbsp; &#9500;&#9472;&#9472; bookReturned1.groovy
&#9474;&nbsp;&nbsp; &#9492;&#9472;&#9472; bookReturned2.groovy
&#9492;&#9472;&#9472; mappings</pre><p>Consider the following contracts (numbered <span class="strong"><strong>1</strong></span>):</p><pre class="programlisting">Contract.make {
label <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'return_book_1'</span>
input { triggeredBy(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'bookReturnedTriggered()'</span>) }
outputMessage {
sentTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'returnBook'</span>)
body(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'{ "bookName" : "foo" }'</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">''</span>)
headers { header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'BOOK-NAME'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span>) }
}
}</pre><p>Now consider <span class="strong"><strong>2</strong></span>:</p><pre class="programlisting">Contract.make {
label <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'return_book_2'</span>
input {
messageFrom(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'bookStorage'</span>)
messageBody([
bookName: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span>
])
messageHeaders { header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'sample'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'header'</span>) }
}
outputMessage {
sentTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'returnBook'</span>)
body([
bookName: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span>
])
headers { header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'BOOK-NAME'</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span>) }
}
}</pre><p>Now consider the following Spring configuration:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">stubrunner.repositoryRoot</span>: classpath:m2repo/repository/
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">stubrunner.ids</span>: org.springframework.cloud.contract.verifier.stubs:streamService:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.0</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>-SNAPSHOT:stubs
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">spring</span>:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> cloud</span>:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> stream</span>:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> bindings</span>:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> output</span>:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> destination</span>: returnBook
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> input</span>:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> destination</span>: bookStorage
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">server</span>:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> port</span>: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">debug</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">true</span></pre><p>These examples lend themselves to three scenarios:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a class="xref" href="multi__stub_runner_for_messaging.html#stream-scenario-1" title="Scenario 1 (no input message)">the section called &#8220;Scenario 1 (no input message)&#8221;</a></li><li class="listitem"><a class="xref" href="multi__stub_runner_for_messaging.html#stream-scenario-2" title="Scenario 2 (output triggered by input)">the section called &#8220;Scenario 2 (output triggered by input)&#8221;</a></li><li class="listitem"><a class="xref" href="multi__stub_runner_for_messaging.html#stream-scenario-3" title="Scenario 3 (input with no output)">the section called &#8220;Scenario 3 (input with no output)&#8221;</a></li></ul></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="stream-scenario-1" href="#stream-scenario-1"></a>Scenario 1 (no input message)</h4></div></div></div><p>To trigger a message via the <code class="literal">return_book_1</code> label, use the <code class="literal">StubTrigger</code> interface as
follows:</p><pre class="programlisting">stubFinder.trigger(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'return_book_1'</span>)</pre><p>To listen to the output of the message sent to a channel whose <code class="literal">destination</code> is
<code class="literal">returnBook</code>:</p><pre class="programlisting">Message&lt;?&gt; receivedMessage = messaging.receive(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'returnBook'</span>)</pre><p>The received message passes the following assertions:</p><pre class="programlisting">receivedMessage != null
assertJsons(receivedMessage.payload)
receivedMessage.headers.get(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'BOOK-NAME'</span>) == <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span></pre></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="stream-scenario-2" href="#stream-scenario-2"></a>Scenario 2 (output triggered by input)</h4></div></div></div><p>Since the route is set for you, you can send a message to the <code class="literal">bookStorage</code>
<code class="literal">destination</code>:</p><pre class="programlisting">messaging.send(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> BookReturned(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span>), [sample: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'header'</span>], <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'bookStorage'</span>)</pre><p>To listen to the output of the message sent to <code class="literal">returnBook</code>:</p><pre class="programlisting">Message&lt;?&gt; receivedMessage = messaging.receive(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'returnBook'</span>)</pre><p>The received message passes the following assertions:</p><pre class="programlisting">receivedMessage != null
assertJsons(receivedMessage.payload)
receivedMessage.headers.get(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'BOOK-NAME'</span>) == <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span></pre></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="stream-scenario-3" href="#stream-scenario-3"></a>Scenario 3 (input with no output)</h4></div></div></div><p>Since the route is set for you, you can send a message to the <code class="literal">output</code>
destination:</p><pre class="programlisting">messaging.send(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> BookReturned(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'foo'</span>), [sample: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'header'</span>], <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'delete'</span>)</pre></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_stub_runner_spring_amqp" href="#_stub_runner_spring_amqp"></a>7.5&nbsp;Stub Runner Spring AMQP</h2></div></div></div><p>Spring Cloud Contract Verifier Stub Runner&#8217;s messaging module provides an easy way to
integrate with Spring AMQP&#8217;s Rabbit Template. For the provided artifacts, it
automatically downloads the stubs and registers the required routes.</p><p>The integration tries to work standalone (that is, without interaction with a running
RabbitMQ message broker). It expects a <code class="literal">RabbitTemplate</code> on the application context and
uses it as a spring boot test named <code class="literal">@SpyBean</code>. As a result, it can use the mockito spy
functionality to verify and inspect messages sent by the application.</p><p>On the message consumer side, the stub runner considers all <code class="literal">@RabbitListener</code> annotated
endpoints and all <code class="literal">SimpleMessageListenerContainer</code> objects on the application context.</p><p>As messages are usually sent to exchanges in AMQP, the message contract contains the
exchange name as the destination. Message listeners on the other side are bound to
queues. Bindings connect an exchange to a queue. If message contracts are triggered, the
Spring AMQP stub runner integration looks for bindings on the application context that
match this exchange. Then it collects the queues from the Spring exchanges and tries to
find message listeners bound to these queues. The message is triggered for all matching
message listeners.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_adding_the_runner_to_the_project_4" href="#_adding_the_runner_to_the_project_4"></a>7.5.1&nbsp;Adding the Runner to the Project</h3></div></div></div><p>You can have both Spring AMQP and Spring Cloud Contract Stub Runner on the classpath and
set the property <code class="literal">stubrunner.amqp.enabled=true</code>. Remember to annotate your test class
with <code class="literal">@AutoConfigureStubRunner</code>.</p><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>If you already have Stream and Integration on the classpath, you need
to disable them explicitly by setting the <code class="literal">stubrunner.stream.enabled=false</code> and
<code class="literal">stubrunner.integration.enabled=false</code> properties.</p></td></tr></table></div><p>Assume that you have the following Maven repository with a deployed stubs for the
<code class="literal">spring-cloud-contract-amqp-test</code> application.</p><pre class="programlisting">&#9492;&#9472;&#9472; .m2
&#9492;&#9472;&#9472; repository
&#9492;&#9472;&#9472; com
&#9492;&#9472;&#9472; example
&#9492;&#9472;&#9472; spring-cloud-contract-amqp-<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">test</span>
&#9500;&#9472;&#9472; <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.4</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>-SNAPSHOT
&#9474;&nbsp;&nbsp; &#9500;&#9472;&#9472; spring-cloud-contract-amqp-<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">test</span>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.4</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>-SNAPSHOT.pom
&#9474;&nbsp;&nbsp; &#9500;&#9472;&#9472; spring-cloud-contract-amqp-<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">test</span>-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.4</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>-SNAPSHOT-stubs.jar
&#9474;&nbsp;&nbsp; &#9492;&#9472;&#9472; maven-metadata-local.xml
&#9492;&#9472;&#9472; maven-metadata-local.xml</pre><p>Further assume that the stubs contain the following structure:</p><pre class="programlisting">&#9500;&#9472;&#9472; META-INF
&#9474;&nbsp;&nbsp; &#9492;&#9472;&#9472; MANIFEST.MF
&#9492;&#9472;&#9472; contracts
&#9492;&#9472;&#9472; shouldProduceValidPersonData.groovy</pre><p>Consider the following contract:</p><pre class="programlisting">Contract.make {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Human readable description</span>
description <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'Should produce valid person data'</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Label by means of which the output message can be triggered</span>
label <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'contract-test.person.created.event'</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// input to the contract</span>
input {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// the contract will be triggered by a method</span>
triggeredBy(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'createPerson()'</span>)
}
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// output message of the contract</span>
outputMessage {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// destination to which the output message will be sent</span>
sentTo <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'contract-test.exchange'</span>
headers {
header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'contentType'</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'application/json'</span>)
header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'__TypeId__'</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'org.springframework.cloud.contract.stubrunner.messaging.amqp.Person'</span>)
}
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// the body of the output message</span>
body ([
id: $(consumer(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">9</xslthl:number>), producer(regex(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"[0-9]+"</span>))),
name: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"me"</span>
])
}
}</pre><p>Now consider the following Spring configuration:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">stubrunner</span>:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> repositoryRoot</span>: classpath:m2repo/repository/
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> ids</span>: org.springframework.cloud.contract.verifier.stubs.amqp:spring-cloud-contract-amqp-test:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.4</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>-SNAPSHOT:stubs
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> amqp</span>:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> enabled</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">true</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">server</span>:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> port</span>: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number></pre><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_triggering_the_message" href="#_triggering_the_message"></a>Triggering the message</h4></div></div></div><p>To trigger a message using the contract above, use the <code class="literal">StubTrigger</code> interface as
follows:</p><pre class="programlisting">stubTrigger.trigger(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"contract-test.person.created.event"</span>)</pre><p>The message has a destination of <code class="literal">contract-test.exchange</code>, so the Spring AMQP stub runner
integration looks for bindings related to this exchange.</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Bean</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> Binding binding() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> BindingBuilder.bind(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> Queue(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"test.queue"</span>)).to(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> DirectExchange(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"contract-test.exchange"</span>)).with(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"#"</span>);
}</pre><p>The binding definition binds the queue <code class="literal">test.queue</code>. As a result, the following listener
definition is matched and invoked with the contract message.</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Bean</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> SimpleMessageListenerContainer simpleMessageListenerContainer(ConnectionFactory connectionFactory,
MessageListenerAdapter listenerAdapter) {
SimpleMessageListenerContainer container = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.setQueueNames(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"test.queue"</span>);
container.setMessageListener(listenerAdapter);
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> container;
}</pre><p>Also, the following annotated listener matches and is invoked:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RabbitListener(bindings = @QueueBinding(
value = @Queue(value = "test.queue"),
exchange = @Exchange(value = "contract-test.exchange", ignoreDeclarationExceptions = "true")))</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> handlePerson(Person person) {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.person = person;
}</pre><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>The message is directly handed over to the <code class="literal">onMessage</code> method of the
<code class="literal">MessageListener</code> associated with the matching <code class="literal">SimpleMessageListenerContainer</code>.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_spring_amqp_test_configuration" href="#_spring_amqp_test_configuration"></a>Spring AMQP Test Configuration</h4></div></div></div><p>In order to avoid Spring AMQP trying to connect to a running broker during our tests
configure a mock <code class="literal">ConnectionFactory</code>.</p><p>To disable the mocked ConnectionFactory, set the following property:
<code class="literal">stubrunner.amqp.mockConnection=false</code></p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">stubrunner</span>:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> amqp</span>:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> mockConnection</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">false</span></pre></div></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__spring_cloud_contract_stub_runner.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi__contract_dsl.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">6.&nbsp;Spring Cloud Contract Stub Runner&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-contract.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;8.&nbsp;Contract DSL</td></tr></table></div></body></html>

View File

@@ -0,0 +1,380 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>10.&nbsp;Using the Pluggable Architecture</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud-contract.html" title="Spring Cloud Contract"><link rel="up" href="multi_spring-cloud-contract.html" title="Spring Cloud Contract"><link rel="prev" href="multi__customization.html" title="9.&nbsp;Customization"><link rel="next" href="multi__spring_cloud_contract_wiremock.html" title="11.&nbsp;Spring Cloud Contract WireMock"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">10.&nbsp;Using the Pluggable Architecture</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__customization.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi__spring_cloud_contract_wiremock.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_using_the_pluggable_architecture" href="#_using_the_pluggable_architecture"></a>10.&nbsp;Using the Pluggable Architecture</h1></div></div></div><p>You may encounter cases where you have your contracts have been defined in other formats,
such as YAML, RAML or PACT. In those cases, you still want to benefit from the automatic
generation of tests and stubs. You can add your own implementation for generating both
tests and stubs. Also, you can customize the way tests are generated (for example, you
can generate tests for other languages) and the way stubs are generated (for example, you
can generate stubs for other HTTP server implementations).</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_custom_contract_converter" href="#_custom_contract_converter"></a>10.1&nbsp;Custom Contract Converter</h2></div></div></div><p>The <code class="literal">ContractConverter</code> interface lets you register your own implementation of a contract
structure converter. The following code listing shows the <code class="literal">ContractConverter</code> interface:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">package</span> org.springframework.cloud.contract.spec
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
* Converter to be used to convert FROM {@link File} TO {@link Contract}
* and from {@link Contract} to {@code T}
*
* @param &lt;T&gt; - type to which we want to convert the contract
*
* @author Marcin Grzejszczak
* @since 1.1.0
*/</xslthl:doccomment>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">interface</span> ContractConverter&lt;T&gt; {
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
* Should this file be accepted by the converter. Can use the file extension
* to check if the conversion is possible.
*
* @param file - file to be considered for conversion
* @return - {@code true} if the given implementation can convert the file
*/</xslthl:doccomment>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">boolean</span> isAccepted(File file)
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
* Converts the given {@link File} to its {@link Contract} representation
*
* @param file - file to convert
* @return - {@link Contract} representation of the file
*/</xslthl:doccomment>
Collection&lt;Contract&gt; convertFrom(File file)
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
* Converts the given {@link Contract} to a {@link T} representation
*
* @param contract - the parsed contract
* @return - {@link T} the type to which we do the conversion
*/</xslthl:doccomment>
T convertTo(Collection&lt;Contract&gt; contract)
}</pre><p>Your implementation must define the condition on which it should start the
conversion. Also, you must define how to perform that conversion in both directions.</p><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>Once you create your implementation, you must create a
<code class="literal">/META-INF/spring.factories</code> file in which you provide the fully qualified name of your
implementation.</p></td></tr></table></div><p>The following example shows a typical <code class="literal">spring.factories</code> file:</p><pre class="screen">org.springframework.cloud.contract.spec.ContractConverter=\
org.springframework.cloud.contract.verifier.converter.YamlContractConverter</pre><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_pact_converter" href="#_pact_converter"></a>10.1.1&nbsp;Pact Converter</h3></div></div></div><p>Spring Cloud Contract includes support for <a class="link" href="https://docs.pact.io/" target="_top">Pact</a> representation of
contracts. Instead of using the Groovy DSL, you can use Pact files. In this section, we
present how to add Pact support for your project.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_pact_contract" href="#_pact_contract"></a>10.1.2&nbsp;Pact Contract</h3></div></div></div><p>Consider following example of a Pact contract, which is a file under the
<code class="literal">src/test/resources/contracts</code> folder.</p><pre class="programlisting">{
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"provider"</span>: {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"name"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Provider"</span>
},
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"consumer"</span>: {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"name"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Consumer"</span>
},
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"interactions"</span>: [
{
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"description"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">""</span>,
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"request"</span>: {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"method"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"PUT"</span>,
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"path"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/fraudcheck"</span>,
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"headers"</span>: {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Content-Type"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"application/vnd.fraud.v1+json"</span>
},
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"body"</span>: {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"clientId"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"1234567890"</span>,
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"loanAmount"</span>: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">99999</xslthl:number>
},
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matchingRules"</span>: {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.body.clientId"</span>: {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"match"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"regex"</span>,
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"regex"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"[0-9]{10}"</span>
}
}
},
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"response"</span>: {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"status"</span>: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>,
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"headers"</span>: {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Content-Type"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"application/vnd.fraud.v1+json;charset=UTF-8"</span>
},
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"body"</span>: {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"fraudCheckStatus"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"FRAUD"</span>,
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"rejectionReason"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Amount too high"</span>
},
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matchingRules"</span>: {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.body.fraudCheckStatus"</span>: {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"match"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"regex"</span>,
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"regex"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"FRAUD"</span>
}
}
}
}
],
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"metadata"</span>: {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"pact-specification"</span>: {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"version"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"2.0.0"</span>
},
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"pact-jvm"</span>: {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"version"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"2.4.18"</span>
}
}
}</pre><p>The remainder of this section about using Pact refers to the preceding file.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_pact_for_producers" href="#_pact_for_producers"></a>10.1.3&nbsp;Pact for Producers</h3></div></div></div><p>On the producer side, you mustadd two additional dependencies to your plugin
configuration. One is the Spring Cloud Contract Pact support, and the other represents
the current Pact version that you use.</p><p class="primary"><b>Maven.&nbsp;</b>
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;plugin&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>spring-cloud-contract-maven-plugin<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;version&gt;</span>${spring-cloud-contract.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/version&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;extensions&gt;</span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/extensions&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;configuration&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;packageWithBaseClasses&gt;</span>com.example.fraud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/packageWithBaseClasses&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/configuration&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;dependencies&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;dependency&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>spring-cloud-contract-spec-pact<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;version&gt;</span>${spring-cloud-contract.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/version&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/dependency&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;dependency&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>au.com.dius<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>pact-jvm-model<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;version&gt;</span>2.4.18<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/version&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/dependency&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/dependencies&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/plugin&gt;</span></pre><p class="primary">
</p><p class="secondary"><b>Gradle.&nbsp;</b>
</p><pre class="programlisting">classpath <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud:spring-cloud-contract-spec-pact:${findProperty('verifierVersion') ?: verifierVersion}"</span>
classpath <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'au.com.dius:pact-jvm-model:2.4.18'</span></pre><p class="secondary">
</p><p>When you execute the build of your application, a test will be generated. The generated
test might be as follows:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Test</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> validate_shouldMarkClientAsFraud() <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> Exception {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// given:</span>
MockMvcRequestSpecification request = given()
.header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Content-Type"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"application/vnd.fraud.v1+json"</span>)
.body(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"{\"clientId\":\"1234567890\",\"loanAmount\":99999}"</span>);
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// when:</span>
ResponseOptions response = given().spec(request)
.put(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/fraudcheck"</span>);
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// then:</span>
assertThat(response.statusCode()).isEqualTo(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>);
assertThat(response.header(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Content-Type"</span>)).isEqualTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"application/vnd.fraud.v1+json;charset=UTF-8"</span>);
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// and:</span>
DocumentContext parsedJson = JsonPath.parse(response.getBody().asString());
assertThatJson(parsedJson).field(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"rejectionReason"</span>).isEqualTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Amount too high"</span>);
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// and:</span>
assertThat(parsedJson.read(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$.fraudCheckStatus"</span>, String.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>)).matches(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"FRAUD"</span>);
}</pre><p>The corresponding generated stub might be as follows:</p><pre class="programlisting">{
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"uuid"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"996ae5ae-6834-4db6-8fac-358ca187ab62"</span>,
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"request"</span> : {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"url"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/fraudcheck"</span>,
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"method"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"PUT"</span>,
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"headers"</span> : {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Content-Type"</span> : {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"equalTo"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"application/vnd.fraud.v1+json"</span>
}
},
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"bodyPatterns"</span> : [ {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matchesJsonPath"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$[?(@.loanAmount == 99999)]"</span>
}, {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"matchesJsonPath"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"$[?(@.clientId =~ /([0-9]{10})/)]"</span>
} ]
},
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"response"</span> : {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"status"</span> : <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">200</xslthl:number>,
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"body"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"{\"fraudCheckStatus\":\"FRAUD\",\"rejectionReason\":\"Amount too high\"}"</span>,
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"headers"</span> : {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Content-Type"</span> : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"application/vnd.fraud.v1+json;charset=UTF-8"</span>
}
}
}</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_pact_for_consumers" href="#_pact_for_consumers"></a>10.1.4&nbsp;Pact for Consumers</h3></div></div></div><p>On the producer side, you must add two additional dependencies to your project
dependencies. One is the Spring Cloud Contract Pact support, and the other represents the
current Pact version that you use.</p><p class="primary"><b>Maven.&nbsp;</b>
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;dependency&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>spring-cloud-contract-spec-pact<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;scope&gt;</span>test<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/scope&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/dependency&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;dependency&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>au.com.dius<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>pact-jvm-model<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;version&gt;</span>2.4.18<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/version&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;scope&gt;</span>test<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/scope&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/dependency&gt;</span></pre><p class="primary">
</p><p class="secondary"><b>Gradle.&nbsp;</b>
</p><pre class="programlisting">testCompile <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud:spring-cloud-contract-spec-pact"</span>
testCompile <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'au.com.dius:pact-jvm-model:2.4.18'</span></pre><p class="secondary">
</p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_using_the_custom_test_generator" href="#_using_the_custom_test_generator"></a>10.2&nbsp;Using the Custom Test Generator</h2></div></div></div><p>If you want to generate tests for languages other than Java or you are not happy with the
way the verifier builds Java tests, you can register your own implementation.</p><p>The <code class="literal">SingleTestGenerator</code> interface lets you register your own implementation. The
following code listing shows the <code class="literal">SingleTestGenerator</code> interface:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">package</span> org.springframework.cloud.contract.verifier.builder
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.cloud.contract.verifier.file.ContractMetadata
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
* Builds a single test.
*
* @since 1.1.0
*/</xslthl:doccomment>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">interface</span> SingleTestGenerator {
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
* Creates contents of a single test class in which all test scenarios from
* the contract metadata should be placed.
*
* @param properties - properties passed to the plugin
* @param listOfFiles - list of parsed contracts with additional metadata
* @param className - the name of the generated test class
* @param classPackage - the name of the package in which the test class should be stored
* @param includedDirectoryRelativePath - relative path to the included directory
* @return contents of a single test class
*/</xslthl:doccomment>
String buildClass(ContractVerifierConfigProperties properties, Collection&lt;ContractMetadata&gt; listOfFiles,
String className, String classPackage, String includedDirectoryRelativePath)
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
* Extension that should be appended to the generated test class. E.g. {@code .java} or {@code .php}
*
* @param properties - properties passed to the plugin
*/</xslthl:doccomment>
String fileExtension(ContractVerifierConfigProperties properties)
}</pre><p>Again, you must provide a <code class="literal">spring.factories</code> file, such as the one shown in the following
example:</p><pre class="screen">org.springframework.cloud.contract.verifier.builder.SingleTestGenerator=/
com.example.MyGenerator</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_using_the_custom_stub_generator" href="#_using_the_custom_stub_generator"></a>10.3&nbsp;Using the Custom Stub Generator</h2></div></div></div><p>If you want to generate stubs for stub servers other than WireMock, you can plug in your
own implementation of the <code class="literal">StubGenerator</code> interface. The following code listing shows the
<code class="literal">StubGenerator</code> interface:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">package</span> org.springframework.cloud.contract.verifier.converter
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> groovy.transform.CompileStatic
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.cloud.contract.spec.Contract
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.cloud.contract.verifier.file.ContractMetadata
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
* Converts contracts into their stub representation.
*
* @since 1.1.0
*/</xslthl:doccomment>
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@CompileStatic</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">interface</span> StubGenerator {
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
* Returns {@code true} if the converter can handle the file to convert it into a stub.
*/</xslthl:doccomment>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">boolean</span> canHandleFileName(String fileName)
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
* Returns the collection of converted contracts into stubs. One contract can
* result in multiple stubs.
*/</xslthl:doccomment>
Map&lt;Contract, String&gt; convertContents(String rootName, ContractMetadata content)
<xslthl:doccomment xmlns:xslthl="http://xslthl.sourceforge.net/">/**
* Returns the name of the converted stub file. If you have multiple contracts
* in a single file then a prefix will be added to the generated file. If you
* provide the {@link Contract#name} field then that field will override the
* generated file name.
*
* Example: name of file with 2 contracts is {@code foo.groovy}, it will be
* converted by the implementation to {@code foo.json}. The recursive file
* converter will create two files {@code 0_foo.json} and {@code 1_foo.json}
*/</xslthl:doccomment>
String generateOutputFileNameForInput(String inputFileName)
}</pre><p>Again, you must provide a <code class="literal">spring.factories</code> file, such as the one shown in the following
example:</p><pre class="screen"># Stub converters
org.springframework.cloud.contract.verifier.converter.StubGenerator=\
org.springframework.cloud.contract.verifier.wiremock.DslToWireMockClientConverter</pre><p>The default implementation is the WireMock stub generation.</p><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Tip</th></tr><tr><td align="left" valign="top"><p>You can provide multiple stub generator implementations. For example, from a single
DSL, you can produce both WireMock stubs and Pact files.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_using_the_custom_stub_runner" href="#_using_the_custom_stub_runner"></a>10.4&nbsp;Using the Custom Stub Runner</h2></div></div></div><p>If you decide to use a custom stub generation, you also need a custom way of running
stubs with your different stub provider.</p><p>Assume that you use <a class="link" href="https://github.com/dreamhead/moco" target="_top">Moco</a> to build your stubs and that
you have written a stub generator and placed your stubs in a JAR file.</p><p>In order for Stub Runner to know how to run your stubs, you have to define a custom
HTTP Stub server implementation, which might resemble the following example:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">package</span> org.springframework.cloud.contract.stubrunner.provider.moco
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> com.github.dreamhead.moco.bootstrap.arg.HttpArgs
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> com.github.dreamhead.moco.runner.JsonRunner
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> com.github.dreamhead.moco.runner.RunnerSetting
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> groovy.util.logging.Slf4j
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.cloud.contract.stubrunner.HttpServerStub
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.util.SocketUtils
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Slf4j</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> MocoHttpServerStub <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">implements</span> HttpServerStub {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">boolean</span> started
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> JsonRunner runner
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">int</span> port
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">int</span> port() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">if</span> (!isRunning()) {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> -<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>
}
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> port
}
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">boolean</span> isRunning() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> started
}
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation>
HttpServerStub start() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> start(SocketUtils.findAvailableTcpPort())
}
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation>
HttpServerStub start(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">int</span> port) {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.port = port
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>
}
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation>
HttpServerStub stop() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">if</span> (!isRunning()) {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>
}
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.runner.stop()
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>
}
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation>
HttpServerStub registerMappings(Collection&lt;File&gt; stubFiles) {
List&lt;RunnerSetting&gt; settings = stubFiles.findAll { it.name.endsWith(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"json"</span>) }
.collect {
log.info(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Trying to parse [{}]"</span>, it.name)
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">try</span> {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> RunnerSetting.aRunnerSetting().withStream(it.newInputStream()).build()
} <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">catch</span> (Exception e) {
log.warn(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Exception occurred while trying to parse file [{}]"</span>, it.name, e)
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> null
}
}.findAll { it }
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.runner = JsonRunner.newJsonRunnerWithSetting(settings,
HttpArgs.httpArgs().withPort(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.port).build())
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.runner.run()
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.started = true
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>
}
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation>
String registeredMappings() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">""</span>
}
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">boolean</span> isAccepted(File file) {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> file.name.endsWith(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">".json"</span>)
}
}</pre><p>Then, you can register it in your <code class="literal">spring.factories</code> file, as shown in the following
example:</p><pre class="screen">org.springframework.cloud.contract.stubrunner.HttpServerStub=\
org.springframework.cloud.contract.stubrunner.provider.moco.MocoHttpServerStub</pre><p>Now you can run stubs with Moco.</p><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>If you do not provide any implementation, then the default (WireMock)
implementation is used. If you provide more than one, the first one on the list is used.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_using_the_custom_stub_downloader" href="#_using_the_custom_stub_downloader"></a>10.5&nbsp;Using the Custom Stub Downloader</h2></div></div></div><p>You can customize the way your stubs are downloaded by creating an implementation of the
<code class="literal">StubDownloaderBuilder</code> interface, as shown in the following example:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">package</span> com.example;
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> CustomStubDownloaderBuilder <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">implements</span> StubDownloaderBuilder {
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> StubDownloader build(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">final</span> StubRunnerOptions stubRunnerOptions) {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> StubDownloader() {
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> Map.Entry&lt;StubConfiguration, File&gt; downloadAndUnpackStubJar(
StubConfiguration config) {
File unpackedStubs = retrieveStubs();
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> AbstractMap.SimpleEntry&lt;&gt;(
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> StubConfiguration(config.getGroupId(), config.getArtifactId(), version,
config.getClassifier()), unpackedStubs);
}
File retrieveStubs() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// here goes your custom logic to provide a folder where all the stubs reside</span>
}
}</pre><p>Then you can register it in your <code class="literal">spring.factories</code> file, as shown in the following
example:</p><pre class="screen"># Example of a custom Stub Downloader Provider
org.springframework.cloud.contract.stubrunner.StubDownloaderBuilder=\
com.example.CustomStubDownloaderBuilder</pre><p>Now you can pick a folder with the source of your stubs.</p><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>If you do not provide any implementation, then the default is used.
If you use the <code class="literal">repositoryRoot</code> property or the <code class="literal">workOffline</code> flag, then an Aether-based
implementation that downloads stubs from a remote repository is used. If you do not
provide these values, the <code class="literal">ClasspathStubProvider</code> (which will scan the classpath) is
used. If you provide more than one, then the first one on the list is used.</p></td></tr></table></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__customization.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi__spring_cloud_contract_wiremock.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">9.&nbsp;Customization&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-contract.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;11.&nbsp;Spring Cloud Contract WireMock</td></tr></table></div></body></html>

View File

@@ -0,0 +1,4 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title></title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud-contract.html" title="Spring Cloud Contract"><link rel="up" href="multi_spring-cloud-contract.html" title="Spring Cloud Contract"><link rel="prev" href="multi_spring-cloud-contract.html" title="Spring Cloud Contract"><link rel="next" href="multi__spring_cloud_contract.html" title="1.&nbsp;Spring Cloud Contract"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center"></th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi_spring-cloud-contract.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi__spring_cloud_contract.html">Next</a></td></tr></table><hr></div><div class="preface"><div class="titlepage"><div><div><h1 class="title"><a name="d0e9" href="#d0e9"></a></h1></div></div></div><p>_Documentation Authors: Adam Dudczak, Mathias D&uuml;sterh&ouml;ft, Marcin Grzejszczak, Dennis Kieselhorst, Jakub Kubry&#324;ski, Karol Lassak,
Olga Maciaszek-Sharma, Mariusz Smyku&#322;a, Dave Syer, Jay Bryant</p><p>1.2.7.RELEASE</p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi_spring-cloud-contract.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi__spring_cloud_contract.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Spring Cloud Contract&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-contract.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;1.&nbsp;Spring Cloud Contract</td></tr></table></div></body></html>

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,35 @@
/*
code highlight CSS resemblign the Eclipse IDE default color schema
@author Costin Leau
*/
.hl-keyword {
color: #7F0055;
font-weight: bold;
}
.hl-comment {
color: #3F5F5F;
font-style: italic;
}
.hl-multiline-comment {
color: #3F5FBF;
font-style: italic;
}
.hl-tag {
color: #3F7F7F;
}
.hl-attribute {
color: #7F007F;
}
.hl-value {
color: #2A00FF;
}
.hl-string {
color: #2A00FF;
}

View File

@@ -0,0 +1,9 @@
@IMPORT url("manual.css");
body.firstpage {
background: url("../images/background.png") no-repeat center top;
}
div.part h1 {
border-top: none;
}

View File

@@ -0,0 +1,6 @@
@IMPORT url("manual.css");
body {
background: url("../images/background.png") no-repeat center top;
}

View File

@@ -0,0 +1,344 @@
@IMPORT url("highlight.css");
html {
padding: 0pt;
margin: 0pt;
}
body {
color: #333333;
margin: 15px 30px;
font-family: Helvetica, Arial, Freesans, Clean, Sans-serif;
line-height: 1.6;
-webkit-font-smoothing: antialiased;
}
code {
font-size: 16px;
font-family: Consolas, "Liberation Mono", Courier, monospace;
}
:not(a)>code {
color: #6D180B;
}
:not(pre)>code {
background-color: #F2F2F2;
border: 1px solid #CCCCCC;
border-radius: 4px;
padding: 1px 3px 0;
text-shadow: none;
white-space: nowrap;
}
body>*:first-child {
margin-top: 0 !important;
}
div {
margin: 0pt;
}
hr {
border: 1px solid #CCCCCC;
background: #CCCCCC;
}
h1,h2,h3,h4,h5,h6 {
color: #000000;
cursor: text;
font-weight: bold;
margin: 30px 0 10px;
padding: 0;
}
h1,h2,h3 {
margin: 40px 0 10px;
}
h1 {
margin: 70px 0 30px;
padding-top: 20px;
}
div.part h1 {
border-top: 1px dotted #CCCCCC;
}
h1,h1 code {
font-size: 32px;
}
h2,h2 code {
font-size: 24px;
}
h3,h3 code {
font-size: 20px;
}
h4,h1 code,h5,h5 code,h6,h6 code {
font-size: 18px;
}
div.book,div.chapter,div.appendix,div.part,div.preface {
min-width: 300px;
max-width: 1200px;
margin: 0 auto;
}
p.releaseinfo {
font-weight: bold;
margin-bottom: 40px;
margin-top: 40px;
}
div.authorgroup {
line-height: 1;
}
p.copyright {
line-height: 1;
margin-bottom: -5px;
}
.legalnotice p {
font-style: italic;
font-size: 14px;
line-height: 1;
}
div.titlepage+p,div.titlepage+p {
margin-top: 0;
}
pre {
line-height: 1.0;
color: black;
}
a {
color: #4183C4;
text-decoration: none;
}
p {
margin: 15px 0;
text-align: left;
}
ul,ol {
padding-left: 30px;
}
li p {
margin: 0;
}
div.table {
margin: 1em;
padding: 0.5em;
text-align: center;
}
div.table table,div.informaltable table {
display: table;
width: 100%;
}
div.table td {
padding-left: 7px;
padding-right: 7px;
}
.sidebar {
line-height: 1.4;
padding: 0 20px;
background-color: #F8F8F8;
border: 1px solid #CCCCCC;
border-radius: 3px 3px 3px 3px;
}
.sidebar p.title {
color: #6D180B;
}
pre.programlisting,pre.screen {
font-size: 15px;
padding: 6px 10px;
background-color: #F8F8F8;
border: 1px solid #CCCCCC;
border-radius: 3px 3px 3px 3px;
clear: both;
overflow: auto;
line-height: 1.4;
font-family: Consolas, "Liberation Mono", Courier, monospace;
}
table {
border-collapse: collapse;
border-spacing: 0;
border: 1px solid #DDDDDD !important;
border-radius: 4px !important;
border-collapse: separate !important;
line-height: 1.6;
}
table thead {
background: #F5F5F5;
}
table tr {
border: none;
border-bottom: none;
}
table th {
font-weight: bold;
}
table th,table td {
border: none !important;
padding: 6px 13px;
}
table tr:nth-child(2n) {
background-color: #F8F8F8;
}
td p {
margin: 0 0 15px 0;
}
div.table-contents td p {
margin: 0;
}
div.important *,div.note *,div.tip *,div.warning *,div.navheader *,div.navfooter *,div.calloutlist *
{
border: none !important;
background: none !important;
margin: 0;
}
div.important p,div.note p,div.tip p,div.warning p {
color: #6F6F6F;
line-height: 1.6;
}
div.important code,div.note code,div.tip code,div.warning code {
background-color: #F2F2F2 !important;
border: 1px solid #CCCCCC !important;
border-radius: 4px !important;
padding: 1px 3px 0 !important;
text-shadow: none !important;
white-space: nowrap !important;
}
.note th,.tip th,.warning th {
display: none;
}
.note tr:first-child td,.tip tr:first-child td,.warning tr:first-child td
{
border-right: 1px solid #CCCCCC !important;
padding-top: 10px;
}
div.calloutlist p,div.calloutlist td {
padding: 0;
margin: 0;
}
div.calloutlist>table>tbody>tr>td:first-child {
padding-left: 10px;
width: 30px !important;
}
div.important,div.note,div.tip,div.warning {
margin-left: 0px !important;
margin-right: 20px !important;
margin-top: 20px;
margin-bottom: 20px;
padding-top: 10px;
padding-bottom: 10px;
}
div.toc {
line-height: 1.2;
}
dl,dt {
margin-top: 1px;
margin-bottom: 0;
}
div.toc>dl>dt {
font-size: 32px;
font-weight: bold;
margin: 30px 0 10px 0;
display: block;
}
div.toc>dl>dd>dl>dt {
font-size: 24px;
font-weight: bold;
margin: 20px 0 10px 0;
display: block;
}
div.toc>dl>dd>dl>dd>dl>dt {
font-weight: bold;
font-size: 20px;
margin: 10px 0 0 0;
}
tbody.footnotes * {
border: none !important;
}
div.footnote p {
margin: 0;
line-height: 1;
}
div.footnote p sup {
margin-right: 6px;
vertical-align: middle;
}
div.navheader {
border-bottom: 1px solid #CCCCCC;
}
div.navfooter {
border-top: 1px solid #CCCCCC;
}
.title {
margin-left: -1em;
padding-left: 1em;
}
.title>a {
position: absolute;
visibility: hidden;
display: block;
font-size: 0.85em;
margin-top: 0.05em;
margin-left: -1em;
vertical-align: text-top;
color: black;
}
.title>a:before {
content: "\00A7";
}
.title:hover>a,.title>a:hover,.title:hover>a:hover {
visibility: visible;
}
.title:focus>a,.title>a:focus,.title:focus>a:focus {
outline: 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 350 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 931 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,326 @@
<!DOCTYPE html>
<!--
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2019-05-23
| Rendered using Apache Maven Fluido Skin 1.5
-->
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="Date-Revision-yyyymmdd" content="20190523" />
<meta http-equiv="Content-Language" content="en" />
<title>Spring Cloud Contract Maven Plugin &#x2013; Checkstyle Results</title>
<link rel="stylesheet" href="./css/apache-maven-fluido-1.5.min.css" />
<link rel="stylesheet" href="./css/site.css" />
<link rel="stylesheet" href="./css/print.css" media="print" />
<script type="text/javascript" src="./js/apache-maven-fluido-1.5.min.js"></script>
</head>
<body class="topBarEnabled">
<a href="https://github.com/spring-cloud/spring-cloud-contract">
<img style="position: absolute; top: 0; right: 0; border: 0; z-index: 10000;"
src="https://s3.amazonaws.com/github/ribbons/forkme_right_orange_ff7600.png"
alt="Fork me on GitHub">
</a>
<div id="topbar" class="navbar navbar-fixed-top ">
<div class="navbar-inner">
<div class="container-fluid">
<a data-target=".nav-collapse" data-toggle="collapse" class="btn btn-navbar">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<ul class="nav">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Overview <b class="caret"></b></a>
<ul class="dropdown-menu">
<li> <a href="index.html" title="Introduction">Introduction</a>
</li>
<li> <a href="usage.html" title="Usage">Usage</a>
</li>
<li> <a href="plugin-info.html" title="Goals">Goals</a>
</li>
<li> <a href="junit.html" title="JUnit Configuration">JUnit Configuration</a>
</li>
<li> <a href="spock.html" title="Spock Configuration">Spock Configuration</a>
</li>
<li> <a href="complex.html" title="Complex Configuration">Complex Configuration</a>
</li>
<li> <a href="configs.html" title="Configuration snippets">Configuration snippets</a>
</li>
</ul>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Related Projects <b class="caret"></b></a>
<ul class="dropdown-menu">
<li> <a href="https://github.com/spring-cloud/spring-cloud-contract" title="Spring Cloud Contract">Spring Cloud Contract</a>
</li>
</ul>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Project Documentation <b class="caret"></b></a>
<ul class="dropdown-menu">
<li class="dropdown-submenu">
<a href="project-info.html" title="Project Information">Project Information</a>
<ul class="dropdown-menu">
<li> <a href="integration.html" title="CI Management">CI Management</a>
</li>
<li> <a href="index.html" title="About">About</a>
</li>
<li> <a href="issue-tracking.html" title="Issue Management">Issue Management</a>
</li>
<li> <a href="license.html" title="Licenses">Licenses</a>
</li>
<li> <a href="plugin-management.html" title="Plugin Management">Plugin Management</a>
</li>
<li> <a href="plugins.html" title="Plugins">Plugins</a>
</li>
<li> <a href="team-list.html" title="Team">Team</a>
</li>
<li> <a href="source-repository.html" title="Source Code Management">Source Code Management</a>
</li>
<li> <a href="project-summary.html" title="Summary">Summary</a>
</li>
</ul>
</li>
<li class="dropdown-submenu">
<a href="project-reports.html" title="Project Reports">Project Reports</a>
<ul class="dropdown-menu">
<li> <a href="checkstyle.html" title="Checkstyle">Checkstyle</a>
</li>
<li> <a href="plugin-info.html" title="Plugin Documentation">Plugin Documentation</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="container-fluid">
<div id="banner">
<div class="pull-left">
<div id="bannerLeft">
<h2>Spring Cloud Contract Maven Plugin</h2>
</div>
</div>
<div class="pull-right"> <div id="bannerRight">
<img src="" />
</div>
</div>
<div class="clear"><hr/></div>
</div>
<div id="breadcrumbs">
<ul class="breadcrumb">
<li id="publishDate">Last Published: 2019-05-23
<span class="divider">|</span>
</li>
<li id="projectVersion">Version: 1.2.7.RELEASE
</li>
</ul>
</div>
<div class="row-fluid">
<div id="leftColumn" class="span2">
<div class="well sidebar-nav">
<ul class="nav nav-list">
<li class="nav-header">Overview</li>
<li>
<a href="index.html" title="Introduction">
<span class="none"></span>
Introduction</a>
</li>
<li>
<a href="usage.html" title="Usage">
<span class="none"></span>
Usage</a>
</li>
<li>
<a href="plugin-info.html" title="Goals">
<span class="none"></span>
Goals</a>
</li>
<li>
<a href="junit.html" title="JUnit Configuration">
<span class="none"></span>
JUnit Configuration</a>
</li>
<li>
<a href="spock.html" title="Spock Configuration">
<span class="none"></span>
Spock Configuration</a>
</li>
<li>
<a href="complex.html" title="Complex Configuration">
<span class="none"></span>
Complex Configuration</a>
</li>
<li>
<a href="configs.html" title="Configuration snippets">
<span class="none"></span>
Configuration snippets</a>
</li>
<li class="nav-header">Related Projects</li>
<li>
<a href="https://github.com/spring-cloud/spring-cloud-contract" title="Spring Cloud Contract">
<span class="none"></span>
Spring Cloud Contract</a>
</li>
<li class="nav-header">Project Documentation</li>
<li>
<a href="project-info.html" title="Project Information">
<span class="icon-chevron-right"></span>
Project Information</a>
</li>
<li>
<a href="project-reports.html" title="Project Reports">
<span class="icon-chevron-down"></span>
Project Reports</a>
<ul class="nav nav-list">
<li class="active">
<a href="#"><span class="none"></span>Checkstyle</a>
</li>
<li>
<a href="plugin-info.html" title="Plugin Documentation">
<span class="none"></span>
Plugin Documentation</a>
</li>
</ul>
</li>
</ul>
<hr />
<div id="poweredBy">
<div class="clear"></div>
<div class="clear"></div>
<div class="clear"></div>
<div class="clear"></div>
<a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy">
<img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" />
</a>
</div>
</div>
</div>
<div id="bodyColumn" class="span10" >
<div class="section">
<h2><a name="Checkstyle_Results"></a>Checkstyle Results</h2>
<p>The following document contains the results of <a class="externalLink" href="http://checkstyle.sourceforge.net/">Checkstyle</a> 6.11.2 with checkstyle.xml ruleset.&#160;<a href="checkstyle.rss"><img alt="rss feed" src="images/rss.png" /></a></p></div>
<div class="section">
<h2><a name="Summary"></a>Summary</h2>
<table border="0" class="table table-striped">
<tr class="a">
<th>Files</th>
<th><img src="images/icon_info_sml.gif" alt="" />&#160;Info</th>
<th><img src="images/icon_warning_sml.gif" alt="" />&#160;Warnings</th>
<th><img src="images/icon_error_sml.gif" alt="" />&#160;Errors</th></tr>
<tr class="b">
<td>11</td>
<td>0</td>
<td>0</td>
<td>0</td></tr></table></div>
<div class="section">
<h2><a name="Files"></a>Files</h2>
<table border="0" class="table table-striped">
<tr class="a">
<th>File</th>
<th><img src="images/icon_info_sml.gif" alt="" />&#160;I</th>
<th><img src="images/icon_warning_sml.gif" alt="" />&#160;W</th>
<th><img src="images/icon_error_sml.gif" alt="" />&#160;E</th></tr></table></div>
<div class="section">
<h2><a name="Rules"></a>Rules</h2>
<table border="0" class="table table-striped">
<tr class="b">
<th>Category</th>
<th>Rule</th>
<th>Violations</th>
<th>Severity</th></tr></table></div>
<div class="section">
<h2><a name="Details"></a>Details</h2></div>
</div>
</div>
</div>
<hr/>
<footer>
<div class="container-fluid">
<div class="row-fluid">
<p >Copyright &copy; 2016&#x2013;2019
<a href="https://spring.io/">Spring</a>.
All rights reserved.
</p>
</div>
</div>
</footer>
</body>
</html>

View File

@@ -0,0 +1,208 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<rss version="0.91">
<channel>
<title>Spring Cloud Contract Maven Plugin - Checkstyle report</title>
<link>https://github.com/spring-cloud/spring-cloud-contract</link>
<description>Spring Cloud Contract Maven Plugin - Checkstyle report</description>
<language>en-us</language>
<copyright>&#169;2016 - 2019 Spring</copyright>
<item>
<title>File: 11,
Errors: 0,
Warnings: 0,
Infos: 0
</title>
<link>https://github.com/spring-cloud/spring-cloud-contract/checkstyle.html</link>
<description>
<p>Click <a href="https://github.com/spring-cloud/spring-cloud-contract/checkstyle.html">here</a> for the full Checkstyle report.</p>
<table summary="Files" boder="1">
<thead>
<tr>
<th>Files</th>
<th style="width:30px;"><abbr title="Info">I</abbr></th>
<th style="width:30px;"><abbr title="Warning">W</abbr></th>
<th style="width:30px;"><abbr title="Error">E</abbr></th>
</tr>
</thead>
<tbody>
<tr>
<td>
<a href="https://github.com/spring-cloud/spring-cloud-contract/checkstyle.html#org.springframework.cloud.contract.maven.verifier.GenerateTestsMojo.java">org/springframework/cloud/contract/maven/verifier/GenerateTestsMojo.java</a>
</td>
<td>
0
</td>
<td>
0
</td>
<td>
0
</td>
</tr>
<tr>
<td>
<a href="https://github.com/spring-cloud/spring-cloud-contract/checkstyle.html#org.springframework.cloud.contract.maven.verifier.MavenContractsDownloader.java">org/springframework/cloud/contract/maven/verifier/MavenContractsDownloader.java</a>
</td>
<td>
0
</td>
<td>
0
</td>
<td>
0
</td>
</tr>
<tr>
<td>
<a href="https://github.com/spring-cloud/spring-cloud-contract/checkstyle.html#org.springframework.cloud.contract.maven.verifier.GenerateStubsMojo.java">org/springframework/cloud/contract/maven/verifier/GenerateStubsMojo.java</a>
</td>
<td>
0
</td>
<td>
0
</td>
<td>
0
</td>
</tr>
<tr>
<td>
<a href="https://github.com/spring-cloud/spring-cloud-contract/checkstyle.html#org.springframework.cloud.contract.maven.verifier.BaseClassMapping.java">org/springframework/cloud/contract/maven/verifier/BaseClassMapping.java</a>
</td>
<td>
0
</td>
<td>
0
</td>
<td>
0
</td>
</tr>
<tr>
<td>
<a href="https://github.com/spring-cloud/spring-cloud-contract/checkstyle.html#org.springframework.cloud.contract.maven.verifier.stubrunner.AetherStubDownloaderFactory.java">org/springframework/cloud/contract/maven/verifier/stubrunner/AetherStubDownloaderFactory.java</a>
</td>
<td>
0
</td>
<td>
0
</td>
<td>
0
</td>
</tr>
<tr>
<td>
<a href="https://github.com/spring-cloud/spring-cloud-contract/checkstyle.html#org.springframework.cloud.contract.maven.verifier.stubrunner.RemoteStubRunner.java">org/springframework/cloud/contract/maven/verifier/stubrunner/RemoteStubRunner.java</a>
</td>
<td>
0
</td>
<td>
0
</td>
<td>
0
</td>
</tr>
<tr>
<td>
<a href="https://github.com/spring-cloud/spring-cloud-contract/checkstyle.html#org.springframework.cloud.contract.maven.verifier.RunMojo.java">org/springframework/cloud/contract/maven/verifier/RunMojo.java</a>
</td>
<td>
0
</td>
<td>
0
</td>
<td>
0
</td>
</tr>
<tr>
<td>
<a href="https://github.com/spring-cloud/spring-cloud-contract/checkstyle.html#org.springframework.cloud.contract.maven.verifier.CopyContracts.java">org/springframework/cloud/contract/maven/verifier/CopyContracts.java</a>
</td>
<td>
0
</td>
<td>
0
</td>
<td>
0
</td>
</tr>
<tr>
<td>
<a href="https://github.com/spring-cloud/spring-cloud-contract/checkstyle.html#org.springframework.cloud.contract.maven.verifier.stubrunner.LocalStubRunner.java">org/springframework/cloud/contract/maven/verifier/stubrunner/LocalStubRunner.java</a>
</td>
<td>
0
</td>
<td>
0
</td>
<td>
0
</td>
</tr>
<tr>
<td>
<a href="https://github.com/spring-cloud/spring-cloud-contract/checkstyle.html#org.springframework.cloud.contract.maven.verifier.ManifestCreator.java">org/springframework/cloud/contract/maven/verifier/ManifestCreator.java</a>
</td>
<td>
0
</td>
<td>
0
</td>
<td>
0
</td>
</tr>
<tr>
<td>
<a href="https://github.com/spring-cloud/spring-cloud-contract/checkstyle.html#org.springframework.cloud.contract.maven.verifier.ConvertMojo.java">org/springframework/cloud/contract/maven/verifier/ConvertMojo.java</a>
</td>
<td>
0
</td>
<td>
0
</td>
<td>
0
</td>
</tr>
</tbody>
</table>
</description>
</item>
</channel>
</rss>

View File

@@ -0,0 +1,464 @@
<!DOCTYPE html>
<!--
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2019-05-23
| Rendered using Apache Maven Fluido Skin 1.5
-->
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="Date-Revision-yyyymmdd" content="20190523" />
<meta http-equiv="Content-Language" content="en" />
<title>Spring Cloud Contract Maven Plugin &#x2013; </title>
<link rel="stylesheet" href="./css/apache-maven-fluido-1.5.min.css" />
<link rel="stylesheet" href="./css/site.css" />
<link rel="stylesheet" href="./css/print.css" media="print" />
<script type="text/javascript" src="./js/apache-maven-fluido-1.5.min.js"></script>
</head>
<body class="topBarEnabled">
<a href="https://github.com/spring-cloud/spring-cloud-contract">
<img style="position: absolute; top: 0; right: 0; border: 0; z-index: 10000;"
src="https://s3.amazonaws.com/github/ribbons/forkme_right_orange_ff7600.png"
alt="Fork me on GitHub">
</a>
<div id="topbar" class="navbar navbar-fixed-top ">
<div class="navbar-inner">
<div class="container-fluid">
<a data-target=".nav-collapse" data-toggle="collapse" class="btn btn-navbar">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<ul class="nav">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Overview <b class="caret"></b></a>
<ul class="dropdown-menu">
<li> <a href="index.html" title="Introduction">Introduction</a>
</li>
<li> <a href="usage.html" title="Usage">Usage</a>
</li>
<li> <a href="plugin-info.html" title="Goals">Goals</a>
</li>
<li> <a href="junit.html" title="JUnit Configuration">JUnit Configuration</a>
</li>
<li> <a href="spock.html" title="Spock Configuration">Spock Configuration</a>
</li>
<li> <a href="complex.html" title="Complex Configuration">Complex Configuration</a>
</li>
<li> <a href="configs.html" title="Configuration snippets">Configuration snippets</a>
</li>
</ul>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Related Projects <b class="caret"></b></a>
<ul class="dropdown-menu">
<li> <a href="https://github.com/spring-cloud/spring-cloud-contract" title="Spring Cloud Contract">Spring Cloud Contract</a>
</li>
</ul>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Project Documentation <b class="caret"></b></a>
<ul class="dropdown-menu">
<li class="dropdown-submenu">
<a href="project-info.html" title="Project Information">Project Information</a>
<ul class="dropdown-menu">
<li> <a href="integration.html" title="CI Management">CI Management</a>
</li>
<li> <a href="index.html" title="About">About</a>
</li>
<li> <a href="issue-tracking.html" title="Issue Management">Issue Management</a>
</li>
<li> <a href="license.html" title="Licenses">Licenses</a>
</li>
<li> <a href="plugin-management.html" title="Plugin Management">Plugin Management</a>
</li>
<li> <a href="plugins.html" title="Plugins">Plugins</a>
</li>
<li> <a href="team-list.html" title="Team">Team</a>
</li>
<li> <a href="source-repository.html" title="Source Code Management">Source Code Management</a>
</li>
<li> <a href="project-summary.html" title="Summary">Summary</a>
</li>
</ul>
</li>
<li class="dropdown-submenu">
<a href="project-reports.html" title="Project Reports">Project Reports</a>
<ul class="dropdown-menu">
<li> <a href="checkstyle.html" title="Checkstyle">Checkstyle</a>
</li>
<li> <a href="plugin-info.html" title="Plugin Documentation">Plugin Documentation</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="container-fluid">
<div id="banner">
<div class="pull-left">
<div id="bannerLeft">
<h2>Spring Cloud Contract Maven Plugin</h2>
</div>
</div>
<div class="pull-right"> <div id="bannerRight">
<img src="" />
</div>
</div>
<div class="clear"><hr/></div>
</div>
<div id="breadcrumbs">
<ul class="breadcrumb">
<li id="publishDate">Last Published: 2019-05-23
<span class="divider">|</span>
</li>
<li id="projectVersion">Version: 1.2.7.RELEASE
</li>
</ul>
</div>
<div class="row-fluid">
<div id="leftColumn" class="span2">
<div class="well sidebar-nav">
<ul class="nav nav-list">
<li class="nav-header">Overview</li>
<li>
<a href="index.html" title="Introduction">
<span class="none"></span>
Introduction</a>
</li>
<li>
<a href="usage.html" title="Usage">
<span class="none"></span>
Usage</a>
</li>
<li>
<a href="plugin-info.html" title="Goals">
<span class="none"></span>
Goals</a>
</li>
<li>
<a href="junit.html" title="JUnit Configuration">
<span class="none"></span>
JUnit Configuration</a>
</li>
<li>
<a href="spock.html" title="Spock Configuration">
<span class="none"></span>
Spock Configuration</a>
</li>
<li class="active">
<a href="#"><span class="none"></span>Complex Configuration</a>
</li>
<li>
<a href="configs.html" title="Configuration snippets">
<span class="none"></span>
Configuration snippets</a>
</li>
<li class="nav-header">Related Projects</li>
<li>
<a href="https://github.com/spring-cloud/spring-cloud-contract" title="Spring Cloud Contract">
<span class="none"></span>
Spring Cloud Contract</a>
</li>
<li class="nav-header">Project Documentation</li>
<li>
<a href="project-info.html" title="Project Information">
<span class="icon-chevron-right"></span>
Project Information</a>
</li>
<li>
<a href="project-reports.html" title="Project Reports">
<span class="icon-chevron-right"></span>
Project Reports</a>
</li>
</ul>
<hr />
<div id="poweredBy">
<div class="clear"></div>
<div class="clear"></div>
<div class="clear"></div>
<div class="clear"></div>
<a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy">
<img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" />
</a>
</div>
</div>
</div>
<div id="bodyColumn" class="span10" >
<div class="sect1">
<h2 id="more_complex_plugin_configuration">More Complex Plugin Configuration</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Sample more complex configuration for Java Project with JUnit tests.</p>
</div>
<div class="sect2">
<h3 id="project_configuration_for_spring_cloud_contract_verifier_with_junit_tests_and_stub_publishing">Project configuration for Spring Cloud Contract Verifier with JUnit tests and stub publishing</h3>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"> <span style="color:#070;font-weight:bold">&lt;plugin&gt;</span>
<span style="color:#070;font-weight:bold">&lt;groupId&gt;</span>org.springframework.cloud<span style="color:#070;font-weight:bold">&lt;/groupId&gt;</span>
<span style="color:#070;font-weight:bold">&lt;artifactId&gt;</span>spring-cloud-contract-maven-plugin<span style="color:#070;font-weight:bold">&lt;/artifactId&gt;</span>
<span style="color:#070;font-weight:bold">&lt;version&gt;</span>${spring-cloud-verifier-plugin.version}<span style="color:#070;font-weight:bold">&lt;/version&gt;</span>
<span style="color:#070;font-weight:bold">&lt;executions&gt;</span>
<span style="color:#070;font-weight:bold">&lt;execution&gt;</span>
<span style="color:#070;font-weight:bold">&lt;goals&gt;</span>
<span style="color:#070;font-weight:bold">&lt;goal&gt;</span>convert<span style="color:#070;font-weight:bold">&lt;/goal&gt;</span>
<span style="color:#070;font-weight:bold">&lt;goal&gt;</span>generateStubs<span style="color:#070;font-weight:bold">&lt;/goal&gt;</span>
<span style="color:#070;font-weight:bold">&lt;goal&gt;</span>generateTests<span style="color:#070;font-weight:bold">&lt;/goal&gt;</span>
<span style="color:#070;font-weight:bold">&lt;/goals&gt;</span>
<span style="color:#070;font-weight:bold">&lt;configuration&gt;</span>
<span style="color:#070;font-weight:bold">&lt;contractsDirectory&gt;</span>src/test/contracts<span style="color:#070;font-weight:bold">&lt;/contractsDirectory&gt;</span>
<span style="color:#070;font-weight:bold">&lt;basePackageForTests&gt;</span>com.blogspot.toomuchcoding.frauddetection<span style="color:#070;font-weight:bold">&lt;/basePackageForTests&gt;</span>
<span style="color:#070;font-weight:bold">&lt;testMode&gt;</span>MOCKMVC<span style="color:#070;font-weight:bold">&lt;/testMode&gt;</span>
<span style="color:#070;font-weight:bold">&lt;testFramework&gt;</span>JUNIT<span style="color:#070;font-weight:bold">&lt;/testFramework&gt;</span>
<span style="color:#070;font-weight:bold">&lt;classifier&gt;</span>stubs<span style="color:#070;font-weight:bold">&lt;/classifier&gt;</span>
<span style="color:#070;font-weight:bold">&lt;nameSuffixForTests&gt;</span>Test<span style="color:#070;font-weight:bold">&lt;/nameSuffixForTests&gt;</span>
<span style="color:#070;font-weight:bold">&lt;ruleClassForTests&gt;</span>org.junit.rules.ErrorCollector<span style="color:#070;font-weight:bold">&lt;/ruleClassForTests&gt;</span>
<span style="color:#070;font-weight:bold">&lt;staticImports&gt;</span>
<span style="color:#070;font-weight:bold">&lt;staticImport&gt;</span>com.blogspot.toomuchcoding.frauddetection.matchers.CustomMatchers.*<span style="color:#070;font-weight:bold">&lt;/staticImport&gt;</span>
<span style="color:#070;font-weight:bold">&lt;/staticImports&gt;</span>
<span style="color:#070;font-weight:bold">&lt;imports&gt;</span>
<span style="color:#070;font-weight:bold">&lt;import&gt;</span>com.blogspot.toomuchcoding.frauddetection.matchers.CustomMatchers<span style="color:#070;font-weight:bold">&lt;/import&gt;</span>
<span style="color:#070;font-weight:bold">&lt;/imports&gt;</span>
<span style="color:#070;font-weight:bold">&lt;ignoredFiles&gt;</span>
<span style="color:#070;font-weight:bold">&lt;ignoredFile&gt;</span>broken**<span style="color:#070;font-weight:bold">&lt;/ignoredFile&gt;</span>
<span style="color:#070;font-weight:bold">&lt;/ignoredFiles&gt;</span>
<span style="color:#070;font-weight:bold">&lt;excludedFiles&gt;</span>
<span style="color:#070;font-weight:bold">&lt;param&gt;</span>shouldMarkClientAsFraud.groovy<span style="color:#070;font-weight:bold">&lt;/param&gt;</span>
<span style="color:#070;font-weight:bold">&lt;/excludedFiles&gt;</span>
<span style="color:#070;font-weight:bold">&lt;/configuration&gt;</span>
<span style="color:#070;font-weight:bold">&lt;/execution&gt;</span>
<span style="color:#070;font-weight:bold">&lt;/executions&gt;</span>
<span style="color:#070;font-weight:bold">&lt;configuration&gt;</span>
<span style="color:#070;font-weight:bold">&lt;baseClassForTests&gt;</span>com.blogspot.toomuchcoding.frauddetection.BaseAccurest<span style="color:#070;font-weight:bold">&lt;/baseClassForTests&gt;</span>
<span style="color:#070;font-weight:bold">&lt;/configuration&gt;</span>
<span style="color:#070;font-weight:bold">&lt;/plugin&gt;</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="base_test_class">Base Test class</h3>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span style="color:#777">/**
*
* Copyright 2013-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
* 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 &quot;AS IS&quot; BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/</span>
<span style="color:#080;font-weight:bold">package</span> <span style="color:#707;font-weight:bold">com.blogspot.toomuchcoding.frauddetection</span>;
<span style="color:#080;font-weight:bold">import</span> <span style="color:#B44;font-weight:bold">io.restassured.module.mockmvc.RestAssuredMockMvc</span>;
<span style="color:#080;font-weight:bold">import</span> <span style="color:#B44;font-weight:bold">org.junit.Before</span>;
<span style="color:#088;font-weight:bold">public</span> <span style="color:#339;font-weight:bold">class</span> <span style="color:#B06;font-weight:bold">BaseAccurest</span> {
<span style="color:#007">@Before</span>
<span style="color:#088;font-weight:bold">public</span> <span style="color:#339;font-weight:bold">void</span> setup() {
RestAssuredMockMvc.standaloneSetup(<span style="color:#080;font-weight:bold">new</span> FraudDetectionController());
}
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="sample_additional_matcher">Sample additional matcher</h3>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span style="color:#777">/**
*
* Copyright 2013-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
* 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 &quot;AS IS&quot; BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/</span>
<span style="color:#080;font-weight:bold">package</span> <span style="color:#707;font-weight:bold">com.blogspot.toomuchcoding.frauddetection.matchers</span>;
<span style="color:#080;font-weight:bold">import</span> <span style="color:#B44;font-weight:bold">org.junit.Assert</span>;
<span style="color:#088;font-weight:bold">public</span> <span style="color:#339;font-weight:bold">class</span> <span style="color:#B06;font-weight:bold">CustomMatchers</span> {
<span style="color:#088;font-weight:bold">public</span> <span style="color:#088;font-weight:bold">static</span> <span style="color:#339;font-weight:bold">void</span> assertThatRejectionReasonIsNull(<span style="color:#0a8;font-weight:bold">String</span> rejectionReason) {
Assert.assertNull(rejectionReason);
}
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="sample_contract_using_matcher">Sample contract using matcher</h3>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span style="color:#777">/**
*
* Copyright 2013-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
* 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 &quot;AS IS&quot; BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/</span>
org.springframework.cloud.contract.spec.Contract.make {
request {
method <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">'</span><span style="color:#D20">PUT</span><span style="color:#710">'</span></span>
url <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">'</span><span style="color:#D20">/fraudcheck</span><span style="color:#710">'</span></span>
body(<span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">&quot;</span><span style="color:#710">&quot;</span></span><span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">&quot;</span><span style="color:#D20">
{
</span><span style="color:#710">&quot;</span></span>clientPesel<span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">&quot;</span><span style="color:#D20">:</span><span style="color:#710">&quot;</span></span><span style="color:#F00;background-color:#FAA">$</span>{value(consumer(regex(<span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">'</span><span style="color:#D20">[0-9]{10}</span><span style="color:#710">'</span></span>)), producer(<span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">'</span><span style="color:#D20">1234567890</span><span style="color:#710">'</span></span>))}<span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">&quot;</span><span style="color:#D20">,
</span><span style="color:#710">&quot;</span></span>loanAmount<span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">&quot;</span><span style="color:#D20">:123.123
}
</span><span style="color:#710">&quot;</span></span><span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">&quot;</span><span style="color:#710">&quot;</span></span>
)
headers {
header(<span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">'</span><span style="color:#D20">Content-Type</span><span style="color:#710">'</span></span>, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">'</span><span style="color:#D20">application/vnd.fraud.v1+json</span><span style="color:#710">'</span></span>)
}
}
response {
status <span style="color:#00D">200</span>
body(
fraudCheckStatus: <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">&quot;</span><span style="color:#D20">OK</span><span style="color:#710">&quot;</span></span>,
rejectionReason: <span style="color:#F00;background-color:#FAA">$</span>(consumer(<span style="color:#069">null</span>), producer(execute(<span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">'</span><span style="color:#D20">assertThatRejectionReasonIsNull($it)</span><span style="color:#710">'</span></span>)))
)
headers {
header(<span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">'</span><span style="color:#D20">Content-Type</span><span style="color:#710">'</span></span>: <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">'</span><span style="color:#D20">application/vnd.fraud.v1+json</span><span style="color:#710">'</span></span>)
}
}
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="project_source_code">Project source code</h3>
<div class="paragraph">
<p><a href="https://github.com/Codearte/accurest-maven-plugin/tree/master/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/complex-configuration" class="bare">https://github.com/Codearte/accurest-maven-plugin/tree/master/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/complex-configuration</a></p>
</div>
</div>
<div class="sect2">
<h3 id="more_samples">More samples</h3>
<div class="paragraph">
<p>You can check out the <a href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples">Spring Cloud Contract Samples project</a> for
more examples of Maven plugin setup.</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<hr/>
<footer>
<div class="container-fluid">
<div class="row-fluid">
<p >Copyright &copy; 2016&#x2013;2019
<a href="https://spring.io/">Spring</a>.
All rights reserved.
</p>
</div>
</div>
</footer>
</body>
</html>

View File

@@ -0,0 +1,379 @@
<!DOCTYPE html>
<!--
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2019-05-23
| Rendered using Apache Maven Fluido Skin 1.5
-->
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="Date-Revision-yyyymmdd" content="20190523" />
<meta http-equiv="Content-Language" content="en" />
<title>Spring Cloud Contract Maven Plugin &#x2013; </title>
<link rel="stylesheet" href="./css/apache-maven-fluido-1.5.min.css" />
<link rel="stylesheet" href="./css/site.css" />
<link rel="stylesheet" href="./css/print.css" media="print" />
<script type="text/javascript" src="./js/apache-maven-fluido-1.5.min.js"></script>
</head>
<body class="topBarEnabled">
<a href="https://github.com/spring-cloud/spring-cloud-contract">
<img style="position: absolute; top: 0; right: 0; border: 0; z-index: 10000;"
src="https://s3.amazonaws.com/github/ribbons/forkme_right_orange_ff7600.png"
alt="Fork me on GitHub">
</a>
<div id="topbar" class="navbar navbar-fixed-top ">
<div class="navbar-inner">
<div class="container-fluid">
<a data-target=".nav-collapse" data-toggle="collapse" class="btn btn-navbar">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<ul class="nav">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Overview <b class="caret"></b></a>
<ul class="dropdown-menu">
<li> <a href="index.html" title="Introduction">Introduction</a>
</li>
<li> <a href="usage.html" title="Usage">Usage</a>
</li>
<li> <a href="plugin-info.html" title="Goals">Goals</a>
</li>
<li> <a href="junit.html" title="JUnit Configuration">JUnit Configuration</a>
</li>
<li> <a href="spock.html" title="Spock Configuration">Spock Configuration</a>
</li>
<li> <a href="complex.html" title="Complex Configuration">Complex Configuration</a>
</li>
<li> <a href="configs.html" title="Configuration snippets">Configuration snippets</a>
</li>
</ul>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Related Projects <b class="caret"></b></a>
<ul class="dropdown-menu">
<li> <a href="https://github.com/spring-cloud/spring-cloud-contract" title="Spring Cloud Contract">Spring Cloud Contract</a>
</li>
</ul>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Project Documentation <b class="caret"></b></a>
<ul class="dropdown-menu">
<li class="dropdown-submenu">
<a href="project-info.html" title="Project Information">Project Information</a>
<ul class="dropdown-menu">
<li> <a href="integration.html" title="CI Management">CI Management</a>
</li>
<li> <a href="index.html" title="About">About</a>
</li>
<li> <a href="issue-tracking.html" title="Issue Management">Issue Management</a>
</li>
<li> <a href="license.html" title="Licenses">Licenses</a>
</li>
<li> <a href="plugin-management.html" title="Plugin Management">Plugin Management</a>
</li>
<li> <a href="plugins.html" title="Plugins">Plugins</a>
</li>
<li> <a href="team-list.html" title="Team">Team</a>
</li>
<li> <a href="source-repository.html" title="Source Code Management">Source Code Management</a>
</li>
<li> <a href="project-summary.html" title="Summary">Summary</a>
</li>
</ul>
</li>
<li class="dropdown-submenu">
<a href="project-reports.html" title="Project Reports">Project Reports</a>
<ul class="dropdown-menu">
<li> <a href="checkstyle.html" title="Checkstyle">Checkstyle</a>
</li>
<li> <a href="plugin-info.html" title="Plugin Documentation">Plugin Documentation</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="container-fluid">
<div id="banner">
<div class="pull-left">
<div id="bannerLeft">
<h2>Spring Cloud Contract Maven Plugin</h2>
</div>
</div>
<div class="pull-right"> <div id="bannerRight">
<img src="" />
</div>
</div>
<div class="clear"><hr/></div>
</div>
<div id="breadcrumbs">
<ul class="breadcrumb">
<li id="publishDate">Last Published: 2019-05-23
<span class="divider">|</span>
</li>
<li id="projectVersion">Version: 1.2.7.RELEASE
</li>
</ul>
</div>
<div class="row-fluid">
<div id="leftColumn" class="span2">
<div class="well sidebar-nav">
<ul class="nav nav-list">
<li class="nav-header">Overview</li>
<li>
<a href="index.html" title="Introduction">
<span class="none"></span>
Introduction</a>
</li>
<li>
<a href="usage.html" title="Usage">
<span class="none"></span>
Usage</a>
</li>
<li>
<a href="plugin-info.html" title="Goals">
<span class="none"></span>
Goals</a>
</li>
<li>
<a href="junit.html" title="JUnit Configuration">
<span class="none"></span>
JUnit Configuration</a>
</li>
<li>
<a href="spock.html" title="Spock Configuration">
<span class="none"></span>
Spock Configuration</a>
</li>
<li>
<a href="complex.html" title="Complex Configuration">
<span class="none"></span>
Complex Configuration</a>
</li>
<li class="active">
<a href="#"><span class="none"></span>Configuration snippets</a>
</li>
<li class="nav-header">Related Projects</li>
<li>
<a href="https://github.com/spring-cloud/spring-cloud-contract" title="Spring Cloud Contract">
<span class="none"></span>
Spring Cloud Contract</a>
</li>
<li class="nav-header">Project Documentation</li>
<li>
<a href="project-info.html" title="Project Information">
<span class="icon-chevron-right"></span>
Project Information</a>
</li>
<li>
<a href="project-reports.html" title="Project Reports">
<span class="icon-chevron-right"></span>
Project Reports</a>
</li>
</ul>
<hr />
<div id="poweredBy">
<div class="clear"></div>
<div class="clear"></div>
<div class="clear"></div>
<div class="clear"></div>
<a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy">
<img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" />
</a>
</div>
</div>
</div>
<div id="bodyColumn" class="span10" >
<div class="sect1">
<h2 id="configuration_snippets">Configuration snippets</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Here you&#8217;ll be able to see different Spring Cloud Contract Maven plugin configuration</p>
</div>
<div class="sect2">
<h3 id="base_class_from_mappings">Base class from mappings</h3>
<div class="paragraph">
<p>Define regular expression mappings to map a contract to its base class.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"> <span style="color:#070;font-weight:bold">&lt;plugin&gt;</span>
<span style="color:#070;font-weight:bold">&lt;groupId&gt;</span>org.springframework.cloud<span style="color:#070;font-weight:bold">&lt;/groupId&gt;</span>
<span style="color:#070;font-weight:bold">&lt;artifactId&gt;</span>spring-cloud-contract-maven-plugin<span style="color:#070;font-weight:bold">&lt;/artifactId&gt;</span>
<span style="color:#070;font-weight:bold">&lt;configuration&gt;</span>
<span style="color:#070;font-weight:bold">&lt;baseClassForTests&gt;</span>com.example.FooBase<span style="color:#070;font-weight:bold">&lt;/baseClassForTests&gt;</span>
<span style="color:#070;font-weight:bold">&lt;baseClassMappings&gt;</span>
<span style="color:#070;font-weight:bold">&lt;baseClassMapping&gt;</span>
<span style="color:#070;font-weight:bold">&lt;contractPackageRegex&gt;</span>.*com.*<span style="color:#070;font-weight:bold">&lt;/contractPackageRegex&gt;</span>
<span style="color:#070;font-weight:bold">&lt;baseClassFQN&gt;</span>com.example.TestBase<span style="color:#070;font-weight:bold">&lt;/baseClassFQN&gt;</span>
<span style="color:#070;font-weight:bold">&lt;/baseClassMapping&gt;</span>
<span style="color:#070;font-weight:bold">&lt;/baseClassMappings&gt;</span>
<span style="color:#070;font-weight:bold">&lt;/configuration&gt;</span>
<span style="color:#070;font-weight:bold">&lt;/plugin&gt;</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="convention_based_mappings">Convention based mappings</h3>
<div class="paragraph">
<p>Define a package in which base classes are placed. In this case we define
a package called <code>hello</code>. If there&#8217;s a contract under /contracts/hello/V1/Contract.groovy` then
we&#8217;ll search for a <code>HelloV1Base</code> base class. We&#8217;re taking two last folders
from the path and combine them into a class name.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"> <span style="color:#070;font-weight:bold">&lt;plugin&gt;</span>
<span style="color:#070;font-weight:bold">&lt;groupId&gt;</span>org.springframework.cloud<span style="color:#070;font-weight:bold">&lt;/groupId&gt;</span>
<span style="color:#070;font-weight:bold">&lt;artifactId&gt;</span>spring-cloud-contract-maven-plugin<span style="color:#070;font-weight:bold">&lt;/artifactId&gt;</span>
<span style="color:#070;font-weight:bold">&lt;configuration&gt;</span>
<span style="color:#070;font-weight:bold">&lt;packageWithBaseClasses&gt;</span>hello<span style="color:#070;font-weight:bold">&lt;/packageWithBaseClasses&gt;</span>
<span style="color:#070;font-weight:bold">&lt;/configuration&gt;</span>
<span style="color:#070;font-weight:bold">&lt;/plugin&gt;</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="remote_contracts">Remote contracts</h3>
<div class="paragraph">
<p>Here you can see a setup where we point to a repository where the JAR with the
contracts got deployed.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"> <span style="color:#070;font-weight:bold">&lt;plugin&gt;</span>
<span style="color:#070;font-weight:bold">&lt;groupId&gt;</span>org.springframework.cloud<span style="color:#070;font-weight:bold">&lt;/groupId&gt;</span>
<span style="color:#070;font-weight:bold">&lt;artifactId&gt;</span>spring-cloud-contract-maven-plugin<span style="color:#070;font-weight:bold">&lt;/artifactId&gt;</span>
<span style="color:#070;font-weight:bold">&lt;configuration&gt;</span>
<span style="color:#070;font-weight:bold">&lt;contractsRepositoryUrl&gt;</span>http://link/to/your/nexus/or/artifactory/or/sth<span style="color:#070;font-weight:bold">&lt;/contractsRepositoryUrl&gt;</span>
<span style="color:#070;font-weight:bold">&lt;contractDependency&gt;</span>
<span style="color:#070;font-weight:bold">&lt;groupId&gt;</span>com.example.standalone<span style="color:#070;font-weight:bold">&lt;/groupId&gt;</span>
<span style="color:#070;font-weight:bold">&lt;artifactId&gt;</span>contracts<span style="color:#070;font-weight:bold">&lt;/artifactId&gt;</span>
<span style="color:#070;font-weight:bold">&lt;/contractDependency&gt;</span>
<span style="color:#070;font-weight:bold">&lt;/configuration&gt;</span>
<span style="color:#070;font-weight:bold">&lt;/plugin&gt;</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="setting_up_repo_with_common_contracts">Setting up repo with common contracts</h3>
<div class="paragraph">
<p>A setup of a repo that contains all common contracts. It can exclude the target / build
folder that gets created when you&#8217;re installing stubs locally as a consumer.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"> <span style="color:#070;font-weight:bold">&lt;properties&gt;</span>
<span style="color:#777">&lt;!-- We don't want the tests to be executed cause we're just build stubs --&gt;</span>
<span style="color:#070;font-weight:bold">&lt;skipTests&gt;</span>true<span style="color:#070;font-weight:bold">&lt;/skipTests&gt;</span>
<span style="color:#777">&lt;!-- The target / build folder needs to be excluded - we don't want to check its contents --&gt;</span>
<span style="color:#070;font-weight:bold">&lt;excludeBuildFolders&gt;</span>true<span style="color:#070;font-weight:bold">&lt;/excludeBuildFolders&gt;</span>
<span style="color:#070;font-weight:bold">&lt;/properties&gt;</span>
<span style="color:#070;font-weight:bold">&lt;build&gt;</span>
<span style="color:#070;font-weight:bold">&lt;plugins&gt;</span>
<span style="color:#070;font-weight:bold">&lt;plugin&gt;</span>
<span style="color:#070;font-weight:bold">&lt;groupId&gt;</span>org.springframework.cloud<span style="color:#070;font-weight:bold">&lt;/groupId&gt;</span>
<span style="color:#070;font-weight:bold">&lt;artifactId&gt;</span>spring-cloud-contract-maven-plugin<span style="color:#070;font-weight:bold">&lt;/artifactId&gt;</span>
<span style="color:#070;font-weight:bold">&lt;configuration&gt;</span>
<span style="color:#777">&lt;!-- By default it would search under src/test/resources/ --&gt;</span>
<span style="color:#070;font-weight:bold">&lt;contractsDirectory&gt;</span>${project.basedir}<span style="color:#070;font-weight:bold">&lt;/contractsDirectory&gt;</span>
<span style="color:#070;font-weight:bold">&lt;/configuration&gt;</span>
<span style="color:#070;font-weight:bold">&lt;/plugin&gt;</span>
<span style="color:#070;font-weight:bold">&lt;/plugins&gt;</span>
<span style="color:#070;font-weight:bold">&lt;/build&gt;</span></code></pre>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<hr/>
<footer>
<div class="container-fluid">
<div class="row-fluid">
<p >Copyright &copy; 2016&#x2013;2019
<a href="https://spring.io/">Spring</a>.
All rights reserved.
</p>
</div>
</div>
</footer>
</body>
</html>

View File

@@ -0,0 +1,697 @@
<!DOCTYPE html>
<!--
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2019-05-23
| Rendered using Apache Maven Fluido Skin 1.5
-->
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="Date-Revision-yyyymmdd" content="20190523" />
<meta http-equiv="Content-Language" content="en" />
<title>Spring Cloud Contract Maven Plugin &#x2013; spring-cloud-contract:convert</title>
<link rel="stylesheet" href="./css/apache-maven-fluido-1.5.min.css" />
<link rel="stylesheet" href="./css/site.css" />
<link rel="stylesheet" href="./css/print.css" media="print" />
<script type="text/javascript" src="./js/apache-maven-fluido-1.5.min.js"></script>
</head>
<body class="topBarEnabled">
<a href="https://github.com/spring-cloud/spring-cloud-contract">
<img style="position: absolute; top: 0; right: 0; border: 0; z-index: 10000;"
src="https://s3.amazonaws.com/github/ribbons/forkme_right_orange_ff7600.png"
alt="Fork me on GitHub">
</a>
<div id="topbar" class="navbar navbar-fixed-top ">
<div class="navbar-inner">
<div class="container-fluid">
<a data-target=".nav-collapse" data-toggle="collapse" class="btn btn-navbar">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<ul class="nav">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Overview <b class="caret"></b></a>
<ul class="dropdown-menu">
<li> <a href="index.html" title="Introduction">Introduction</a>
</li>
<li> <a href="usage.html" title="Usage">Usage</a>
</li>
<li> <a href="plugin-info.html" title="Goals">Goals</a>
</li>
<li> <a href="junit.html" title="JUnit Configuration">JUnit Configuration</a>
</li>
<li> <a href="spock.html" title="Spock Configuration">Spock Configuration</a>
</li>
<li> <a href="complex.html" title="Complex Configuration">Complex Configuration</a>
</li>
<li> <a href="configs.html" title="Configuration snippets">Configuration snippets</a>
</li>
</ul>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Related Projects <b class="caret"></b></a>
<ul class="dropdown-menu">
<li> <a href="https://github.com/spring-cloud/spring-cloud-contract" title="Spring Cloud Contract">Spring Cloud Contract</a>
</li>
</ul>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Project Documentation <b class="caret"></b></a>
<ul class="dropdown-menu">
<li class="dropdown-submenu">
<a href="project-info.html" title="Project Information">Project Information</a>
<ul class="dropdown-menu">
<li> <a href="integration.html" title="CI Management">CI Management</a>
</li>
<li> <a href="index.html" title="About">About</a>
</li>
<li> <a href="issue-tracking.html" title="Issue Management">Issue Management</a>
</li>
<li> <a href="license.html" title="Licenses">Licenses</a>
</li>
<li> <a href="plugin-management.html" title="Plugin Management">Plugin Management</a>
</li>
<li> <a href="plugins.html" title="Plugins">Plugins</a>
</li>
<li> <a href="team-list.html" title="Team">Team</a>
</li>
<li> <a href="source-repository.html" title="Source Code Management">Source Code Management</a>
</li>
<li> <a href="project-summary.html" title="Summary">Summary</a>
</li>
</ul>
</li>
<li class="dropdown-submenu">
<a href="project-reports.html" title="Project Reports">Project Reports</a>
<ul class="dropdown-menu">
<li> <a href="checkstyle.html" title="Checkstyle">Checkstyle</a>
</li>
<li> <a href="plugin-info.html" title="Plugin Documentation">Plugin Documentation</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="container-fluid">
<div id="banner">
<div class="pull-left">
<div id="bannerLeft">
<h2>Spring Cloud Contract Maven Plugin</h2>
</div>
</div>
<div class="pull-right"> <div id="bannerRight">
<img src="" />
</div>
</div>
<div class="clear"><hr/></div>
</div>
<div id="breadcrumbs">
<ul class="breadcrumb">
<li id="publishDate">Last Published: 2019-05-23
<span class="divider">|</span>
</li>
<li id="projectVersion">Version: 1.2.7.RELEASE
</li>
</ul>
</div>
<div class="row-fluid">
<div id="leftColumn" class="span2">
<div class="well sidebar-nav">
<ul class="nav nav-list">
<li class="nav-header">Overview</li>
<li>
<a href="index.html" title="Introduction">
<span class="none"></span>
Introduction</a>
</li>
<li>
<a href="usage.html" title="Usage">
<span class="none"></span>
Usage</a>
</li>
<li>
<a href="plugin-info.html" title="Goals">
<span class="none"></span>
Goals</a>
</li>
<li>
<a href="junit.html" title="JUnit Configuration">
<span class="none"></span>
JUnit Configuration</a>
</li>
<li>
<a href="spock.html" title="Spock Configuration">
<span class="none"></span>
Spock Configuration</a>
</li>
<li>
<a href="complex.html" title="Complex Configuration">
<span class="none"></span>
Complex Configuration</a>
</li>
<li>
<a href="configs.html" title="Configuration snippets">
<span class="none"></span>
Configuration snippets</a>
</li>
<li class="nav-header">Related Projects</li>
<li>
<a href="https://github.com/spring-cloud/spring-cloud-contract" title="Spring Cloud Contract">
<span class="none"></span>
Spring Cloud Contract</a>
</li>
<li class="nav-header">Project Documentation</li>
<li>
<a href="project-info.html" title="Project Information">
<span class="icon-chevron-right"></span>
Project Information</a>
</li>
<li>
<a href="project-reports.html" title="Project Reports">
<span class="icon-chevron-right"></span>
Project Reports</a>
</li>
</ul>
<hr />
<div id="poweredBy">
<div class="clear"></div>
<div class="clear"></div>
<div class="clear"></div>
<div class="clear"></div>
<a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy">
<img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" />
</a>
</div>
</div>
</div>
<div id="bodyColumn" class="span10" >
<div class="section">
<h2><a name="spring-cloud-contract:convert"></a>spring-cloud-contract:convert</h2>
<p><b>Full name</b>:</p>
<p>org.springframework.cloud:spring-cloud-contract-maven-plugin:1.2.7.RELEASE:convert</p>
<p><b>Description</b>:</p>
<div>Convert Spring Cloud Contract Verifier contracts into WireMock
stubs mappings.
<p>This goal allows you to generate `stubs-jar` or execute
`spring-cloud-contract:run` with generated WireMock mappings.</p></div>
<p><b>Attributes</b>:</p>
<ul>
<li>Binds by default to the <a class="externalLink" href="http://maven.apache.org/ref/current/maven-core/lifecycles.html">lifecycle phase</a>: <tt>process-test-resources</tt>.</li>
</ul>
<div class="section">
<h3><a name="Optional_Parameters"></a>Optional Parameters</h3>
<table class="table table-striped" border="0">
<tr class="a">
<th>Name</th>
<th>Type</th>
<th>Since</th>
<th>Description</th>
</tr>
<tr class="b">
<td><b><a href="#contractDependency">contractDependency</a></b></td>
<td><tt>Dependency</tt></td>
<td><tt>-</tt></td>
<td>(no description)<br /><b>User property is</b>: <tt>contractDependency</tt>.</td>
</tr>
<tr class="a">
<td><b><a href="#contractsDirectory">contractsDirectory</a></b></td>
<td><tt>File</tt></td>
<td><tt>-</tt></td>
<td>Directory containing Spring Cloud Contract Verifier contracts
written using the GroovyDSL<br /><b>Default value is</b>: <tt>${project.basedir}/src/test/resources/contracts</tt>.<br /><b>User property is</b>: <tt>spring.cloud.contract.verifier.contractsDirectory</tt>.</td>
</tr>
<tr class="b">
<td><b><a href="#contractsPath">contractsPath</a></b></td>
<td><tt>String</tt></td>
<td><tt>-</tt></td>
<td>The path in the JAR with all the contracts where contracts for this
particular service lay. If not provided will be resolved to
<tt>groupid/artifactid</tt>. Example: <br />
<br />
If <tt>groupid</tt> is <tt>com.example</tt> and
<tt>artifactid</tt> is <tt>service</tt> then the resolved
path will be <tt>/com/example/artifactid</tt><br /><b>User property is</b>: <tt>contractsPath</tt>.</td>
</tr>
<tr class="a">
<td><b><a href="#contractsRepositoryPassword">contractsRepositoryPassword</a></b></td>
<td><tt>String</tt></td>
<td><tt>-</tt></td>
<td>The password to be used to connect to the repo with contracts.<br /><b>User property is</b>: <tt>contractsRepositoryPassword</tt>.</td>
</tr>
<tr class="b">
<td><b><a href="#contractsRepositoryProxyHost">contractsRepositoryProxyHost</a></b></td>
<td><tt>String</tt></td>
<td><tt>-</tt></td>
<td>The proxy host to be used to connect to the repo with contracts.<br /><b>User property is</b>: <tt>contractsRepositoryProxyHost</tt>.</td>
</tr>
<tr class="a">
<td><b><a href="#contractsRepositoryProxyPort">contractsRepositoryProxyPort</a></b></td>
<td><tt>Integer</tt></td>
<td><tt>-</tt></td>
<td>The proxy port to be used to connect to the repo with contracts.<br /><b>User property is</b>: <tt>contractsRepositoryProxyPort</tt>.</td>
</tr>
<tr class="b">
<td><b><a href="#contractsRepositoryUrl">contractsRepositoryUrl</a></b></td>
<td><tt>String</tt></td>
<td><tt>-</tt></td>
<td>The URL from which a JAR containing the contracts should get
downloaded. If not provided but artifactid / coordinates notation
was provided then the current Maven's build repositories will be
taken into consideration<br /><b>User property is</b>: <tt>contractsRepositoryUrl</tt>.</td>
</tr>
<tr class="a">
<td><b><a href="#contractsRepositoryUsername">contractsRepositoryUsername</a></b></td>
<td><tt>String</tt></td>
<td><tt>-</tt></td>
<td>The user name to be used to connect to the repo with contracts.<br /><b>User property is</b>: <tt>contractsRepositoryUsername</tt>.</td>
</tr>
<tr class="b">
<td><b><a href="#contractsWorkOffline">contractsWorkOffline</a></b></td>
<td><tt>boolean</tt></td>
<td><tt>-</tt></td>
<td>If <tt>true</tt> then JAR with contracts will be taken from
local maven repository<br /><b>Default value is</b>: <tt>false</tt>.<br /><b>User property is</b>: <tt>contractsWorkOffline</tt>.</td>
</tr>
<tr class="a">
<td><b><a href="#destination">destination</a></b></td>
<td><tt>File</tt></td>
<td><tt>-</tt></td>
<td>(no description)<br /><b>Default value is</b>: <tt>${basedir}</tt>.<br /><b>User property is</b>: <tt>stubsDirectory</tt>.</td>
</tr>
<tr class="b">
<td><b><a href="#excludeBuildFolders">excludeBuildFolders</a></b></td>
<td><tt>boolean</tt></td>
<td><tt>-</tt></td>
<td>If <tt>true</tt> then any file laying in a path that contains
<tt>build</tt> or <tt>target</tt> will get excluded in
further processing.<br /><b>Default value is</b>: <tt>false</tt>.<br /><b>User property is</b>: <tt>excludeBuildFolders</tt>.</td>
</tr>
<tr class="a">
<td><b><a href="#skip">skip</a></b></td>
<td><tt>boolean</tt></td>
<td><tt>-</tt></td>
<td>(no description)<br /><b>Default value is</b>: <tt>false</tt>.<br /><b>User property is</b>: <tt>spring.cloud.contract.verifier.skip</tt>.</td>
</tr>
<tr class="b">
<td><b><a href="#source">source</a></b></td>
<td><tt>File</tt></td>
<td><tt>-</tt></td>
<td>Directory containing contracts written using the GroovyDSL
<p>This parameter is only used when goal is executed outside of
maven project.</p><br /><b>Default value is</b>: <tt>${basedir}</tt>.<br /><b>User property is</b>: <tt>contractsDirectory</tt>.</td>
</tr>
<tr class="a">
<td><b><a href="#stubsDirectory">stubsDirectory</a></b></td>
<td><tt>File</tt></td>
<td><tt>-</tt></td>
<td>Directory where the generated WireMock stubs from Groovy DSL should
be placed. You can then mention them in your packaging task to
create jar with stubs<br /><b>Default value is</b>: <tt>${project.build.directory}/stubs/</tt>.<br /></td>
</tr>
</table>
</div>
<div class="section">
<h3><a name="Parameter_Details"></a>Parameter Details</h3>
<p><b><a name="contractDependency">contractDependency</a>:</b></p>
<div>(no description)</div>
<ul>
<li><b>Type</b>: <tt>org.apache.maven.model.Dependency</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>User Property</b>: <tt>contractDependency</tt></li>
</ul><hr />
<p><b><a name="contractsDirectory">contractsDirectory</a>:</b></p>
<div>Directory containing Spring Cloud Contract Verifier contracts
written using the GroovyDSL</div>
<ul>
<li><b>Type</b>: <tt>java.io.File</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>User Property</b>: <tt>spring.cloud.contract.verifier.contractsDirectory</tt></li>
<li><b>Default</b>: <tt>${project.basedir}/src/test/resources/contracts</tt></li>
</ul><hr />
<p><b><a name="contractsPath">contractsPath</a>:</b></p>
<div>The path in the JAR with all the contracts where contracts for this
particular service lay. If not provided will be resolved to
<tt>groupid/artifactid</tt>. Example: <br />
<br />
If <tt>groupid</tt> is <tt>com.example</tt> and
<tt>artifactid</tt> is <tt>service</tt> then the resolved
path will be <tt>/com/example/artifactid</tt></div>
<ul>
<li><b>Type</b>: <tt>java.lang.String</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>User Property</b>: <tt>contractsPath</tt></li>
</ul><hr />
<p><b><a name="contractsRepositoryPassword">contractsRepositoryPassword</a>:</b></p>
<div>The password to be used to connect to the repo with contracts.</div>
<ul>
<li><b>Type</b>: <tt>java.lang.String</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>User Property</b>: <tt>contractsRepositoryPassword</tt></li>
</ul><hr />
<p><b><a name="contractsRepositoryProxyHost">contractsRepositoryProxyHost</a>:</b></p>
<div>The proxy host to be used to connect to the repo with contracts.</div>
<ul>
<li><b>Type</b>: <tt>java.lang.String</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>User Property</b>: <tt>contractsRepositoryProxyHost</tt></li>
</ul><hr />
<p><b><a name="contractsRepositoryProxyPort">contractsRepositoryProxyPort</a>:</b></p>
<div>The proxy port to be used to connect to the repo with contracts.</div>
<ul>
<li><b>Type</b>: <tt>java.lang.Integer</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>User Property</b>: <tt>contractsRepositoryProxyPort</tt></li>
</ul><hr />
<p><b><a name="contractsRepositoryUrl">contractsRepositoryUrl</a>:</b></p>
<div>The URL from which a JAR containing the contracts should get
downloaded. If not provided but artifactid / coordinates notation
was provided then the current Maven's build repositories will be
taken into consideration</div>
<ul>
<li><b>Type</b>: <tt>java.lang.String</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>User Property</b>: <tt>contractsRepositoryUrl</tt></li>
</ul><hr />
<p><b><a name="contractsRepositoryUsername">contractsRepositoryUsername</a>:</b></p>
<div>The user name to be used to connect to the repo with contracts.</div>
<ul>
<li><b>Type</b>: <tt>java.lang.String</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>User Property</b>: <tt>contractsRepositoryUsername</tt></li>
</ul><hr />
<p><b><a name="contractsWorkOffline">contractsWorkOffline</a>:</b></p>
<div>If <tt>true</tt> then JAR with contracts will be taken from
local maven repository</div>
<ul>
<li><b>Type</b>: <tt>boolean</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>User Property</b>: <tt>contractsWorkOffline</tt></li>
<li><b>Default</b>: <tt>false</tt></li>
</ul><hr />
<p><b><a name="destination">destination</a>:</b></p>
<div>(no description)</div>
<ul>
<li><b>Type</b>: <tt>java.io.File</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>User Property</b>: <tt>stubsDirectory</tt></li>
<li><b>Default</b>: <tt>${basedir}</tt></li>
</ul><hr />
<p><b><a name="excludeBuildFolders">excludeBuildFolders</a>:</b></p>
<div>If <tt>true</tt> then any file laying in a path that contains
<tt>build</tt> or <tt>target</tt> will get excluded in
further processing.</div>
<ul>
<li><b>Type</b>: <tt>boolean</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>User Property</b>: <tt>excludeBuildFolders</tt></li>
<li><b>Default</b>: <tt>false</tt></li>
</ul><hr />
<p><b><a name="skip">skip</a>:</b></p>
<div>(no description)</div>
<ul>
<li><b>Type</b>: <tt>boolean</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>User Property</b>: <tt>spring.cloud.contract.verifier.skip</tt></li>
<li><b>Default</b>: <tt>false</tt></li>
</ul><hr />
<p><b><a name="source">source</a>:</b></p>
<div>Directory containing contracts written using the GroovyDSL
<p>This parameter is only used when goal is executed outside of
maven project.</p></div>
<ul>
<li><b>Type</b>: <tt>java.io.File</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>User Property</b>: <tt>contractsDirectory</tt></li>
<li><b>Default</b>: <tt>${basedir}</tt></li>
</ul><hr />
<p><b><a name="stubsDirectory">stubsDirectory</a>:</b></p>
<div>Directory where the generated WireMock stubs from Groovy DSL should
be placed. You can then mention them in your packaging task to
create jar with stubs</div>
<ul>
<li><b>Type</b>: <tt>java.io.File</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>Default</b>: <tt>${project.build.directory}/stubs/</tt></li>
</ul>
</div>
</div>
</div>
</div>
</div>
<hr/>
<footer>
<div class="container-fluid">
<div class="row-fluid">
<p >Copyright &copy; 2016&#x2013;2019
<a href="https://spring.io/">Spring</a>.
All rights reserved.
</p>
</div>
</div>
</footer>
</body>
</html>

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,23 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* $Id: print.css 1201871 2011-11-14 20:18:24Z simonetripodi $ */
#banner, #footer, #leftcol, #breadcrumbs, .docs #toc, .docs .courtesylinks, #leftColumn, #navColumn {display: none !important;}
#bodyColumn, body.docs div.docs {margin: 0 !important;border: none !important}

View File

@@ -0,0 +1 @@
/* You can override this file with your own styles */

View File

@@ -0,0 +1,229 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg">
<metadata></metadata>
<defs>
<font id="glyphicons_halflingsregular" horiz-adv-x="1200" >
<font-face units-per-em="1200" ascent="960" descent="-240" />
<missing-glyph horiz-adv-x="500" />
<glyph />
<glyph />
<glyph unicode="&#xd;" />
<glyph unicode=" " />
<glyph unicode="*" d="M100 500v200h259l-183 183l141 141l183 -183v259h200v-259l183 183l141 -141l-183 -183h259v-200h-259l183 -183l-141 -141l-183 183v-259h-200v259l-183 -183l-141 141l183 183h-259z" />
<glyph unicode="+" d="M0 400v300h400v400h300v-400h400v-300h-400v-400h-300v400h-400z" />
<glyph unicode="&#xa0;" />
<glyph unicode="&#x2000;" horiz-adv-x="652" />
<glyph unicode="&#x2001;" horiz-adv-x="1304" />
<glyph unicode="&#x2002;" horiz-adv-x="652" />
<glyph unicode="&#x2003;" horiz-adv-x="1304" />
<glyph unicode="&#x2004;" horiz-adv-x="434" />
<glyph unicode="&#x2005;" horiz-adv-x="326" />
<glyph unicode="&#x2006;" horiz-adv-x="217" />
<glyph unicode="&#x2007;" horiz-adv-x="217" />
<glyph unicode="&#x2008;" horiz-adv-x="163" />
<glyph unicode="&#x2009;" horiz-adv-x="260" />
<glyph unicode="&#x200a;" horiz-adv-x="72" />
<glyph unicode="&#x202f;" horiz-adv-x="260" />
<glyph unicode="&#x205f;" horiz-adv-x="326" />
<glyph unicode="&#x20ac;" d="M100 500l100 100h113q0 47 5 100h-218l100 100h135q37 167 112 257q117 141 297 141q242 0 354 -189q60 -103 66 -209h-181q0 55 -25.5 99t-63.5 68t-75 36.5t-67 12.5q-24 0 -52.5 -10t-62.5 -32t-65.5 -67t-50.5 -107h379l-100 -100h-300q-6 -46 -6 -100h406l-100 -100 h-300q9 -74 33 -132t52.5 -91t62 -54.5t59 -29t46.5 -7.5q29 0 66 13t75 37t63.5 67.5t25.5 96.5h174q-31 -172 -128 -278q-107 -117 -274 -117q-205 0 -324 158q-36 46 -69 131.5t-45 205.5h-217z" />
<glyph unicode="&#x2212;" d="M200 400h900v300h-900v-300z" />
<glyph unicode="&#x2601;" d="M-14 494q0 -80 56.5 -137t135.5 -57h750q120 0 205 86t85 208q0 120 -85 206.5t-205 86.5q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5z" />
<glyph unicode="&#x2709;" d="M0 100l400 400l200 -200l200 200l400 -400h-1200zM0 300v600l300 -300zM0 1100l600 -603l600 603h-1200zM900 600l300 300v-600z" />
<glyph unicode="&#x270f;" d="M-13 -13l333 112l-223 223zM187 403l214 -214l614 614l-214 214zM887 1103l214 -214l99 92q13 13 13 32.5t-13 33.5l-153 153q-15 13 -33 13t-33 -13z" />
<glyph unicode="&#xe000;" horiz-adv-x="500" d="M0 0z" />
<glyph unicode="&#xe001;" d="M0 1200h1200l-500 -550v-550h300v-100h-800v100h300v550z" />
<glyph unicode="&#xe002;" d="M14 84q18 -55 86 -75.5t147 5.5q65 21 109 69t44 90v606l600 155v-521q-64 16 -138 -7q-79 -26 -122.5 -83t-25.5 -111q17 -55 85.5 -75.5t147.5 4.5q70 23 111.5 63.5t41.5 95.5v881q0 10 -7 15.5t-17 2.5l-752 -193q-10 -3 -17 -12.5t-7 -19.5v-689q-64 17 -138 -7 q-79 -25 -122.5 -82t-25.5 -112z" />
<glyph unicode="&#xe003;" d="M23 693q0 200 142 342t342 142t342 -142t142 -342q0 -142 -78 -261l300 -300q7 -8 7 -18t-7 -18l-109 -109q-8 -7 -18 -7t-18 7l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342zM176 693q0 -136 97 -233t234 -97t233.5 96.5t96.5 233.5t-96.5 233.5t-233.5 96.5 t-234 -97t-97 -233z" />
<glyph unicode="&#xe005;" d="M100 784q0 64 28 123t73 100.5t104.5 64t119 20.5t120 -38.5t104.5 -104.5q48 69 109.5 105t121.5 38t118.5 -20.5t102.5 -64t71 -100.5t27 -123q0 -57 -33.5 -117.5t-94 -124.5t-126.5 -127.5t-150 -152.5t-146 -174q-62 85 -145.5 174t-149.5 152.5t-126.5 127.5 t-94 124.5t-33.5 117.5z" />
<glyph unicode="&#xe006;" d="M-72 800h479l146 400h2l146 -400h472l-382 -278l145 -449l-384 275l-382 -275l146 447zM168 71l2 1z" />
<glyph unicode="&#xe007;" d="M-72 800h479l146 400h2l146 -400h472l-382 -278l145 -449l-384 275l-382 -275l146 447zM168 71l2 1zM237 700l196 -142l-73 -226l192 140l195 -141l-74 229l193 140h-235l-77 211l-78 -211h-239z" />
<glyph unicode="&#xe008;" d="M0 0v143l400 257v100q-37 0 -68.5 74.5t-31.5 125.5v200q0 124 88 212t212 88t212 -88t88 -212v-200q0 -51 -31.5 -125.5t-68.5 -74.5v-100l400 -257v-143h-1200z" />
<glyph unicode="&#xe009;" d="M0 0v1100h1200v-1100h-1200zM100 100h100v100h-100v-100zM100 300h100v100h-100v-100zM100 500h100v100h-100v-100zM100 700h100v100h-100v-100zM100 900h100v100h-100v-100zM300 100h600v400h-600v-400zM300 600h600v400h-600v-400zM1000 100h100v100h-100v-100z M1000 300h100v100h-100v-100zM1000 500h100v100h-100v-100zM1000 700h100v100h-100v-100zM1000 900h100v100h-100v-100z" />
<glyph unicode="&#xe010;" d="M0 50v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5zM0 650v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5zM600 50v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5zM600 650v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400 q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5z" />
<glyph unicode="&#xe011;" d="M0 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM0 450v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200 q-21 0 -35.5 14.5t-14.5 35.5zM0 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5 t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 450v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5 v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM800 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM800 450v200q0 21 14.5 35.5t35.5 14.5h200 q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM800 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5z" />
<glyph unicode="&#xe012;" d="M0 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM0 450q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v200q0 21 -14.5 35.5t-35.5 14.5h-200q-21 0 -35.5 -14.5 t-14.5 -35.5v-200zM0 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 50v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5 t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5zM400 450v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5zM400 850v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5 v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5z" />
<glyph unicode="&#xe013;" d="M29 454l419 -420l818 820l-212 212l-607 -607l-206 207z" />
<glyph unicode="&#xe014;" d="M106 318l282 282l-282 282l212 212l282 -282l282 282l212 -212l-282 -282l282 -282l-212 -212l-282 282l-282 -282z" />
<glyph unicode="&#xe015;" d="M23 693q0 200 142 342t342 142t342 -142t142 -342q0 -142 -78 -261l300 -300q7 -8 7 -18t-7 -18l-109 -109q-8 -7 -18 -7t-18 7l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342zM176 693q0 -136 97 -233t234 -97t233.5 96.5t96.5 233.5t-96.5 233.5t-233.5 96.5 t-234 -97t-97 -233zM300 600v200h100v100h200v-100h100v-200h-100v-100h-200v100h-100z" />
<glyph unicode="&#xe016;" d="M23 694q0 200 142 342t342 142t342 -142t142 -342q0 -141 -78 -262l300 -299q7 -7 7 -18t-7 -18l-109 -109q-8 -8 -18 -8t-18 8l-300 299q-120 -77 -261 -77q-200 0 -342 142t-142 342zM176 694q0 -136 97 -233t234 -97t233.5 97t96.5 233t-96.5 233t-233.5 97t-234 -97 t-97 -233zM300 601h400v200h-400v-200z" />
<glyph unicode="&#xe017;" d="M23 600q0 183 105 331t272 210v-166q-103 -55 -165 -155t-62 -220q0 -177 125 -302t302 -125t302 125t125 302q0 120 -62 220t-165 155v166q167 -62 272 -210t105 -331q0 -118 -45.5 -224.5t-123 -184t-184 -123t-224.5 -45.5t-224.5 45.5t-184 123t-123 184t-45.5 224.5 zM500 750q0 -21 14.5 -35.5t35.5 -14.5h100q21 0 35.5 14.5t14.5 35.5v400q0 21 -14.5 35.5t-35.5 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-400z" />
<glyph unicode="&#xe018;" d="M100 1h200v300h-200v-300zM400 1v500h200v-500h-200zM700 1v800h200v-800h-200zM1000 1v1200h200v-1200h-200z" />
<glyph unicode="&#xe019;" d="M26 601q0 -33 6 -74l151 -38l2 -6q14 -49 38 -93l3 -5l-80 -134q45 -59 105 -105l133 81l5 -3q45 -26 94 -39l5 -2l38 -151q40 -5 74 -5q27 0 74 5l38 151l6 2q46 13 93 39l5 3l134 -81q56 44 104 105l-80 134l3 5q24 44 39 93l1 6l152 38q5 40 5 74q0 28 -5 73l-152 38 l-1 6q-16 51 -39 93l-3 5l80 134q-44 58 -104 105l-134 -81l-5 3q-45 25 -93 39l-6 1l-38 152q-40 5 -74 5q-27 0 -74 -5l-38 -152l-5 -1q-50 -14 -94 -39l-5 -3l-133 81q-59 -47 -105 -105l80 -134l-3 -5q-25 -47 -38 -93l-2 -6l-151 -38q-6 -48 -6 -73zM385 601 q0 88 63 151t152 63t152 -63t63 -151q0 -89 -63 -152t-152 -63t-152 63t-63 152z" />
<glyph unicode="&#xe020;" d="M100 1025v50q0 10 7.5 17.5t17.5 7.5h275v100q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5v-100h275q10 0 17.5 -7.5t7.5 -17.5v-50q0 -11 -7 -18t-18 -7h-1050q-11 0 -18 7t-7 18zM200 100v800h900v-800q0 -41 -29.5 -71t-70.5 -30h-700q-41 0 -70.5 30 t-29.5 71zM300 100h100v700h-100v-700zM500 100h100v700h-100v-700zM500 1100h300v100h-300v-100zM700 100h100v700h-100v-700zM900 100h100v700h-100v-700z" />
<glyph unicode="&#xe021;" d="M1 601l656 644l644 -644h-200v-600h-300v400h-300v-400h-300v600h-200z" />
<glyph unicode="&#xe022;" d="M100 25v1150q0 11 7 18t18 7h475v-500h400v-675q0 -11 -7 -18t-18 -7h-850q-11 0 -18 7t-7 18zM700 800v300l300 -300h-300z" />
<glyph unicode="&#xe023;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM500 500v400h100 v-300h200v-100h-300z" />
<glyph unicode="&#xe024;" d="M-100 0l431 1200h209l-21 -300h162l-20 300h208l431 -1200h-538l-41 400h-242l-40 -400h-539zM488 500h224l-27 300h-170z" />
<glyph unicode="&#xe025;" d="M0 0v400h490l-290 300h200v500h300v-500h200l-290 -300h490v-400h-1100zM813 200h175v100h-175v-100z" />
<glyph unicode="&#xe026;" d="M1 600q0 122 47.5 233t127.5 191t191 127.5t233 47.5t233 -47.5t191 -127.5t127.5 -191t47.5 -233t-47.5 -233t-127.5 -191t-191 -127.5t-233 -47.5t-233 47.5t-191 127.5t-127.5 191t-47.5 233zM188 600q0 -170 121 -291t291 -121t291 121t121 291t-121 291t-291 121 t-291 -121t-121 -291zM350 600h150v300h200v-300h150l-250 -300z" />
<glyph unicode="&#xe027;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM350 600l250 300 l250 -300h-150v-300h-200v300h-150z" />
<glyph unicode="&#xe028;" d="M0 25v475l200 700h800q199 -700 200 -700v-475q0 -11 -7 -18t-18 -7h-1150q-11 0 -18 7t-7 18zM200 500h200l50 -200h300l50 200h200l-97 500h-606z" />
<glyph unicode="&#xe029;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -172 121.5 -293t292.5 -121t292.5 121t121.5 293q0 171 -121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM500 397v401 l297 -200z" />
<glyph unicode="&#xe030;" d="M23 600q0 -118 45.5 -224.5t123 -184t184 -123t224.5 -45.5t224.5 45.5t184 123t123 184t45.5 224.5h-150q0 -177 -125 -302t-302 -125t-302 125t-125 302t125 302t302 125q136 0 246 -81l-146 -146h400v400l-145 -145q-157 122 -355 122q-118 0 -224.5 -45.5t-184 -123 t-123 -184t-45.5 -224.5z" />
<glyph unicode="&#xe031;" d="M23 600q0 118 45.5 224.5t123 184t184 123t224.5 45.5q198 0 355 -122l145 145v-400h-400l147 147q-112 80 -247 80q-177 0 -302 -125t-125 -302h-150zM100 0v400h400l-147 -147q112 -80 247 -80q177 0 302 125t125 302h150q0 -118 -45.5 -224.5t-123 -184t-184 -123 t-224.5 -45.5q-198 0 -355 122z" />
<glyph unicode="&#xe032;" d="M100 0h1100v1200h-1100v-1200zM200 100v900h900v-900h-900zM300 200v100h100v-100h-100zM300 400v100h100v-100h-100zM300 600v100h100v-100h-100zM300 800v100h100v-100h-100zM500 200h500v100h-500v-100zM500 400v100h500v-100h-500zM500 600v100h500v-100h-500z M500 800v100h500v-100h-500z" />
<glyph unicode="&#xe033;" d="M0 100v600q0 41 29.5 70.5t70.5 29.5h100v200q0 82 59 141t141 59h300q82 0 141 -59t59 -141v-200h100q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-900q-41 0 -70.5 29.5t-29.5 70.5zM400 800h300v150q0 21 -14.5 35.5t-35.5 14.5h-200 q-21 0 -35.5 -14.5t-14.5 -35.5v-150z" />
<glyph unicode="&#xe034;" d="M100 0v1100h100v-1100h-100zM300 400q60 60 127.5 84t127.5 17.5t122 -23t119 -30t110 -11t103 42t91 120.5v500q-40 -81 -101.5 -115.5t-127.5 -29.5t-138 25t-139.5 40t-125.5 25t-103 -29.5t-65 -115.5v-500z" />
<glyph unicode="&#xe035;" d="M0 275q0 -11 7 -18t18 -7h50q11 0 18 7t7 18v300q0 127 70.5 231.5t184.5 161.5t245 57t245 -57t184.5 -161.5t70.5 -231.5v-300q0 -11 7 -18t18 -7h50q11 0 18 7t7 18v300q0 116 -49.5 227t-131 192.5t-192.5 131t-227 49.5t-227 -49.5t-192.5 -131t-131 -192.5 t-49.5 -227v-300zM200 20v460q0 8 6 14t14 6h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14zM800 20v460q0 8 6 14t14 6h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14z" />
<glyph unicode="&#xe036;" d="M0 400h300l300 -200v800l-300 -200h-300v-400zM688 459l141 141l-141 141l71 71l141 -141l141 141l71 -71l-141 -141l141 -141l-71 -71l-141 141l-141 -141z" />
<glyph unicode="&#xe037;" d="M0 400h300l300 -200v800l-300 -200h-300v-400zM700 857l69 53q111 -135 111 -310q0 -169 -106 -302l-67 54q86 110 86 248q0 146 -93 257z" />
<glyph unicode="&#xe038;" d="M0 401v400h300l300 200v-800l-300 200h-300zM702 858l69 53q111 -135 111 -310q0 -170 -106 -303l-67 55q86 110 86 248q0 145 -93 257zM889 951l7 -8q123 -151 123 -344q0 -189 -119 -339l-7 -8l81 -66l6 8q142 178 142 405q0 230 -144 408l-6 8z" />
<glyph unicode="&#xe039;" d="M0 0h500v500h-200v100h-100v-100h-200v-500zM0 600h100v100h400v100h100v100h-100v300h-500v-600zM100 100v300h300v-300h-300zM100 800v300h300v-300h-300zM200 200v100h100v-100h-100zM200 900h100v100h-100v-100zM500 500v100h300v-300h200v-100h-100v-100h-200v100 h-100v100h100v200h-200zM600 0v100h100v-100h-100zM600 1000h100v-300h200v-300h300v200h-200v100h200v500h-600v-200zM800 800v300h300v-300h-300zM900 0v100h300v-100h-300zM900 900v100h100v-100h-100zM1100 200v100h100v-100h-100z" />
<glyph unicode="&#xe040;" d="M0 200h100v1000h-100v-1000zM100 0v100h300v-100h-300zM200 200v1000h100v-1000h-100zM500 0v91h100v-91h-100zM500 200v1000h200v-1000h-200zM700 0v91h100v-91h-100zM800 200v1000h100v-1000h-100zM900 0v91h200v-91h-200zM1000 200v1000h200v-1000h-200z" />
<glyph unicode="&#xe041;" d="M1 700v475q0 10 7.5 17.5t17.5 7.5h474l700 -700l-500 -500zM148 953q0 -42 29 -71q30 -30 71.5 -30t71.5 30q29 29 29 71t-29 71q-30 30 -71.5 30t-71.5 -30q-29 -29 -29 -71z" />
<glyph unicode="&#xe042;" d="M2 700v475q0 11 7 18t18 7h474l700 -700l-500 -500zM148 953q0 -42 30 -71q29 -30 71 -30t71 30q30 29 30 71t-30 71q-29 30 -71 30t-71 -30q-30 -29 -30 -71zM701 1200h100l700 -700l-500 -500l-50 50l450 450z" />
<glyph unicode="&#xe043;" d="M100 0v1025l175 175h925v-1000l-100 -100v1000h-750l-100 -100h750v-1000h-900z" />
<glyph unicode="&#xe044;" d="M200 0l450 444l450 -443v1150q0 20 -14.5 35t-35.5 15h-800q-21 0 -35.5 -15t-14.5 -35v-1151z" />
<glyph unicode="&#xe045;" d="M0 100v700h200l100 -200h600l100 200h200v-700h-200v200h-800v-200h-200zM253 829l40 -124h592l62 124l-94 346q-2 11 -10 18t-18 7h-450q-10 0 -18 -7t-10 -18zM281 24l38 152q2 10 11.5 17t19.5 7h500q10 0 19.5 -7t11.5 -17l38 -152q2 -10 -3.5 -17t-15.5 -7h-600 q-10 0 -15.5 7t-3.5 17z" />
<glyph unicode="&#xe046;" d="M0 200q0 -41 29.5 -70.5t70.5 -29.5h1000q41 0 70.5 29.5t29.5 70.5v600q0 41 -29.5 70.5t-70.5 29.5h-150q-4 8 -11.5 21.5t-33 48t-53 61t-69 48t-83.5 21.5h-200q-41 0 -82 -20.5t-70 -50t-52 -59t-34 -50.5l-12 -20h-150q-41 0 -70.5 -29.5t-29.5 -70.5v-600z M356 500q0 100 72 172t172 72t172 -72t72 -172t-72 -172t-172 -72t-172 72t-72 172zM494 500q0 -44 31 -75t75 -31t75 31t31 75t-31 75t-75 31t-75 -31t-31 -75zM900 700v100h100v-100h-100z" />
<glyph unicode="&#xe047;" d="M53 0h365v66q-41 0 -72 11t-49 38t1 71l92 234h391l82 -222q16 -45 -5.5 -88.5t-74.5 -43.5v-66h417v66q-34 1 -74 43q-18 19 -33 42t-21 37l-6 13l-385 998h-93l-399 -1006q-24 -48 -52 -75q-12 -12 -33 -25t-36 -20l-15 -7v-66zM416 521l178 457l46 -140l116 -317h-340 z" />
<glyph unicode="&#xe048;" d="M100 0v89q41 7 70.5 32.5t29.5 65.5v827q0 28 -1 39.5t-5.5 26t-15.5 21t-29 14t-49 14.5v70h471q120 0 213 -88t93 -228q0 -55 -11.5 -101.5t-28 -74t-33.5 -47.5t-28 -28l-12 -7q8 -3 21.5 -9t48 -31.5t60.5 -58t47.5 -91.5t21.5 -129q0 -84 -59 -156.5t-142 -111 t-162 -38.5h-500zM400 200h161q89 0 153 48.5t64 132.5q0 90 -62.5 154.5t-156.5 64.5h-159v-400zM400 700h139q76 0 130 61.5t54 138.5q0 82 -84 130.5t-239 48.5v-379z" />
<glyph unicode="&#xe049;" d="M200 0v57q77 7 134.5 40.5t65.5 80.5l173 849q10 56 -10 74t-91 37q-6 1 -10.5 2.5t-9.5 2.5v57h425l2 -57q-33 -8 -62 -25.5t-46 -37t-29.5 -38t-17.5 -30.5l-5 -12l-128 -825q-10 -52 14 -82t95 -36v-57h-500z" />
<glyph unicode="&#xe050;" d="M-75 200h75v800h-75l125 167l125 -167h-75v-800h75l-125 -167zM300 900v300h150h700h150v-300h-50q0 29 -8 48.5t-18.5 30t-33.5 15t-39.5 5.5t-50.5 1h-200v-850l100 -50v-100h-400v100l100 50v850h-200q-34 0 -50.5 -1t-40 -5.5t-33.5 -15t-18.5 -30t-8.5 -48.5h-49z " />
<glyph unicode="&#xe051;" d="M33 51l167 125v-75h800v75l167 -125l-167 -125v75h-800v-75zM100 901v300h150h700h150v-300h-50q0 29 -8 48.5t-18 30t-33.5 15t-40 5.5t-50.5 1h-200v-650l100 -50v-100h-400v100l100 50v650h-200q-34 0 -50.5 -1t-39.5 -5.5t-33.5 -15t-18.5 -30t-8 -48.5h-50z" />
<glyph unicode="&#xe052;" d="M0 50q0 -20 14.5 -35t35.5 -15h1100q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM0 350q0 -20 14.5 -35t35.5 -15h800q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-800q-21 0 -35.5 -14.5t-14.5 -35.5 v-100zM0 650q0 -20 14.5 -35t35.5 -15h1000q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1000q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM0 950q0 -20 14.5 -35t35.5 -15h600q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-600q-21 0 -35.5 -14.5 t-14.5 -35.5v-100z" />
<glyph unicode="&#xe053;" d="M0 50q0 -20 14.5 -35t35.5 -15h1100q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM0 650q0 -20 14.5 -35t35.5 -15h1100q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5 v-100zM200 350q0 -20 14.5 -35t35.5 -15h700q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-700q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM200 950q0 -20 14.5 -35t35.5 -15h700q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-700q-21 0 -35.5 -14.5 t-14.5 -35.5v-100z" />
<glyph unicode="&#xe054;" d="M0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM100 650v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1000q-21 0 -35.5 15 t-14.5 35zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM500 950v100q0 21 14.5 35.5t35.5 14.5h600q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-600 q-21 0 -35.5 15t-14.5 35z" />
<glyph unicode="&#xe055;" d="M0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM0 350v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15 t-14.5 35zM0 650v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM0 950v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100 q-21 0 -35.5 15t-14.5 35z" />
<glyph unicode="&#xe056;" d="M0 50v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35zM0 350v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15 t-14.5 35zM0 650v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35zM0 950v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15 t-14.5 35zM300 50v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800 q-21 0 -35.5 15t-14.5 35zM300 650v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM300 950v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15 h-800q-21 0 -35.5 15t-14.5 35z" />
<glyph unicode="&#xe057;" d="M-101 500v100h201v75l166 -125l-166 -125v75h-201zM300 0h100v1100h-100v-1100zM500 50q0 -20 14.5 -35t35.5 -15h600q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-600q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM500 350q0 -20 14.5 -35t35.5 -15h300q20 0 35 15t15 35 v100q0 21 -15 35.5t-35 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM500 650q0 -20 14.5 -35t35.5 -15h500q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM500 950q0 -20 14.5 -35t35.5 -15h100q20 0 35 15t15 35v100 q0 21 -15 35.5t-35 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-100z" />
<glyph unicode="&#xe058;" d="M1 50q0 -20 14.5 -35t35.5 -15h600q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-600q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM1 350q0 -20 14.5 -35t35.5 -15h300q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM1 650 q0 -20 14.5 -35t35.5 -15h500q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM1 950q0 -20 14.5 -35t35.5 -15h100q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM801 0v1100h100v-1100 h-100zM934 550l167 -125v75h200v100h-200v75z" />
<glyph unicode="&#xe059;" d="M0 275v650q0 31 22 53t53 22h750q31 0 53 -22t22 -53v-650q0 -31 -22 -53t-53 -22h-750q-31 0 -53 22t-22 53zM900 600l300 300v-600z" />
<glyph unicode="&#xe060;" d="M0 44v1012q0 18 13 31t31 13h1112q19 0 31.5 -13t12.5 -31v-1012q0 -18 -12.5 -31t-31.5 -13h-1112q-18 0 -31 13t-13 31zM100 263l247 182l298 -131l-74 156l293 318l236 -288v500h-1000v-737zM208 750q0 56 39 95t95 39t95 -39t39 -95t-39 -95t-95 -39t-95 39t-39 95z " />
<glyph unicode="&#xe062;" d="M148 745q0 124 60.5 231.5t165 172t226.5 64.5q123 0 227 -63t164.5 -169.5t60.5 -229.5t-73 -272q-73 -114 -166.5 -237t-150.5 -189l-57 -66q-10 9 -27 26t-66.5 70.5t-96 109t-104 135.5t-100.5 155q-63 139 -63 262zM342 772q0 -107 75.5 -182.5t181.5 -75.5 q107 0 182.5 75.5t75.5 182.5t-75.5 182t-182.5 75t-182 -75.5t-75 -181.5z" />
<glyph unicode="&#xe063;" d="M1 600q0 122 47.5 233t127.5 191t191 127.5t233 47.5t233 -47.5t191 -127.5t127.5 -191t47.5 -233t-47.5 -233t-127.5 -191t-191 -127.5t-233 -47.5t-233 47.5t-191 127.5t-127.5 191t-47.5 233zM173 600q0 -177 125.5 -302t301.5 -125v854q-176 0 -301.5 -125 t-125.5 -302z" />
<glyph unicode="&#xe064;" d="M117 406q0 94 34 186t88.5 172.5t112 159t115 177t87.5 194.5q21 -71 57.5 -142.5t76 -130.5t83 -118.5t82 -117t70 -116t50 -125.5t18.5 -136q0 -89 -39 -165.5t-102 -126.5t-140 -79.5t-156 -33.5q-114 6 -211.5 53t-161.5 138.5t-64 210.5zM243 414q14 -82 59.5 -136 t136.5 -80l16 98q-7 6 -18 17t-34 48t-33 77q-15 73 -14 143.5t10 122.5l9 51q-92 -110 -119.5 -185t-12.5 -156z" />
<glyph unicode="&#xe065;" d="M0 400v300q0 165 117.5 282.5t282.5 117.5q366 -6 397 -14l-186 -186h-311q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v125l200 200v-225q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5 t-117.5 282.5zM436 341l161 50l412 412l-114 113l-405 -405zM995 1015l113 -113l113 113l-21 85l-92 28z" />
<glyph unicode="&#xe066;" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h261l2 -80q-133 -32 -218 -120h-145q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5l200 153v-53q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5 zM423 524q30 38 81.5 64t103 35.5t99 14t77.5 3.5l29 -1v-209l360 324l-359 318v-216q-7 0 -19 -1t-48 -8t-69.5 -18.5t-76.5 -37t-76.5 -59t-62 -88t-39.5 -121.5z" />
<glyph unicode="&#xe067;" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h300q60 0 127 -23l-178 -177h-349q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v69l200 200v-169q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5 t-117.5 282.5zM342 632l283 -284l566 567l-136 137l-430 -431l-147 147z" />
<glyph unicode="&#xe068;" d="M0 603l300 296v-198h200v200h-200l300 300l295 -300h-195v-200h200v198l300 -296l-300 -300v198h-200v-200h195l-295 -300l-300 300h200v200h-200v-198z" />
<glyph unicode="&#xe069;" d="M200 50v1000q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-437l500 487v-1100l-500 488v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5z" />
<glyph unicode="&#xe070;" d="M0 50v1000q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-437l500 487v-487l500 487v-1100l-500 488v-488l-500 488v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5z" />
<glyph unicode="&#xe071;" d="M136 550l564 550v-487l500 487v-1100l-500 488v-488z" />
<glyph unicode="&#xe072;" d="M200 0l900 550l-900 550v-1100z" />
<glyph unicode="&#xe073;" d="M200 150q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v800q0 21 -14.5 35.5t-35.5 14.5h-200q-21 0 -35.5 -14.5t-14.5 -35.5v-800zM600 150q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v800q0 21 -14.5 35.5t-35.5 14.5h-200 q-21 0 -35.5 -14.5t-14.5 -35.5v-800z" />
<glyph unicode="&#xe074;" d="M200 150q0 -20 14.5 -35t35.5 -15h800q21 0 35.5 15t14.5 35v800q0 21 -14.5 35.5t-35.5 14.5h-800q-21 0 -35.5 -14.5t-14.5 -35.5v-800z" />
<glyph unicode="&#xe075;" d="M0 0v1100l500 -487v487l564 -550l-564 -550v488z" />
<glyph unicode="&#xe076;" d="M0 0v1100l500 -487v487l500 -487v437q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438l-500 -488v488z" />
<glyph unicode="&#xe077;" d="M300 0v1100l500 -487v437q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438z" />
<glyph unicode="&#xe078;" d="M100 250v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5zM100 500h1100l-550 564z" />
<glyph unicode="&#xe079;" d="M185 599l592 -592l240 240l-353 353l353 353l-240 240z" />
<glyph unicode="&#xe080;" d="M272 194l353 353l-353 353l241 240l572 -571l21 -22l-1 -1v-1l-592 -591z" />
<glyph unicode="&#xe081;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -300t-217.5 -218t-299.5 -80t-299.5 80t-217.5 218t-80 300zM300 500h200v-200h200v200h200v200h-200v200h-200v-200h-200v-200z" />
<glyph unicode="&#xe082;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -300t-217.5 -218t-299.5 -80t-299.5 80t-217.5 218t-80 300zM300 500h600v200h-600v-200z" />
<glyph unicode="&#xe083;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -300t-217.5 -218t-299.5 -80t-299.5 80t-217.5 218t-80 300zM246 459l213 -213l141 142l141 -142l213 213l-142 141l142 141l-213 212l-141 -141l-141 142l-212 -213l141 -141z" />
<glyph unicode="&#xe084;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM270 551l276 -277l411 411l-175 174l-236 -236l-102 102z" />
<glyph unicode="&#xe085;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -300t-217.5 -218t-299.5 -80t-299.5 80t-217.5 218t-80 300zM363 700h144q4 0 11.5 -1t11 -1t6.5 3t3 9t1 11t3.5 8.5t3.5 6t5.5 4t6.5 2.5t9 1.5t9 0.5h11.5h12.5q19 0 30 -10t11 -26 q0 -22 -4 -28t-27 -22q-5 -1 -12.5 -3t-27 -13.5t-34 -27t-26.5 -46t-11 -68.5h200q5 3 14 8t31.5 25.5t39.5 45.5t31 69t14 94q0 51 -17.5 89t-42 58t-58.5 32t-58.5 15t-51.5 3q-105 0 -172 -56t-67 -183zM500 300h200v100h-200v-100z" />
<glyph unicode="&#xe086;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -300t-217.5 -218t-299.5 -80t-299.5 80t-217.5 218t-80 300zM400 300h400v100h-100v300h-300v-100h100v-200h-100v-100zM500 800h200v100h-200v-100z" />
<glyph unicode="&#xe087;" d="M0 500v200h194q15 60 36 104.5t55.5 86t88 69t126.5 40.5v200h200v-200q54 -20 113 -60t112.5 -105.5t71.5 -134.5h203v-200h-203q-25 -102 -116.5 -186t-180.5 -117v-197h-200v197q-140 27 -208 102.5t-98 200.5h-194zM290 500q24 -73 79.5 -127.5t130.5 -78.5v206h200 v-206q149 48 201 206h-201v200h200q-25 74 -76 127.5t-124 76.5v-204h-200v203q-75 -24 -130 -77.5t-79 -125.5h209v-200h-210z" />
<glyph unicode="&#xe088;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM356 465l135 135 l-135 135l109 109l135 -135l135 135l109 -109l-135 -135l135 -135l-109 -109l-135 135l-135 -135z" />
<glyph unicode="&#xe089;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM322 537l141 141 l87 -87l204 205l142 -142l-346 -345z" />
<glyph unicode="&#xe090;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -115 62 -215l568 567q-100 62 -216 62q-171 0 -292.5 -121.5t-121.5 -292.5zM391 245q97 -59 209 -59q171 0 292.5 121.5t121.5 292.5 q0 112 -59 209z" />
<glyph unicode="&#xe091;" d="M0 547l600 453v-300h600v-300h-600v-301z" />
<glyph unicode="&#xe092;" d="M0 400v300h600v300l600 -453l-600 -448v301h-600z" />
<glyph unicode="&#xe093;" d="M204 600l450 600l444 -600h-298v-600h-300v600h-296z" />
<glyph unicode="&#xe094;" d="M104 600h296v600h300v-600h298l-449 -600z" />
<glyph unicode="&#xe095;" d="M0 200q6 132 41 238.5t103.5 193t184 138t271.5 59.5v271l600 -453l-600 -448v301q-95 -2 -183 -20t-170 -52t-147 -92.5t-100 -135.5z" />
<glyph unicode="&#xe096;" d="M0 0v400l129 -129l294 294l142 -142l-294 -294l129 -129h-400zM635 777l142 -142l294 294l129 -129v400h-400l129 -129z" />
<glyph unicode="&#xe097;" d="M34 176l295 295l-129 129h400v-400l-129 130l-295 -295zM600 600v400l129 -129l295 295l142 -141l-295 -295l129 -130h-400z" />
<glyph unicode="&#xe101;" d="M23 600q0 118 45.5 224.5t123 184t184 123t224.5 45.5t224.5 -45.5t184 -123t123 -184t45.5 -224.5t-45.5 -224.5t-123 -184t-184 -123t-224.5 -45.5t-224.5 45.5t-184 123t-123 184t-45.5 224.5zM456 851l58 -302q4 -20 21.5 -34.5t37.5 -14.5h54q20 0 37.5 14.5 t21.5 34.5l58 302q4 20 -8 34.5t-33 14.5h-207q-20 0 -32 -14.5t-8 -34.5zM500 300h200v100h-200v-100z" />
<glyph unicode="&#xe102;" d="M0 800h100v-200h400v300h200v-300h400v200h100v100h-111v6t-1 15t-3 18l-34 172q-11 39 -41.5 63t-69.5 24q-32 0 -61 -17l-239 -144q-22 -13 -40 -35q-19 24 -40 36l-238 144q-33 18 -62 18q-39 0 -69.5 -23t-40.5 -61l-35 -177q-2 -8 -3 -18t-1 -15v-6h-111v-100z M100 0h400v400h-400v-400zM200 900q-3 0 14 48t35 96l18 47l214 -191h-281zM700 0v400h400v-400h-400zM731 900l202 197q5 -12 12 -32.5t23 -64t25 -72t7 -28.5h-269z" />
<glyph unicode="&#xe103;" d="M0 -22v143l216 193q-9 53 -13 83t-5.5 94t9 113t38.5 114t74 124q47 60 99.5 102.5t103 68t127.5 48t145.5 37.5t184.5 43.5t220 58.5q0 -189 -22 -343t-59 -258t-89 -181.5t-108.5 -120t-122 -68t-125.5 -30t-121.5 -1.5t-107.5 12.5t-87.5 17t-56.5 7.5l-99 -55z M238.5 300.5q19.5 -6.5 86.5 76.5q55 66 367 234q70 38 118.5 69.5t102 79t99 111.5t86.5 148q22 50 24 60t-6 19q-7 5 -17 5t-26.5 -14.5t-33.5 -39.5q-35 -51 -113.5 -108.5t-139.5 -89.5l-61 -32q-369 -197 -458 -401q-48 -111 -28.5 -117.5z" />
<glyph unicode="&#xe104;" d="M111 408q0 -33 5 -63q9 -56 44 -119.5t105 -108.5q31 -21 64 -16t62 23.5t57 49.5t48 61.5t35 60.5q32 66 39 184.5t-13 157.5q79 -80 122 -164t26 -184q-5 -33 -20.5 -69.5t-37.5 -80.5q-10 -19 -14.5 -29t-12 -26t-9 -23.5t-3 -19t2.5 -15.5t11 -9.5t19.5 -5t30.5 2.5 t42 8q57 20 91 34t87.5 44.5t87 64t65.5 88.5t47 122q38 172 -44.5 341.5t-246.5 278.5q22 -44 43 -129q39 -159 -32 -154q-15 2 -33 9q-79 33 -120.5 100t-44 175.5t48.5 257.5q-13 -8 -34 -23.5t-72.5 -66.5t-88.5 -105.5t-60 -138t-8 -166.5q2 -12 8 -41.5t8 -43t6 -39.5 t3.5 -39.5t-1 -33.5t-6 -31.5t-13.5 -24t-21 -20.5t-31 -12q-38 -10 -67 13t-40.5 61.5t-15 81.5t10.5 75q-52 -46 -83.5 -101t-39 -107t-7.5 -85z" />
<glyph unicode="&#xe105;" d="M-61 600l26 40q6 10 20 30t49 63.5t74.5 85.5t97 90t116.5 83.5t132.5 59t145.5 23.5t145.5 -23.5t132.5 -59t116.5 -83.5t97 -90t74.5 -85.5t49 -63.5t20 -30l26 -40l-26 -40q-6 -10 -20 -30t-49 -63.5t-74.5 -85.5t-97 -90t-116.5 -83.5t-132.5 -59t-145.5 -23.5 t-145.5 23.5t-132.5 59t-116.5 83.5t-97 90t-74.5 85.5t-49 63.5t-20 30zM120 600q7 -10 40.5 -58t56 -78.5t68 -77.5t87.5 -75t103 -49.5t125 -21.5t123.5 20t100.5 45.5t85.5 71.5t66.5 75.5t58 81.5t47 66q-1 1 -28.5 37.5t-42 55t-43.5 53t-57.5 63.5t-58.5 54 q49 -74 49 -163q0 -124 -88 -212t-212 -88t-212 88t-88 212q0 85 46 158q-102 -87 -226 -258zM377 656q49 -124 154 -191l105 105q-37 24 -75 72t-57 84l-20 36z" />
<glyph unicode="&#xe106;" d="M-61 600l26 40q6 10 20 30t49 63.5t74.5 85.5t97 90t116.5 83.5t132.5 59t145.5 23.5q61 0 121 -17l37 142h148l-314 -1200h-148l37 143q-82 21 -165 71.5t-140 102t-109.5 112t-72 88.5t-29.5 43zM120 600q210 -282 393 -336l37 141q-107 18 -178.5 101.5t-71.5 193.5 q0 85 46 158q-102 -87 -226 -258zM377 656q49 -124 154 -191l47 47l23 87q-30 28 -59 69t-44 68l-14 26zM780 161l38 145q22 15 44.5 34t46 44t40.5 44t41 50.5t33.5 43.5t33 44t24.5 34q-97 127 -140 175l39 146q67 -54 131.5 -125.5t87.5 -103.5t36 -52l26 -40l-26 -40 q-7 -12 -25.5 -38t-63.5 -79.5t-95.5 -102.5t-124 -100t-146.5 -79z" />
<glyph unicode="&#xe107;" d="M-97.5 34q13.5 -34 50.5 -34h1294q37 0 50.5 35.5t-7.5 67.5l-642 1056q-20 33 -48 36t-48 -29l-642 -1066q-21 -32 -7.5 -66zM155 200l445 723l445 -723h-345v100h-200v-100h-345zM500 600l100 -300l100 300v100h-200v-100z" />
<glyph unicode="&#xe108;" d="M100 262v41q0 20 11 44.5t26 38.5l363 325v339q0 62 44 106t106 44t106 -44t44 -106v-339l363 -325q15 -14 26 -38.5t11 -44.5v-41q0 -20 -12 -26.5t-29 5.5l-359 249v-263q100 -91 100 -113v-64q0 -21 -13 -29t-32 1l-94 78h-222l-94 -78q-19 -9 -32 -1t-13 29v64 q0 22 100 113v263l-359 -249q-17 -12 -29 -5.5t-12 26.5z" />
<glyph unicode="&#xe109;" d="M0 50q0 -20 14.5 -35t35.5 -15h1000q21 0 35.5 15t14.5 35v750h-1100v-750zM0 900h1100v150q0 21 -14.5 35.5t-35.5 14.5h-150v100h-100v-100h-500v100h-100v-100h-150q-21 0 -35.5 -14.5t-14.5 -35.5v-150zM100 100v100h100v-100h-100zM100 300v100h100v-100h-100z M100 500v100h100v-100h-100zM300 100v100h100v-100h-100zM300 300v100h100v-100h-100zM300 500v100h100v-100h-100zM500 100v100h100v-100h-100zM500 300v100h100v-100h-100zM500 500v100h100v-100h-100zM700 100v100h100v-100h-100zM700 300v100h100v-100h-100zM700 500 v100h100v-100h-100zM900 100v100h100v-100h-100zM900 300v100h100v-100h-100zM900 500v100h100v-100h-100z" />
<glyph unicode="&#xe110;" d="M0 200v200h259l600 600h241v198l300 -295l-300 -300v197h-159l-600 -600h-341zM0 800h259l122 -122l141 142l-181 180h-341v-200zM678 381l141 142l122 -123h159v198l300 -295l-300 -300v197h-241z" />
<glyph unicode="&#xe111;" d="M0 400v600q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-596l-304 -300v300h-100q-41 0 -70.5 29.5t-29.5 70.5z" />
<glyph unicode="&#xe112;" d="M100 600v200h300v-250q0 -113 6 -145q17 -92 102 -117q39 -11 92 -11q37 0 66.5 5.5t50 15.5t36 24t24 31.5t14 37.5t7 42t2.5 45t0 47v25v250h300v-200q0 -42 -3 -83t-15 -104t-31.5 -116t-58 -109.5t-89 -96.5t-129 -65.5t-174.5 -25.5t-174.5 25.5t-129 65.5t-89 96.5 t-58 109.5t-31.5 116t-15 104t-3 83zM100 900v300h300v-300h-300zM800 900v300h300v-300h-300z" />
<glyph unicode="&#xe113;" d="M-30 411l227 -227l352 353l353 -353l226 227l-578 579z" />
<glyph unicode="&#xe114;" d="M70 797l580 -579l578 579l-226 227l-353 -353l-352 353z" />
<glyph unicode="&#xe115;" d="M-198 700l299 283l300 -283h-203v-400h385l215 -200h-800v600h-196zM402 1000l215 -200h381v-400h-198l299 -283l299 283h-200v600h-796z" />
<glyph unicode="&#xe116;" d="M18 939q-5 24 10 42q14 19 39 19h896l38 162q5 17 18.5 27.5t30.5 10.5h94q20 0 35 -14.5t15 -35.5t-15 -35.5t-35 -14.5h-54l-201 -961q-2 -4 -6 -10.5t-19 -17.5t-33 -11h-31v-50q0 -20 -14.5 -35t-35.5 -15t-35.5 15t-14.5 35v50h-300v-50q0 -20 -14.5 -35t-35.5 -15 t-35.5 15t-14.5 35v50h-50q-21 0 -35.5 15t-14.5 35q0 21 14.5 35.5t35.5 14.5h535l48 200h-633q-32 0 -54.5 21t-27.5 43z" />
<glyph unicode="&#xe117;" d="M0 0v800h1200v-800h-1200zM0 900v100h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500v-100h-1200z" />
<glyph unicode="&#xe118;" d="M1 0l300 700h1200l-300 -700h-1200zM1 400v600h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500v-200h-1000z" />
<glyph unicode="&#xe119;" d="M302 300h198v600h-198l298 300l298 -300h-198v-600h198l-298 -300z" />
<glyph unicode="&#xe120;" d="M0 600l300 298v-198h600v198l300 -298l-300 -297v197h-600v-197z" />
<glyph unicode="&#xe121;" d="M0 100v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM31 400l172 739q5 22 23 41.5t38 19.5h672q19 0 37.5 -22.5t23.5 -45.5l172 -732h-1138zM800 100h100v100h-100v-100z M1000 100h100v100h-100v-100z" />
<glyph unicode="&#xe122;" d="M-101 600v50q0 24 25 49t50 38l25 13v-250l-11 5.5t-24 14t-30 21.5t-24 27.5t-11 31.5zM99 500v250v5q0 13 0.5 18.5t2.5 13t8 10.5t15 3h200l675 250v-850l-675 200h-38l47 -276q2 -12 -3 -17.5t-11 -6t-21 -0.5h-8h-83q-20 0 -34.5 14t-18.5 35q-56 337 -56 351z M1100 200v850q0 21 14.5 35.5t35.5 14.5q20 0 35 -14.5t15 -35.5v-850q0 -20 -15 -35t-35 -15q-21 0 -35.5 15t-14.5 35z" />
<glyph unicode="&#xe123;" d="M74 350q0 21 13.5 35.5t33.5 14.5h17l118 173l63 327q15 77 76 140t144 83l-18 32q-6 19 3 32t29 13h94q20 0 29 -10.5t3 -29.5l-18 -37q83 -19 144 -82.5t76 -140.5l63 -327l118 -173h17q20 0 33.5 -14.5t13.5 -35.5q0 -20 -13 -40t-31 -27q-22 -9 -63 -23t-167.5 -37 t-251.5 -23t-245.5 20.5t-178.5 41.5l-58 20q-18 7 -31 27.5t-13 40.5zM497 110q12 -49 40 -79.5t63 -30.5t63 30.5t39 79.5q-48 -6 -102 -6t-103 6z" />
<glyph unicode="&#xe124;" d="M21 445l233 -45l-78 -224l224 78l45 -233l155 179l155 -179l45 233l224 -78l-78 224l234 45l-180 155l180 156l-234 44l78 225l-224 -78l-45 233l-155 -180l-155 180l-45 -233l-224 78l78 -225l-233 -44l179 -156z" />
<glyph unicode="&#xe125;" d="M0 200h200v600h-200v-600zM300 275q0 -75 100 -75h61q123 -100 139 -100h250q46 0 83 57l238 344q29 31 29 74v100q0 44 -30.5 84.5t-69.5 40.5h-328q28 118 28 125v150q0 44 -30.5 84.5t-69.5 40.5h-50q-27 0 -51 -20t-38 -48l-96 -198l-145 -196q-20 -26 -20 -63v-400z M400 300v375l150 212l100 213h50v-175l-50 -225h450v-125l-250 -375h-214l-136 100h-100z" />
<glyph unicode="&#xe126;" d="M0 400v600h200v-600h-200zM300 525v400q0 75 100 75h61q123 100 139 100h250q46 0 83 -57l238 -344q29 -31 29 -74v-100q0 -44 -30.5 -84.5t-69.5 -40.5h-328q28 -118 28 -125v-150q0 -44 -30.5 -84.5t-69.5 -40.5h-50q-27 0 -51 20t-38 48l-96 198l-145 196 q-20 26 -20 63zM400 525l150 -212l100 -213h50v175l-50 225h450v125l-250 375h-214l-136 -100h-100v-375z" />
<glyph unicode="&#xe127;" d="M8 200v600h200v-600h-200zM308 275v525q0 17 14 35.5t28 28.5l14 9l362 230q14 6 25 6q17 0 29 -12l109 -112q14 -14 14 -34q0 -18 -11 -32l-85 -121h302q85 0 138.5 -38t53.5 -110t-54.5 -111t-138.5 -39h-107l-130 -339q-7 -22 -20.5 -41.5t-28.5 -19.5h-341 q-7 0 -90 81t-83 94zM408 289l100 -89h293l131 339q6 21 19.5 41t28.5 20h203q16 0 25 15t9 36q0 20 -9 34.5t-25 14.5h-457h-6.5h-7.5t-6.5 0.5t-6 1t-5 1.5t-5.5 2.5t-4 4t-4 5.5q-5 12 -5 20q0 14 10 27l147 183l-86 83l-339 -236v-503z" />
<glyph unicode="&#xe128;" d="M-101 651q0 72 54 110t139 37h302l-85 121q-11 16 -11 32q0 21 14 34l109 113q13 12 29 12q11 0 25 -6l365 -230q7 -4 16.5 -10.5t26 -26t16.5 -36.5v-526q0 -13 -85.5 -93.5t-93.5 -80.5h-342q-15 0 -28.5 20t-19.5 41l-131 339h-106q-84 0 -139 39t-55 111zM-1 601h222 q15 0 28.5 -20.5t19.5 -40.5l131 -339h293l106 89v502l-342 237l-87 -83l145 -184q10 -11 10 -26q0 -11 -5 -20q-1 -3 -3.5 -5.5l-4 -4t-5 -2.5t-5.5 -1.5t-6.5 -1t-6.5 -0.5h-7.5h-6.5h-476v-100zM999 201v600h200v-600h-200z" />
<glyph unicode="&#xe129;" d="M97 719l230 -363q4 -6 10.5 -15.5t26 -25t36.5 -15.5h525q13 0 94 83t81 90v342q0 15 -20 28.5t-41 19.5l-339 131v106q0 84 -39 139t-111 55t-110 -53.5t-38 -138.5v-302l-121 84q-15 12 -33.5 11.5t-32.5 -13.5l-112 -110q-22 -22 -6 -53zM172 739l83 86l183 -146 q22 -18 47 -5q3 1 5.5 3.5l4 4t2.5 5t1.5 5.5t1 6.5t0.5 6v7.5v7v456q0 22 25 31t50 -0.5t25 -30.5v-202q0 -16 20 -29.5t41 -19.5l339 -130v-294l-89 -100h-503zM400 0v200h600v-200h-600z" />
<glyph unicode="&#xe130;" d="M1 585q-15 -31 7 -53l112 -110q13 -13 32 -13.5t34 10.5l121 85l-1 -302q0 -84 38.5 -138t110.5 -54t111 55t39 139v106l339 131q20 6 40.5 19.5t20.5 28.5v342q0 7 -81 90t-94 83h-525q-17 0 -35.5 -14t-28.5 -28l-10 -15zM76 565l237 339h503l89 -100v-294l-340 -130 q-20 -6 -40 -20t-20 -29v-202q0 -22 -25 -31t-50 0t-25 31v456v14.5t-1.5 11.5t-5 12t-9.5 7q-24 13 -46 -5l-184 -146zM305 1104v200h600v-200h-600z" />
<glyph unicode="&#xe131;" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q162 0 299.5 -80t217.5 -218t80 -300t-80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM300 500h300l-2 -194l402 294l-402 298v-197h-298v-201z" />
<glyph unicode="&#xe132;" d="M0 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t231.5 47.5q122 0 232.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-218 -217.5t-300 -80t-299.5 80t-217.5 217.5t-80 299.5zM200 600l400 -294v194h302v201h-300v197z" />
<glyph unicode="&#xe133;" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q121 0 231.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM300 600h200v-300h200v300h200l-300 400z" />
<glyph unicode="&#xe134;" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q121 0 231.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM300 600l300 -400l300 400h-200v300h-200v-300h-200z" />
<glyph unicode="&#xe135;" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q121 0 231.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM254 780q-8 -34 5.5 -93t7.5 -87q0 -9 17 -44t16 -60q12 0 23 -5.5 t23 -15t20 -13.5q20 -10 108 -42q22 -8 53 -31.5t59.5 -38.5t57.5 -11q8 -18 -15 -55.5t-20 -57.5q12 -21 22.5 -34.5t28 -27t36.5 -17.5q0 -6 -3 -15.5t-3.5 -14.5t4.5 -17q101 -2 221 111q31 30 47 48t34 49t21 62q-14 9 -37.5 9.5t-35.5 7.5q-14 7 -49 15t-52 19 q-9 0 -39.5 -0.5t-46.5 -1.5t-39 -6.5t-39 -16.5q-50 -35 -66 -12q-4 2 -3.5 25.5t0.5 25.5q-6 13 -26.5 17t-24.5 7q2 22 -2 41t-16.5 28t-38.5 -20q-23 -25 -42 4q-19 28 -8 58q8 16 22 22q6 -1 26 -1.5t33.5 -4.5t19.5 -13q12 -19 32 -37.5t34 -27.5l14 -8q0 3 9.5 39.5 t5.5 57.5q-4 23 14.5 44.5t22.5 31.5q5 14 10 35t8.5 31t15.5 22.5t34 21.5q-6 18 10 37q8 0 23.5 -1.5t24.5 -1.5t20.5 4.5t20.5 15.5q-10 23 -30.5 42.5t-38 30t-49 26.5t-43.5 23q11 41 1 44q31 -13 58.5 -14.5t39.5 3.5l11 4q6 36 -17 53.5t-64 28.5t-56 23 q-19 -3 -37 0q-15 -12 -36.5 -21t-34.5 -12t-44 -8t-39 -6q-15 -3 -46 0t-45 -3q-20 -6 -51.5 -25.5t-34.5 -34.5q-3 -11 6.5 -22.5t8.5 -18.5q-3 -34 -27.5 -91t-29.5 -79zM518 915q3 12 16 30.5t16 25.5q10 -10 18.5 -10t14 6t14.5 14.5t16 12.5q0 -18 8 -42.5t16.5 -44 t9.5 -23.5q-6 1 -39 5t-53.5 10t-36.5 16z" />
<glyph unicode="&#xe136;" d="M0 164.5q0 21.5 15 37.5l600 599q-33 101 6 201.5t135 154.5q164 92 306 -9l-259 -138l145 -232l251 126q13 -175 -151 -267q-123 -70 -253 -23l-596 -596q-15 -16 -36.5 -16t-36.5 16l-111 110q-15 15 -15 36.5z" />
<glyph unicode="&#xe137;" horiz-adv-x="1220" d="M0 196v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM0 596v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5zM0 996v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM600 596h500v100h-500v-100zM800 196h300v100h-300v-100zM900 996h200v100h-200v-100z" />
<glyph unicode="&#xe138;" d="M100 1100v100h1000v-100h-1000zM150 1000h900l-350 -500v-300l-200 -200v500z" />
<glyph unicode="&#xe139;" d="M0 200v200h1200v-200q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM0 500v400q0 41 29.5 70.5t70.5 29.5h300v100q0 41 29.5 70.5t70.5 29.5h200q41 0 70.5 -29.5t29.5 -70.5v-100h300q41 0 70.5 -29.5t29.5 -70.5v-400h-500v100h-200v-100h-500z M500 1000h200v100h-200v-100z" />
<glyph unicode="&#xe140;" d="M0 0v400l129 -129l200 200l142 -142l-200 -200l129 -129h-400zM0 800l129 129l200 -200l142 142l-200 200l129 129h-400v-400zM729 329l142 142l200 -200l129 129v-400h-400l129 129zM729 871l200 200l-129 129h400v-400l-129 129l-200 -200z" />
<glyph unicode="&#xe141;" d="M0 596q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM182 596q0 -172 121.5 -293t292.5 -121t292.5 121t121.5 293q0 171 -121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM291 655 q0 23 15.5 38.5t38.5 15.5t39 -16t16 -38q0 -23 -16 -39t-39 -16q-22 0 -38 16t-16 39zM400 850q0 22 16 38.5t39 16.5q22 0 38 -16t16 -39t-16 -39t-38 -16q-23 0 -39 16.5t-16 38.5zM513 609q0 32 21 56.5t52 29.5l122 126l1 1q-9 14 -9 28q0 22 16 38.5t39 16.5 q22 0 38 -16t16 -39t-16 -39t-38 -16q-16 0 -29 10l-55 -145q17 -22 17 -51q0 -36 -25.5 -61.5t-61.5 -25.5q-37 0 -62.5 25.5t-25.5 61.5zM800 655q0 22 16 38t39 16t38.5 -15.5t15.5 -38.5t-16 -39t-38 -16q-23 0 -39 16t-16 39z" />
<glyph unicode="&#xe142;" d="M-40 375q-13 -95 35 -173q35 -57 94 -89t129 -32q63 0 119 28q33 16 65 40.5t52.5 45.5t59.5 64q40 44 57 61l394 394q35 35 47 84t-3 96q-27 87 -117 104q-20 2 -29 2q-46 0 -79.5 -17t-67.5 -51l-388 -396l-7 -7l69 -67l377 373q20 22 39 38q23 23 50 23q38 0 53 -36 q16 -39 -20 -75l-547 -547q-52 -52 -125 -52q-55 0 -100 33t-54 96q-5 35 2.5 66t31.5 63t42 50t56 54q24 21 44 41l348 348q52 52 82.5 79.5t84 54t107.5 26.5q25 0 48 -4q95 -17 154 -94.5t51 -175.5q-7 -101 -98 -192l-252 -249l-253 -256l7 -7l69 -60l517 511 q67 67 95 157t11 183q-16 87 -67 154t-130 103q-69 33 -152 33q-107 0 -197 -55q-40 -24 -111 -95l-512 -512q-68 -68 -81 -163z" />
<glyph unicode="&#xe143;" d="M79 784q0 131 99 229.5t230 98.5q144 0 242 -129q103 129 245 129q130 0 227 -98.5t97 -229.5q0 -46 -17.5 -91t-61 -99t-77 -89.5t-104.5 -105.5q-197 -191 -293 -322l-17 -23l-16 23q-43 58 -100 122.5t-92 99.5t-101 100l-84.5 84.5t-68 74t-60 78t-33.5 70.5t-15 78z M250 784q0 -27 30.5 -70t61.5 -75.5t95 -94.5l22 -22q93 -90 190 -201q82 92 195 203l12 12q64 62 97.5 97t64.5 79t31 72q0 71 -48 119.5t-106 48.5q-73 0 -131 -83l-118 -171l-114 174q-51 80 -124 80q-59 0 -108.5 -49.5t-49.5 -118.5z" />
<glyph unicode="&#xe144;" d="M57 353q0 -94 66 -160l141 -141q66 -66 159 -66q95 0 159 66l283 283q66 66 66 159t-66 159l-141 141q-12 12 -19 17l-105 -105l212 -212l-389 -389l-247 248l95 95l-18 18q-46 45 -75 101l-55 -55q-66 -66 -66 -159zM269 706q0 -93 66 -159l141 -141l19 -17l105 105 l-212 212l389 389l247 -247l-95 -96l18 -18q46 -46 77 -99l29 29q35 35 62.5 88t27.5 96q0 93 -66 159l-141 141q-66 66 -159 66q-95 0 -159 -66l-283 -283q-66 -64 -66 -159z" />
<glyph unicode="&#xe145;" d="M200 100v953q0 21 30 46t81 48t129 38t163 15t162 -15t127 -38t79 -48t29 -46v-953q0 -41 -29.5 -70.5t-70.5 -29.5h-600q-41 0 -70.5 29.5t-29.5 70.5zM300 300h600v700h-600v-700zM496 150q0 -43 30.5 -73.5t73.5 -30.5t73.5 30.5t30.5 73.5t-30.5 73.5t-73.5 30.5 t-73.5 -30.5t-30.5 -73.5z" />
<glyph unicode="&#xe146;" d="M0 0l303 380l207 208l-210 212h300l267 279l-35 36q-15 14 -15 35t15 35q14 15 35 15t35 -15l283 -282q15 -15 15 -36t-15 -35q-14 -15 -35 -15t-35 15l-36 35l-279 -267v-300l-212 210l-208 -207z" />
<glyph unicode="&#xe148;" d="M295 433h139q5 -77 48.5 -126.5t117.5 -64.5v335l-27 7q-46 14 -79 26.5t-72 36t-62.5 52t-40 72.5t-16.5 99q0 92 44 159.5t109 101t144 40.5v78h100v-79q38 -4 72.5 -13.5t75.5 -31.5t71 -53.5t51.5 -84t24.5 -118.5h-159q-8 72 -35 109.5t-101 50.5v-307l64 -14 q34 -7 64 -16.5t70 -31.5t67.5 -52t47.5 -80.5t20 -112.5q0 -139 -89 -224t-244 -96v-77h-100v78q-152 17 -237 104q-40 40 -52.5 93.5t-15.5 139.5zM466 889q0 -29 8 -51t16.5 -34t29.5 -22.5t31 -13.5t38 -10q7 -2 11 -3v274q-61 -8 -97.5 -37.5t-36.5 -102.5zM700 237 q170 18 170 151q0 64 -44 99.5t-126 60.5v-311z" />
<glyph unicode="&#xe149;" d="M100 600v100h166q-24 49 -44 104q-10 26 -14.5 55.5t-3 72.5t25 90t68.5 87q97 88 263 88q129 0 230 -89t101 -208h-153q0 52 -34 89.5t-74 51.5t-76 14q-37 0 -79 -14.5t-62 -35.5q-41 -44 -41 -101q0 -11 2.5 -24.5t5.5 -24t9.5 -26.5t10.5 -25t14 -27.5t14 -25.5 t15.5 -27t13.5 -24h242v-100h-197q8 -50 -2.5 -115t-31.5 -94q-41 -59 -99 -113q35 11 84 18t70 7q32 1 102 -16t104 -17q76 0 136 30l50 -147q-41 -25 -80.5 -36.5t-59 -13t-61.5 -1.5q-23 0 -128 33t-155 29q-39 -4 -82 -17t-66 -25l-24 -11l-55 145l16.5 11t15.5 10 t13.5 9.5t14.5 12t14.5 14t17.5 18.5q48 55 54 126.5t-30 142.5h-221z" />
<glyph unicode="&#xe150;" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM602 900l298 300l298 -300h-198v-900h-200v900h-198z" />
<glyph unicode="&#xe151;" d="M2 300h198v900h200v-900h198l-298 -300zM700 0v200h100v-100h200v-100h-300zM700 400v100h300v-200h-99v-100h-100v100h99v100h-200zM700 700v500h300v-500h-100v100h-100v-100h-100zM801 900h100v200h-100v-200z" />
<glyph unicode="&#xe152;" d="M2 300h198v900h200v-900h198l-298 -300zM700 0v500h300v-500h-100v100h-100v-100h-100zM700 700v200h100v-100h200v-100h-300zM700 1100v100h300v-200h-99v-100h-100v100h99v100h-200zM801 200h100v200h-100v-200z" />
<glyph unicode="&#xe153;" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM800 100v400h300v-500h-100v100h-200zM800 1100v100h200v-500h-100v400h-100zM901 200h100v200h-100v-200z" />
<glyph unicode="&#xe154;" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM800 400v100h200v-500h-100v400h-100zM800 800v400h300v-500h-100v100h-200zM901 900h100v200h-100v-200z" />
<glyph unicode="&#xe155;" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM700 100v200h500v-200h-500zM700 400v200h400v-200h-400zM700 700v200h300v-200h-300zM700 1000v200h200v-200h-200z" />
<glyph unicode="&#xe156;" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM700 100v200h200v-200h-200zM700 400v200h300v-200h-300zM700 700v200h400v-200h-400zM700 1000v200h500v-200h-500z" />
<glyph unicode="&#xe157;" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h300q162 0 281 -118.5t119 -281.5v-300q0 -165 -118.5 -282.5t-281.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500z" />
<glyph unicode="&#xe158;" d="M0 400v300q0 163 119 281.5t281 118.5h300q165 0 282.5 -117.5t117.5 -282.5v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-163 0 -281.5 117.5t-118.5 282.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM400 300l333 250l-333 250v-500z" />
<glyph unicode="&#xe159;" d="M0 400v300q0 163 117.5 281.5t282.5 118.5h300q163 0 281.5 -119t118.5 -281v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM300 700l250 -333l250 333h-500z" />
<glyph unicode="&#xe160;" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h300q165 0 282.5 -117.5t117.5 -282.5v-300q0 -162 -118.5 -281t-281.5 -119h-300q-165 0 -282.5 118.5t-117.5 281.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM300 400h500l-250 333z" />
<glyph unicode="&#xe161;" d="M0 400v300h300v200l400 -350l-400 -350v200h-300zM500 0v200h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-500v200h400q165 0 282.5 -117.5t117.5 -282.5v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-400z" />
<glyph unicode="&#xe162;" d="M216 519q10 -19 32 -19h302q-155 -438 -160 -458q-5 -21 4 -32l9 -8l9 -1q13 0 26 16l538 630q15 19 6 36q-8 18 -32 16h-300q1 4 78 219.5t79 227.5q2 17 -6 27l-8 8h-9q-16 0 -25 -15q-4 -5 -98.5 -111.5t-228 -257t-209.5 -238.5q-17 -19 -7 -40z" />
<glyph unicode="&#xe163;" d="M0 400q0 -165 117.5 -282.5t282.5 -117.5h300q47 0 100 15v185h-500q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5h500v185q-14 4 -114 7.5t-193 5.5l-93 2q-165 0 -282.5 -117.5t-117.5 -282.5v-300zM600 400v300h300v200l400 -350l-400 -350v200h-300z " />
<glyph unicode="&#xe164;" d="M0 400q0 -165 117.5 -282.5t282.5 -117.5h300q163 0 281.5 117.5t118.5 282.5v98l-78 73l-122 -123v-148q0 -41 -29.5 -70.5t-70.5 -29.5h-500q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5h156l118 122l-74 78h-100q-165 0 -282.5 -117.5t-117.5 -282.5 v-300zM496 709l353 342l-149 149h500v-500l-149 149l-342 -353z" />
<glyph unicode="&#xe165;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM406 600 q0 80 57 137t137 57t137 -57t57 -137t-57 -137t-137 -57t-137 57t-57 137z" />
<glyph unicode="&#xe166;" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 800l445 -500l450 500h-295v400h-300v-400h-300zM900 150h100v50h-100v-50z" />
<glyph unicode="&#xe167;" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 700h300v-300h300v300h295l-445 500zM900 150h100v50h-100v-50z" />
<glyph unicode="&#xe168;" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 705l305 -305l596 596l-154 155l-442 -442l-150 151zM900 150h100v50h-100v-50z" />
<glyph unicode="&#xe169;" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 988l97 -98l212 213l-97 97zM200 401h700v699l-250 -239l-149 149l-212 -212l149 -149zM900 150h100v50h-100v-50z" />
<glyph unicode="&#xe170;" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM200 612l212 -212l98 97l-213 212zM300 1200l239 -250l-149 -149l212 -212l149 148l248 -237v700h-699zM900 150h100v50h-100v-50z" />
<glyph unicode="&#xe171;" d="M23 415l1177 784v-1079l-475 272l-310 -393v416h-392zM494 210l672 938l-672 -712v-226z" />
<glyph unicode="&#xe172;" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-850q0 -21 -15 -35.5t-35 -14.5h-150v400h-700v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 1000h100v200h-100v-200z" />
<glyph unicode="&#xe173;" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-218l-276 -275l-120 120l-126 -127h-378v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM581 306l123 123l120 -120l353 352l123 -123l-475 -476zM600 1000h100v200h-100v-200z" />
<glyph unicode="&#xe174;" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-269l-103 -103l-170 170l-298 -298h-329v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 1000h100v200h-100v-200zM700 133l170 170l-170 170l127 127l170 -170l170 170l127 -128l-170 -169l170 -170 l-127 -127l-170 170l-170 -170z" />
<glyph unicode="&#xe175;" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-300h-400v-200h-500v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 300l300 -300l300 300h-200v300h-200v-300h-200zM600 1000v200h100v-200h-100z" />
<glyph unicode="&#xe176;" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-402l-200 200l-298 -298h-402v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 300h200v-300h200v300h200l-300 300zM600 1000v200h100v-200h-100z" />
<glyph unicode="&#xe177;" d="M0 250q0 -21 14.5 -35.5t35.5 -14.5h1100q21 0 35.5 14.5t14.5 35.5v550h-1200v-550zM0 900h1200v150q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-150zM100 300v200h400v-200h-400z" />
<glyph unicode="&#xe178;" d="M0 400l300 298v-198h400v-200h-400v-198zM100 800v200h100v-200h-100zM300 800v200h100v-200h-100zM500 800v200h400v198l300 -298l-300 -298v198h-400zM800 300v200h100v-200h-100zM1000 300h100v200h-100v-200z" />
<glyph unicode="&#xe179;" d="M100 700v400l50 100l50 -100v-300h100v300l50 100l50 -100v-300h100v300l50 100l50 -100v-400l-100 -203v-447q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v447zM800 597q0 -29 10.5 -55.5t25 -43t29 -28.5t25.5 -18l10 -5v-397q0 -21 14.5 -35.5 t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v1106q0 31 -18 40.5t-44 -7.5l-276 -117q-25 -16 -43.5 -50.5t-18.5 -65.5v-359z" />
<glyph unicode="&#xe180;" d="M100 0h400v56q-75 0 -87.5 6t-12.5 44v394h500v-394q0 -38 -12.5 -44t-87.5 -6v-56h400v56q-4 0 -11 0.5t-24 3t-30 7t-24 15t-11 24.5v888q0 22 25 34.5t50 13.5l25 2v56h-400v-56q75 0 87.5 -6t12.5 -44v-394h-500v394q0 38 12.5 44t87.5 6v56h-400v-56q4 0 11 -0.5 t24 -3t30 -7t24 -15t11 -24.5v-888q0 -22 -25 -34.5t-50 -13.5l-25 -2v-56z" />
<glyph unicode="&#xe181;" d="M0 300q0 -41 29.5 -70.5t70.5 -29.5h300q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-300q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM100 100h400l200 200h105l295 98v-298h-425l-100 -100h-375zM100 300v200h300v-200h-300zM100 600v200h300v-200h-300z M100 1000h400l200 -200v-98l295 98h105v200h-425l-100 100h-375zM700 402v163l400 133v-163z" />
<glyph unicode="&#xe182;" d="M16.5 974.5q0.5 -21.5 16 -90t46.5 -140t104 -177.5t175 -208q103 -103 207.5 -176t180 -103.5t137 -47t92.5 -16.5l31 1l163 162q16 17 13 40.5t-22 37.5l-192 136q-19 14 -45 12t-42 -19l-119 -118q-143 103 -267 227q-126 126 -227 268l118 118q17 17 20 41.5 t-11 44.5l-139 194q-14 19 -36.5 22t-40.5 -14l-162 -162q-1 -11 -0.5 -32.5z" />
<glyph unicode="&#xe183;" d="M0 50v212q0 20 10.5 45.5t24.5 39.5l365 303v50q0 4 1 10.5t12 22.5t30 28.5t60 23t97 10.5t97 -10t60 -23.5t30 -27.5t12 -24l1 -10v-50l365 -303q14 -14 24.5 -39.5t10.5 -45.5v-212q0 -21 -15 -35.5t-35 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5zM0 712 q0 -21 14.5 -33.5t34.5 -8.5l202 33q20 4 34.5 21t14.5 38v146q141 24 300 24t300 -24v-146q0 -21 14.5 -38t34.5 -21l202 -33q20 -4 34.5 8.5t14.5 33.5v200q-6 8 -19 20.5t-63 45t-112 57t-171 45t-235 20.5q-92 0 -175 -10.5t-141.5 -27t-108.5 -36.5t-81.5 -40 t-53.5 -36.5t-31 -27.5l-9 -10v-200z" />
<glyph unicode="&#xe184;" d="M100 0v100h1100v-100h-1100zM175 200h950l-125 150v250l100 100v400h-100v-200h-100v200h-200v-200h-100v200h-200v-200h-100v200h-100v-400l100 -100v-250z" />
<glyph unicode="&#xe185;" d="M100 0h300v400q0 41 -29.5 70.5t-70.5 29.5h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-400zM500 0v1000q0 41 29.5 70.5t70.5 29.5h100q41 0 70.5 -29.5t29.5 -70.5v-1000h-300zM900 0v700q0 41 29.5 70.5t70.5 29.5h100q41 0 70.5 -29.5t29.5 -70.5v-700h-300z" />
<glyph unicode="&#xe186;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v300h-200v100h200v100h-300v-300h200v-100h-200v-100zM600 300h200v100h100v300h-100v100h-200v-500 zM700 400v300h100v-300h-100z" />
<glyph unicode="&#xe187;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h100v200h100v-200h100v500h-100v-200h-100v200h-100v-500zM600 300h200v100h100v300h-100v100h-200v-500 zM700 400v300h100v-300h-100z" />
<glyph unicode="&#xe188;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v100h-200v300h200v100h-300v-500zM600 300h300v100h-200v300h200v100h-300v-500z" />
<glyph unicode="&#xe189;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 550l300 -150v300zM600 400l300 150l-300 150v-300z" />
<glyph unicode="&#xe190;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300v500h700v-500h-700zM300 400h130q41 0 68 42t27 107t-28.5 108t-66.5 43h-130v-300zM575 549 q0 -65 27 -107t68 -42h130v300h-130q-38 0 -66.5 -43t-28.5 -108z" />
<glyph unicode="&#xe191;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v300h-200v100h200v100h-300v-300h200v-100h-200v-100zM601 300h100v100h-100v-100zM700 700h100 v-400h100v500h-200v-100z" />
<glyph unicode="&#xe192;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v400h-200v100h-100v-500zM301 400v200h100v-200h-100zM601 300h100v100h-100v-100zM700 700h100 v-400h100v500h-200v-100z" />
<glyph unicode="&#xe193;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 700v100h300v-300h-99v-100h-100v100h99v200h-200zM201 300v100h100v-100h-100zM601 300v100h100v-100h-100z M700 700v100h200v-500h-100v400h-100z" />
<glyph unicode="&#xe194;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM400 500v200 l100 100h300v-100h-300v-200h300v-100h-300z" />
<glyph unicode="&#xe195;" d="M0 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM182 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM400 400v400h300 l100 -100v-100h-100v100h-200v-100h200v-100h-200v-100h-100zM700 400v100h100v-100h-100z" />
<glyph unicode="&#xe197;" d="M-14 494q0 -80 56.5 -137t135.5 -57h222v300h400v-300h128q120 0 205 86t85 208q0 120 -85 206.5t-205 86.5q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5zM300 200h200v300h200v-300 h200l-300 -300z" />
<glyph unicode="&#xe198;" d="M-14 494q0 -80 56.5 -137t135.5 -57h8l414 414l403 -403q94 26 154.5 104t60.5 178q0 121 -85 207.5t-205 86.5q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5zM300 200l300 300 l300 -300h-200v-300h-200v300h-200z" />
<glyph unicode="&#xe199;" d="M100 200h400v-155l-75 -45h350l-75 45v155h400l-270 300h170l-270 300h170l-300 333l-300 -333h170l-270 -300h170z" />
<glyph unicode="&#xe200;" d="M121 700q0 -53 28.5 -97t75.5 -65q-4 -16 -4 -38q0 -74 52.5 -126.5t126.5 -52.5q56 0 100 30v-306l-75 -45h350l-75 45v306q46 -30 100 -30q74 0 126.5 52.5t52.5 126.5q0 24 -9 55q50 32 79.5 83t29.5 112q0 90 -61.5 155.5t-150.5 71.5q-26 89 -99.5 145.5 t-167.5 56.5q-116 0 -197.5 -81.5t-81.5 -197.5q0 -4 1 -12t1 -11q-14 2 -23 2q-74 0 -126.5 -52.5t-52.5 -126.5z" />
</font>
</defs></svg>

After

Width:  |  Height:  |  Size: 62 KiB

View File

@@ -0,0 +1,468 @@
<!DOCTYPE html>
<!--
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2019-05-23
| Rendered using Apache Maven Fluido Skin 1.5
-->
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="Date-Revision-yyyymmdd" content="20190523" />
<meta http-equiv="Content-Language" content="en" />
<title>Spring Cloud Contract Maven Plugin &#x2013; spring-cloud-contract:generateStubs</title>
<link rel="stylesheet" href="./css/apache-maven-fluido-1.5.min.css" />
<link rel="stylesheet" href="./css/site.css" />
<link rel="stylesheet" href="./css/print.css" media="print" />
<script type="text/javascript" src="./js/apache-maven-fluido-1.5.min.js"></script>
</head>
<body class="topBarEnabled">
<a href="https://github.com/spring-cloud/spring-cloud-contract">
<img style="position: absolute; top: 0; right: 0; border: 0; z-index: 10000;"
src="https://s3.amazonaws.com/github/ribbons/forkme_right_orange_ff7600.png"
alt="Fork me on GitHub">
</a>
<div id="topbar" class="navbar navbar-fixed-top ">
<div class="navbar-inner">
<div class="container-fluid">
<a data-target=".nav-collapse" data-toggle="collapse" class="btn btn-navbar">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<ul class="nav">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Overview <b class="caret"></b></a>
<ul class="dropdown-menu">
<li> <a href="index.html" title="Introduction">Introduction</a>
</li>
<li> <a href="usage.html" title="Usage">Usage</a>
</li>
<li> <a href="plugin-info.html" title="Goals">Goals</a>
</li>
<li> <a href="junit.html" title="JUnit Configuration">JUnit Configuration</a>
</li>
<li> <a href="spock.html" title="Spock Configuration">Spock Configuration</a>
</li>
<li> <a href="complex.html" title="Complex Configuration">Complex Configuration</a>
</li>
<li> <a href="configs.html" title="Configuration snippets">Configuration snippets</a>
</li>
</ul>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Related Projects <b class="caret"></b></a>
<ul class="dropdown-menu">
<li> <a href="https://github.com/spring-cloud/spring-cloud-contract" title="Spring Cloud Contract">Spring Cloud Contract</a>
</li>
</ul>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Project Documentation <b class="caret"></b></a>
<ul class="dropdown-menu">
<li class="dropdown-submenu">
<a href="project-info.html" title="Project Information">Project Information</a>
<ul class="dropdown-menu">
<li> <a href="integration.html" title="CI Management">CI Management</a>
</li>
<li> <a href="index.html" title="About">About</a>
</li>
<li> <a href="issue-tracking.html" title="Issue Management">Issue Management</a>
</li>
<li> <a href="license.html" title="Licenses">Licenses</a>
</li>
<li> <a href="plugin-management.html" title="Plugin Management">Plugin Management</a>
</li>
<li> <a href="plugins.html" title="Plugins">Plugins</a>
</li>
<li> <a href="team-list.html" title="Team">Team</a>
</li>
<li> <a href="source-repository.html" title="Source Code Management">Source Code Management</a>
</li>
<li> <a href="project-summary.html" title="Summary">Summary</a>
</li>
</ul>
</li>
<li class="dropdown-submenu">
<a href="project-reports.html" title="Project Reports">Project Reports</a>
<ul class="dropdown-menu">
<li> <a href="checkstyle.html" title="Checkstyle">Checkstyle</a>
</li>
<li> <a href="plugin-info.html" title="Plugin Documentation">Plugin Documentation</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="container-fluid">
<div id="banner">
<div class="pull-left">
<div id="bannerLeft">
<h2>Spring Cloud Contract Maven Plugin</h2>
</div>
</div>
<div class="pull-right"> <div id="bannerRight">
<img src="" />
</div>
</div>
<div class="clear"><hr/></div>
</div>
<div id="breadcrumbs">
<ul class="breadcrumb">
<li id="publishDate">Last Published: 2019-05-23
<span class="divider">|</span>
</li>
<li id="projectVersion">Version: 1.2.7.RELEASE
</li>
</ul>
</div>
<div class="row-fluid">
<div id="leftColumn" class="span2">
<div class="well sidebar-nav">
<ul class="nav nav-list">
<li class="nav-header">Overview</li>
<li>
<a href="index.html" title="Introduction">
<span class="none"></span>
Introduction</a>
</li>
<li>
<a href="usage.html" title="Usage">
<span class="none"></span>
Usage</a>
</li>
<li>
<a href="plugin-info.html" title="Goals">
<span class="none"></span>
Goals</a>
</li>
<li>
<a href="junit.html" title="JUnit Configuration">
<span class="none"></span>
JUnit Configuration</a>
</li>
<li>
<a href="spock.html" title="Spock Configuration">
<span class="none"></span>
Spock Configuration</a>
</li>
<li>
<a href="complex.html" title="Complex Configuration">
<span class="none"></span>
Complex Configuration</a>
</li>
<li>
<a href="configs.html" title="Configuration snippets">
<span class="none"></span>
Configuration snippets</a>
</li>
<li class="nav-header">Related Projects</li>
<li>
<a href="https://github.com/spring-cloud/spring-cloud-contract" title="Spring Cloud Contract">
<span class="none"></span>
Spring Cloud Contract</a>
</li>
<li class="nav-header">Project Documentation</li>
<li>
<a href="project-info.html" title="Project Information">
<span class="icon-chevron-right"></span>
Project Information</a>
</li>
<li>
<a href="project-reports.html" title="Project Reports">
<span class="icon-chevron-right"></span>
Project Reports</a>
</li>
</ul>
<hr />
<div id="poweredBy">
<div class="clear"></div>
<div class="clear"></div>
<div class="clear"></div>
<div class="clear"></div>
<a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy">
<img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" />
</a>
</div>
</div>
</div>
<div id="bodyColumn" class="span10" >
<div class="section">
<h2><a name="spring-cloud-contract:generateStubs"></a>spring-cloud-contract:generateStubs</h2>
<p><b>Full name</b>:</p>
<p>org.springframework.cloud:spring-cloud-contract-maven-plugin:1.2.7.RELEASE:generateStubs</p>
<p><b>Description</b>:</p>
<div>Picks the converted .json files and creates a jar. Requires convert
to be executed first</div>
<p><b>Attributes</b>:</p>
<ul>
<li>Requires a Maven project to be executed.</li>
<li>Binds by default to the <a class="externalLink" href="http://maven.apache.org/ref/current/maven-core/lifecycles.html">lifecycle phase</a>: <tt>package</tt>.</li>
</ul>
<div class="section">
<h3><a name="Optional_Parameters"></a>Optional Parameters</h3>
<table class="table table-striped" border="0">
<tr class="a">
<th>Name</th>
<th>Type</th>
<th>Since</th>
<th>Description</th>
</tr>
<tr class="b">
<td><b><a href="#attachContracts">attachContracts</a></b></td>
<td><tt>boolean</tt></td>
<td><tt>-</tt></td>
<td>(no description)<br /><b>Default value is</b>: <tt>true</tt>.<br /></td>
</tr>
<tr class="a">
<td><b><a href="#classifier">classifier</a></b></td>
<td><tt>String</tt></td>
<td><tt>-</tt></td>
<td>(no description)<br /><b>Default value is</b>: <tt>stubs</tt>.<br /></td>
</tr>
<tr class="b">
<td><b><a href="#excludedFiles">excludedFiles</a></b></td>
<td><tt>String[]</tt></td>
<td><tt>-</tt></td>
<td>Patterns that should not be taken into account for processing<br /></td>
</tr>
<tr class="a">
<td><b><a href="#jarSkip">jarSkip</a></b></td>
<td><tt>boolean</tt></td>
<td><tt>-</tt></td>
<td>Set this to &quot;true&quot; to bypass only JAR creation<br /><b>Default value is</b>: <tt>false</tt>.<br /><b>User property is</b>: <tt>spring.cloud.contract.verifier.jar.skip</tt>.</td>
</tr>
<tr class="b">
<td><b><a href="#outputDirectory">outputDirectory</a></b></td>
<td><tt>File</tt></td>
<td><tt>-</tt></td>
<td>(no description)<br /><b>Default value is</b>: <tt>${project.build.directory}/stubs</tt>.<br /><b>User property is</b>: <tt>stubsDirectory</tt>.</td>
</tr>
<tr class="a">
<td><b><a href="#skip">skip</a></b></td>
<td><tt>boolean</tt></td>
<td><tt>-</tt></td>
<td>Set this to &quot;true&quot; to bypass the whole Verifier execution<br /><b>Default value is</b>: <tt>false</tt>.<br /><b>User property is</b>: <tt>spring.cloud.contract.verifier.skip</tt>.</td>
</tr>
</table>
</div>
<div class="section">
<h3><a name="Parameter_Details"></a>Parameter Details</h3>
<p><b><a name="attachContracts">attachContracts</a>:</b></p>
<div>(no description)</div>
<ul>
<li><b>Type</b>: <tt>boolean</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>Default</b>: <tt>true</tt></li>
</ul><hr />
<p><b><a name="classifier">classifier</a>:</b></p>
<div>(no description)</div>
<ul>
<li><b>Type</b>: <tt>java.lang.String</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>Default</b>: <tt>stubs</tt></li>
</ul><hr />
<p><b><a name="excludedFiles">excludedFiles</a>:</b></p>
<div>Patterns that should not be taken into account for processing</div>
<ul>
<li><b>Type</b>: <tt>java.lang.String[]</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
</ul><hr />
<p><b><a name="jarSkip">jarSkip</a>:</b></p>
<div>Set this to &quot;true&quot; to bypass only JAR creation</div>
<ul>
<li><b>Type</b>: <tt>boolean</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>User Property</b>: <tt>spring.cloud.contract.verifier.jar.skip</tt></li>
<li><b>Default</b>: <tt>false</tt></li>
</ul><hr />
<p><b><a name="outputDirectory">outputDirectory</a>:</b></p>
<div>(no description)</div>
<ul>
<li><b>Type</b>: <tt>java.io.File</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>User Property</b>: <tt>stubsDirectory</tt></li>
<li><b>Default</b>: <tt>${project.build.directory}/stubs</tt></li>
</ul><hr />
<p><b><a name="skip">skip</a>:</b></p>
<div>Set this to &quot;true&quot; to bypass the whole Verifier execution</div>
<ul>
<li><b>Type</b>: <tt>boolean</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>User Property</b>: <tt>spring.cloud.contract.verifier.skip</tt></li>
<li><b>Default</b>: <tt>false</tt></li>
</ul>
</div>
</div>
</div>
</div>
</div>
<hr/>
<footer>
<div class="container-fluid">
<div class="row-fluid">
<p >Copyright &copy; 2016&#x2013;2019
<a href="https://spring.io/">Spring</a>.
All rights reserved.
</p>
</div>
</div>
</footer>
</body>
</html>

View File

@@ -0,0 +1,984 @@
<!DOCTYPE html>
<!--
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2019-05-23
| Rendered using Apache Maven Fluido Skin 1.5
-->
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="Date-Revision-yyyymmdd" content="20190523" />
<meta http-equiv="Content-Language" content="en" />
<title>Spring Cloud Contract Maven Plugin &#x2013; spring-cloud-contract:generateTests</title>
<link rel="stylesheet" href="./css/apache-maven-fluido-1.5.min.css" />
<link rel="stylesheet" href="./css/site.css" />
<link rel="stylesheet" href="./css/print.css" media="print" />
<script type="text/javascript" src="./js/apache-maven-fluido-1.5.min.js"></script>
</head>
<body class="topBarEnabled">
<a href="https://github.com/spring-cloud/spring-cloud-contract">
<img style="position: absolute; top: 0; right: 0; border: 0; z-index: 10000;"
src="https://s3.amazonaws.com/github/ribbons/forkme_right_orange_ff7600.png"
alt="Fork me on GitHub">
</a>
<div id="topbar" class="navbar navbar-fixed-top ">
<div class="navbar-inner">
<div class="container-fluid">
<a data-target=".nav-collapse" data-toggle="collapse" class="btn btn-navbar">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<ul class="nav">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Overview <b class="caret"></b></a>
<ul class="dropdown-menu">
<li> <a href="index.html" title="Introduction">Introduction</a>
</li>
<li> <a href="usage.html" title="Usage">Usage</a>
</li>
<li> <a href="plugin-info.html" title="Goals">Goals</a>
</li>
<li> <a href="junit.html" title="JUnit Configuration">JUnit Configuration</a>
</li>
<li> <a href="spock.html" title="Spock Configuration">Spock Configuration</a>
</li>
<li> <a href="complex.html" title="Complex Configuration">Complex Configuration</a>
</li>
<li> <a href="configs.html" title="Configuration snippets">Configuration snippets</a>
</li>
</ul>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Related Projects <b class="caret"></b></a>
<ul class="dropdown-menu">
<li> <a href="https://github.com/spring-cloud/spring-cloud-contract" title="Spring Cloud Contract">Spring Cloud Contract</a>
</li>
</ul>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Project Documentation <b class="caret"></b></a>
<ul class="dropdown-menu">
<li class="dropdown-submenu">
<a href="project-info.html" title="Project Information">Project Information</a>
<ul class="dropdown-menu">
<li> <a href="integration.html" title="CI Management">CI Management</a>
</li>
<li> <a href="index.html" title="About">About</a>
</li>
<li> <a href="issue-tracking.html" title="Issue Management">Issue Management</a>
</li>
<li> <a href="license.html" title="Licenses">Licenses</a>
</li>
<li> <a href="plugin-management.html" title="Plugin Management">Plugin Management</a>
</li>
<li> <a href="plugins.html" title="Plugins">Plugins</a>
</li>
<li> <a href="team-list.html" title="Team">Team</a>
</li>
<li> <a href="source-repository.html" title="Source Code Management">Source Code Management</a>
</li>
<li> <a href="project-summary.html" title="Summary">Summary</a>
</li>
</ul>
</li>
<li class="dropdown-submenu">
<a href="project-reports.html" title="Project Reports">Project Reports</a>
<ul class="dropdown-menu">
<li> <a href="checkstyle.html" title="Checkstyle">Checkstyle</a>
</li>
<li> <a href="plugin-info.html" title="Plugin Documentation">Plugin Documentation</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="container-fluid">
<div id="banner">
<div class="pull-left">
<div id="bannerLeft">
<h2>Spring Cloud Contract Maven Plugin</h2>
</div>
</div>
<div class="pull-right"> <div id="bannerRight">
<img src="" />
</div>
</div>
<div class="clear"><hr/></div>
</div>
<div id="breadcrumbs">
<ul class="breadcrumb">
<li id="publishDate">Last Published: 2019-05-23
<span class="divider">|</span>
</li>
<li id="projectVersion">Version: 1.2.7.RELEASE
</li>
</ul>
</div>
<div class="row-fluid">
<div id="leftColumn" class="span2">
<div class="well sidebar-nav">
<ul class="nav nav-list">
<li class="nav-header">Overview</li>
<li>
<a href="index.html" title="Introduction">
<span class="none"></span>
Introduction</a>
</li>
<li>
<a href="usage.html" title="Usage">
<span class="none"></span>
Usage</a>
</li>
<li>
<a href="plugin-info.html" title="Goals">
<span class="none"></span>
Goals</a>
</li>
<li>
<a href="junit.html" title="JUnit Configuration">
<span class="none"></span>
JUnit Configuration</a>
</li>
<li>
<a href="spock.html" title="Spock Configuration">
<span class="none"></span>
Spock Configuration</a>
</li>
<li>
<a href="complex.html" title="Complex Configuration">
<span class="none"></span>
Complex Configuration</a>
</li>
<li>
<a href="configs.html" title="Configuration snippets">
<span class="none"></span>
Configuration snippets</a>
</li>
<li class="nav-header">Related Projects</li>
<li>
<a href="https://github.com/spring-cloud/spring-cloud-contract" title="Spring Cloud Contract">
<span class="none"></span>
Spring Cloud Contract</a>
</li>
<li class="nav-header">Project Documentation</li>
<li>
<a href="project-info.html" title="Project Information">
<span class="icon-chevron-right"></span>
Project Information</a>
</li>
<li>
<a href="project-reports.html" title="Project Reports">
<span class="icon-chevron-right"></span>
Project Reports</a>
</li>
</ul>
<hr />
<div id="poweredBy">
<div class="clear"></div>
<div class="clear"></div>
<div class="clear"></div>
<div class="clear"></div>
<a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy">
<img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" />
</a>
</div>
</div>
</div>
<div id="bodyColumn" class="span10" >
<div class="section">
<h2><a name="spring-cloud-contract:generateTests"></a>spring-cloud-contract:generateTests</h2>
<p><b>Full name</b>:</p>
<p>org.springframework.cloud:spring-cloud-contract-maven-plugin:1.2.7.RELEASE:generateTests</p>
<p><b>Description</b>:</p>
<div>From the provided directory with contracts generates the acceptance
tests on the producer side</div>
<p><b>Attributes</b>:</p>
<ul>
<li>Requires a Maven project to be executed.</li>
<li>Requires dependency resolution of artifacts in scope: <tt>test</tt>.</li>
<li>Binds by default to the <a class="externalLink" href="http://maven.apache.org/ref/current/maven-core/lifecycles.html">lifecycle phase</a>: <tt>generate-test-sources</tt>.</li>
</ul>
<div class="section">
<h3><a name="Optional_Parameters"></a>Optional Parameters</h3>
<table class="table table-striped" border="0">
<tr class="a">
<th>Name</th>
<th>Type</th>
<th>Since</th>
<th>Description</th>
</tr>
<tr class="b">
<td><b><a href="#assertJsonSize">assertJsonSize</a></b></td>
<td><tt>boolean</tt></td>
<td><tt>-</tt></td>
<td>Incubating feature. You can check the size of JSON arrays. If not
turned on explicitly will be disabled.<br /><b>Default value is</b>: <tt>false</tt>.<br /><b>User property is</b>: <tt>spring.cloud.contract.verifier.assert.size</tt>.</td>
</tr>
<tr class="a">
<td><b><a href="#baseClassForTests">baseClassForTests</a></b></td>
<td><tt>String</tt></td>
<td><tt>-</tt></td>
<td>(no description)<br /></td>
</tr>
<tr class="b">
<td><b><a href="#baseClassMappings">baseClassMappings</a></b></td>
<td><tt>List</tt></td>
<td><tt>-</tt></td>
<td>A way to override any base class mappings. The keys are regular
expressions on the package name of the contract and the values FQN
to a base class for that given expression. <br />
<br />
Example of a mapping <br />
<br />
<tt>.*.com.example.v1..*</tt> -&gt;
<tt>com.example.SomeBaseClass</tt> <br />
<br />
When a contract's package matches the provided regular expression
then extending class will be the one provided in the map - in this
case <tt>com.example.SomeBaseClass</tt><br /><b>User property is</b>: <tt>baseClassMappings</tt>.</td>
</tr>
<tr class="a">
<td><b><a href="#basePackageForTests">basePackageForTests</a></b></td>
<td><tt>String</tt></td>
<td><tt>-</tt></td>
<td>(no description)<br /></td>
</tr>
<tr class="b">
<td><b><a href="#contractDependency">contractDependency</a></b></td>
<td><tt>Dependency</tt></td>
<td><tt>-</tt></td>
<td>(no description)<br /><b>User property is</b>: <tt>contractDependency</tt>.</td>
</tr>
<tr class="a">
<td><b><a href="#contractsDirectory">contractsDirectory</a></b></td>
<td><tt>File</tt></td>
<td><tt>-</tt></td>
<td>(no description)<br /><b>Default value is</b>: <tt>${project.basedir}/src/test/resources/contracts</tt>.<br /><b>User property is</b>: <tt>spring.cloud.contract.verifier.contractsDirectory</tt>.</td>
</tr>
<tr class="b">
<td><b><a href="#contractsPath">contractsPath</a></b></td>
<td><tt>String</tt></td>
<td><tt>-</tt></td>
<td>The path in the JAR with all the contracts where contracts for this
particular service lay. If not provided will be resolved to
<tt>groupid/artifactid</tt>. Example: <br />
<br />
If <tt>groupid</tt> is <tt>com.example</tt> and
<tt>artifactid</tt> is <tt>service</tt> then the resolved
path will be <tt>/com/example/artifactid</tt><br /><b>User property is</b>: <tt>contractsPath</tt>.</td>
</tr>
<tr class="a">
<td><b><a href="#contractsRepositoryPassword">contractsRepositoryPassword</a></b></td>
<td><tt>String</tt></td>
<td><tt>-</tt></td>
<td>The password to be used to connect to the repo with contracts.<br /><b>User property is</b>: <tt>contractsRepositoryPassword</tt>.</td>
</tr>
<tr class="b">
<td><b><a href="#contractsRepositoryProxyHost">contractsRepositoryProxyHost</a></b></td>
<td><tt>String</tt></td>
<td><tt>-</tt></td>
<td>The proxy host to be used to connect to the repo with contracts.<br /><b>User property is</b>: <tt>contractsRepositoryProxyHost</tt>.</td>
</tr>
<tr class="a">
<td><b><a href="#contractsRepositoryProxyPort">contractsRepositoryProxyPort</a></b></td>
<td><tt>Integer</tt></td>
<td><tt>-</tt></td>
<td>The proxy port to be used to connect to the repo with contracts.<br /><b>User property is</b>: <tt>contractsRepositoryProxyPort</tt>.</td>
</tr>
<tr class="b">
<td><b><a href="#contractsRepositoryUrl">contractsRepositoryUrl</a></b></td>
<td><tt>String</tt></td>
<td><tt>-</tt></td>
<td>The URL from which a JAR containing the contracts should get
downloaded. If not provided but artifactid / coordinates notation
was provided then the current Maven's build repositories will be
taken into consideration<br /><b>User property is</b>: <tt>contractsRepositoryUrl</tt>.</td>
</tr>
<tr class="a">
<td><b><a href="#contractsRepositoryUsername">contractsRepositoryUsername</a></b></td>
<td><tt>String</tt></td>
<td><tt>-</tt></td>
<td>The user name to be used to connect to the repo with contracts.<br /><b>User property is</b>: <tt>contractsRepositoryUsername</tt>.</td>
</tr>
<tr class="b">
<td><b><a href="#contractsWorkOffline">contractsWorkOffline</a></b></td>
<td><tt>boolean</tt></td>
<td><tt>-</tt></td>
<td>If <tt>true</tt> then JAR with contracts will be taken from
local maven repository<br /><b>Default value is</b>: <tt>false</tt>.<br /><b>User property is</b>: <tt>contractsWorkOffline</tt>.</td>
</tr>
<tr class="a">
<td><b><a href="#excludedFiles">excludedFiles</a></b></td>
<td><tt>List</tt></td>
<td><tt>-</tt></td>
<td>Patterns that should not be taken into account for processing<br /></td>
</tr>
<tr class="b">
<td><b><a href="#generatedTestSourcesDir">generatedTestSourcesDir</a></b></td>
<td><tt>File</tt></td>
<td><tt>-</tt></td>
<td>(no description)<br /><b>Default value is</b>: <tt>${project.build.directory}/generated-test-sources/contracts</tt>.<br /></td>
</tr>
<tr class="a">
<td><b><a href="#ignoredFiles">ignoredFiles</a></b></td>
<td><tt>List</tt></td>
<td><tt>-</tt></td>
<td>Patterns for which Spring Cloud Contract Verifier should generate
@Ignored tests<br /></td>
</tr>
<tr class="b">
<td><b><a href="#imports">imports</a></b></td>
<td><tt>String[]</tt></td>
<td><tt>-</tt></td>
<td>Imports that should be added to generated tests<br /></td>
</tr>
<tr class="a">
<td><b><a href="#mavenTestSkip">mavenTestSkip</a></b></td>
<td><tt>boolean</tt></td>
<td><tt>-</tt></td>
<td>(no description)<br /><b>Default value is</b>: <tt>false</tt>.<br /><b>User property is</b>: <tt>maven.test.skip</tt>.</td>
</tr>
<tr class="b">
<td><b><a href="#nameSuffixForTests">nameSuffixForTests</a></b></td>
<td><tt>String</tt></td>
<td><tt>-</tt></td>
<td>(no description)<br /></td>
</tr>
<tr class="a">
<td><b><a href="#packageWithBaseClasses">packageWithBaseClasses</a></b></td>
<td><tt>String</tt></td>
<td><tt>-</tt></td>
<td>A package that contains all the base clases for generated tests. If
your contract resides in a location
<tt>src/test/resources/contracts/com/example/v1/</tt> and you
provide the <tt>packageWithBaseClasses</tt> value to
<tt>com.example.contracts.base</tt> then we will search for a
test source file that will have the package
<tt>com.example.contracts.base</tt> and name
<tt>ExampleV1Base</tt>. As you can see it will take the two
last folders to and attach <tt>Base</tt> to its name.<br /><b>User property is</b>: <tt>packageWithBaseClasses</tt>.</td>
</tr>
<tr class="b">
<td><b><a href="#ruleClassForTests">ruleClassForTests</a></b></td>
<td><tt>String</tt></td>
<td><tt>-</tt></td>
<td>(no description)<br /></td>
</tr>
<tr class="a">
<td><b><a href="#skip">skip</a></b></td>
<td><tt>boolean</tt></td>
<td><tt>-</tt></td>
<td>(no description)<br /><b>Default value is</b>: <tt>false</tt>.<br /><b>User property is</b>: <tt>spring.cloud.contract.verifier.skip</tt>.</td>
</tr>
<tr class="b">
<td><b><a href="#skipTests">skipTests</a></b></td>
<td><tt>boolean</tt></td>
<td><tt>-</tt></td>
<td>(no description)<br /><b>Default value is</b>: <tt>false</tt>.<br /><b>User property is</b>: <tt>skipTests</tt>.</td>
</tr>
<tr class="a">
<td><b><a href="#staticImports">staticImports</a></b></td>
<td><tt>String[]</tt></td>
<td><tt>-</tt></td>
<td>Static imports that should be added to generated tests<br /></td>
</tr>
<tr class="b">
<td><b><a href="#testFramework">testFramework</a></b></td>
<td><tt>TestFramework</tt></td>
<td><tt>-</tt></td>
<td>(no description)<br /><b>Default value is</b>: <tt>JUNIT</tt>.<br /></td>
</tr>
<tr class="a">
<td><b><a href="#testMode">testMode</a></b></td>
<td><tt>TestMode</tt></td>
<td><tt>-</tt></td>
<td>(no description)<br /><b>Default value is</b>: <tt>MOCKMVC</tt>.<br /></td>
</tr>
</table>
</div>
<div class="section">
<h3><a name="Parameter_Details"></a>Parameter Details</h3>
<p><b><a name="assertJsonSize">assertJsonSize</a>:</b></p>
<div>Incubating feature. You can check the size of JSON arrays. If not
turned on explicitly will be disabled.</div>
<ul>
<li><b>Type</b>: <tt>boolean</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>User Property</b>: <tt>spring.cloud.contract.verifier.assert.size</tt></li>
<li><b>Default</b>: <tt>false</tt></li>
</ul><hr />
<p><b><a name="baseClassForTests">baseClassForTests</a>:</b></p>
<div>(no description)</div>
<ul>
<li><b>Type</b>: <tt>java.lang.String</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
</ul><hr />
<p><b><a name="baseClassMappings">baseClassMappings</a>:</b></p>
<div>A way to override any base class mappings. The keys are regular
expressions on the package name of the contract and the values FQN
to a base class for that given expression. <br />
<br />
Example of a mapping <br />
<br />
<tt>.*.com.example.v1..*</tt> -&gt;
<tt>com.example.SomeBaseClass</tt> <br />
<br />
When a contract's package matches the provided regular expression
then extending class will be the one provided in the map - in this
case <tt>com.example.SomeBaseClass</tt></div>
<ul>
<li><b>Type</b>: <tt>java.util.List</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>User Property</b>: <tt>baseClassMappings</tt></li>
</ul><hr />
<p><b><a name="basePackageForTests">basePackageForTests</a>:</b></p>
<div>(no description)</div>
<ul>
<li><b>Type</b>: <tt>java.lang.String</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
</ul><hr />
<p><b><a name="contractDependency">contractDependency</a>:</b></p>
<div>(no description)</div>
<ul>
<li><b>Type</b>: <tt>org.apache.maven.model.Dependency</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>User Property</b>: <tt>contractDependency</tt></li>
</ul><hr />
<p><b><a name="contractsDirectory">contractsDirectory</a>:</b></p>
<div>(no description)</div>
<ul>
<li><b>Type</b>: <tt>java.io.File</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>User Property</b>: <tt>spring.cloud.contract.verifier.contractsDirectory</tt></li>
<li><b>Default</b>: <tt>${project.basedir}/src/test/resources/contracts</tt></li>
</ul><hr />
<p><b><a name="contractsPath">contractsPath</a>:</b></p>
<div>The path in the JAR with all the contracts where contracts for this
particular service lay. If not provided will be resolved to
<tt>groupid/artifactid</tt>. Example: <br />
<br />
If <tt>groupid</tt> is <tt>com.example</tt> and
<tt>artifactid</tt> is <tt>service</tt> then the resolved
path will be <tt>/com/example/artifactid</tt></div>
<ul>
<li><b>Type</b>: <tt>java.lang.String</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>User Property</b>: <tt>contractsPath</tt></li>
</ul><hr />
<p><b><a name="contractsRepositoryPassword">contractsRepositoryPassword</a>:</b></p>
<div>The password to be used to connect to the repo with contracts.</div>
<ul>
<li><b>Type</b>: <tt>java.lang.String</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>User Property</b>: <tt>contractsRepositoryPassword</tt></li>
</ul><hr />
<p><b><a name="contractsRepositoryProxyHost">contractsRepositoryProxyHost</a>:</b></p>
<div>The proxy host to be used to connect to the repo with contracts.</div>
<ul>
<li><b>Type</b>: <tt>java.lang.String</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>User Property</b>: <tt>contractsRepositoryProxyHost</tt></li>
</ul><hr />
<p><b><a name="contractsRepositoryProxyPort">contractsRepositoryProxyPort</a>:</b></p>
<div>The proxy port to be used to connect to the repo with contracts.</div>
<ul>
<li><b>Type</b>: <tt>java.lang.Integer</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>User Property</b>: <tt>contractsRepositoryProxyPort</tt></li>
</ul><hr />
<p><b><a name="contractsRepositoryUrl">contractsRepositoryUrl</a>:</b></p>
<div>The URL from which a JAR containing the contracts should get
downloaded. If not provided but artifactid / coordinates notation
was provided then the current Maven's build repositories will be
taken into consideration</div>
<ul>
<li><b>Type</b>: <tt>java.lang.String</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>User Property</b>: <tt>contractsRepositoryUrl</tt></li>
</ul><hr />
<p><b><a name="contractsRepositoryUsername">contractsRepositoryUsername</a>:</b></p>
<div>The user name to be used to connect to the repo with contracts.</div>
<ul>
<li><b>Type</b>: <tt>java.lang.String</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>User Property</b>: <tt>contractsRepositoryUsername</tt></li>
</ul><hr />
<p><b><a name="contractsWorkOffline">contractsWorkOffline</a>:</b></p>
<div>If <tt>true</tt> then JAR with contracts will be taken from
local maven repository</div>
<ul>
<li><b>Type</b>: <tt>boolean</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>User Property</b>: <tt>contractsWorkOffline</tt></li>
<li><b>Default</b>: <tt>false</tt></li>
</ul><hr />
<p><b><a name="excludedFiles">excludedFiles</a>:</b></p>
<div>Patterns that should not be taken into account for processing</div>
<ul>
<li><b>Type</b>: <tt>java.util.List</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
</ul><hr />
<p><b><a name="generatedTestSourcesDir">generatedTestSourcesDir</a>:</b></p>
<div>(no description)</div>
<ul>
<li><b>Type</b>: <tt>java.io.File</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>Default</b>: <tt>${project.build.directory}/generated-test-sources/contracts</tt></li>
</ul><hr />
<p><b><a name="ignoredFiles">ignoredFiles</a>:</b></p>
<div>Patterns for which Spring Cloud Contract Verifier should generate
@Ignored tests</div>
<ul>
<li><b>Type</b>: <tt>java.util.List</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
</ul><hr />
<p><b><a name="imports">imports</a>:</b></p>
<div>Imports that should be added to generated tests</div>
<ul>
<li><b>Type</b>: <tt>java.lang.String[]</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
</ul><hr />
<p><b><a name="mavenTestSkip">mavenTestSkip</a>:</b></p>
<div>(no description)</div>
<ul>
<li><b>Type</b>: <tt>boolean</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>User Property</b>: <tt>maven.test.skip</tt></li>
<li><b>Default</b>: <tt>false</tt></li>
</ul><hr />
<p><b><a name="nameSuffixForTests">nameSuffixForTests</a>:</b></p>
<div>(no description)</div>
<ul>
<li><b>Type</b>: <tt>java.lang.String</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
</ul><hr />
<p><b><a name="packageWithBaseClasses">packageWithBaseClasses</a>:</b></p>
<div>A package that contains all the base clases for generated tests. If
your contract resides in a location
<tt>src/test/resources/contracts/com/example/v1/</tt> and you
provide the <tt>packageWithBaseClasses</tt> value to
<tt>com.example.contracts.base</tt> then we will search for a
test source file that will have the package
<tt>com.example.contracts.base</tt> and name
<tt>ExampleV1Base</tt>. As you can see it will take the two
last folders to and attach <tt>Base</tt> to its name.</div>
<ul>
<li><b>Type</b>: <tt>java.lang.String</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>User Property</b>: <tt>packageWithBaseClasses</tt></li>
</ul><hr />
<p><b><a name="ruleClassForTests">ruleClassForTests</a>:</b></p>
<div>(no description)</div>
<ul>
<li><b>Type</b>: <tt>java.lang.String</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
</ul><hr />
<p><b><a name="skip">skip</a>:</b></p>
<div>(no description)</div>
<ul>
<li><b>Type</b>: <tt>boolean</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>User Property</b>: <tt>spring.cloud.contract.verifier.skip</tt></li>
<li><b>Default</b>: <tt>false</tt></li>
</ul><hr />
<p><b><a name="skipTests">skipTests</a>:</b></p>
<div>(no description)</div>
<ul>
<li><b>Type</b>: <tt>boolean</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>User Property</b>: <tt>skipTests</tt></li>
<li><b>Default</b>: <tt>false</tt></li>
</ul><hr />
<p><b><a name="staticImports">staticImports</a>:</b></p>
<div>Static imports that should be added to generated tests</div>
<ul>
<li><b>Type</b>: <tt>java.lang.String[]</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
</ul><hr />
<p><b><a name="testFramework">testFramework</a>:</b></p>
<div>(no description)</div>
<ul>
<li><b>Type</b>: <tt>org.springframework.cloud.contract.verifier.config.TestFramework</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>Default</b>: <tt>JUNIT</tt></li>
</ul><hr />
<p><b><a name="testMode">testMode</a>:</b></p>
<div>(no description)</div>
<ul>
<li><b>Type</b>: <tt>org.springframework.cloud.contract.verifier.config.TestMode</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>Default</b>: <tt>MOCKMVC</tt></li>
</ul>
</div>
</div>
</div>
</div>
</div>
<hr/>
<footer>
<div class="container-fluid">
<div class="row-fluid">
<p >Copyright &copy; 2016&#x2013;2019
<a href="https://spring.io/">Spring</a>.
All rights reserved.
</p>
</div>
</div>
</footer>
</body>
</html>

View File

@@ -0,0 +1,428 @@
<!DOCTYPE html>
<!--
| Generated by Apache Maven Doxia Site Renderer 1.6 at 2019-05-23
| Rendered using Apache Maven Fluido Skin 1.5
-->
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="Date-Revision-yyyymmdd" content="20190523" />
<meta http-equiv="Content-Language" content="en" />
<title>Spring Cloud Contract Maven Plugin &#x2013; spring-cloud-contract:help</title>
<link rel="stylesheet" href="./css/apache-maven-fluido-1.5.min.css" />
<link rel="stylesheet" href="./css/site.css" />
<link rel="stylesheet" href="./css/print.css" media="print" />
<script type="text/javascript" src="./js/apache-maven-fluido-1.5.min.js"></script>
</head>
<body class="topBarEnabled">
<a href="https://github.com/spring-cloud/spring-cloud-contract">
<img style="position: absolute; top: 0; right: 0; border: 0; z-index: 10000;"
src="https://s3.amazonaws.com/github/ribbons/forkme_right_orange_ff7600.png"
alt="Fork me on GitHub">
</a>
<div id="topbar" class="navbar navbar-fixed-top ">
<div class="navbar-inner">
<div class="container-fluid">
<a data-target=".nav-collapse" data-toggle="collapse" class="btn btn-navbar">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<ul class="nav">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Overview <b class="caret"></b></a>
<ul class="dropdown-menu">
<li> <a href="index.html" title="Introduction">Introduction</a>
</li>
<li> <a href="usage.html" title="Usage">Usage</a>
</li>
<li> <a href="plugin-info.html" title="Goals">Goals</a>
</li>
<li> <a href="junit.html" title="JUnit Configuration">JUnit Configuration</a>
</li>
<li> <a href="spock.html" title="Spock Configuration">Spock Configuration</a>
</li>
<li> <a href="complex.html" title="Complex Configuration">Complex Configuration</a>
</li>
<li> <a href="configs.html" title="Configuration snippets">Configuration snippets</a>
</li>
</ul>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Related Projects <b class="caret"></b></a>
<ul class="dropdown-menu">
<li> <a href="https://github.com/spring-cloud/spring-cloud-contract" title="Spring Cloud Contract">Spring Cloud Contract</a>
</li>
</ul>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Project Documentation <b class="caret"></b></a>
<ul class="dropdown-menu">
<li class="dropdown-submenu">
<a href="project-info.html" title="Project Information">Project Information</a>
<ul class="dropdown-menu">
<li> <a href="integration.html" title="CI Management">CI Management</a>
</li>
<li> <a href="index.html" title="About">About</a>
</li>
<li> <a href="issue-tracking.html" title="Issue Management">Issue Management</a>
</li>
<li> <a href="license.html" title="Licenses">Licenses</a>
</li>
<li> <a href="plugin-management.html" title="Plugin Management">Plugin Management</a>
</li>
<li> <a href="plugins.html" title="Plugins">Plugins</a>
</li>
<li> <a href="team-list.html" title="Team">Team</a>
</li>
<li> <a href="source-repository.html" title="Source Code Management">Source Code Management</a>
</li>
<li> <a href="project-summary.html" title="Summary">Summary</a>
</li>
</ul>
</li>
<li class="dropdown-submenu">
<a href="project-reports.html" title="Project Reports">Project Reports</a>
<ul class="dropdown-menu">
<li> <a href="checkstyle.html" title="Checkstyle">Checkstyle</a>
</li>
<li> <a href="plugin-info.html" title="Plugin Documentation">Plugin Documentation</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="container-fluid">
<div id="banner">
<div class="pull-left">
<div id="bannerLeft">
<h2>Spring Cloud Contract Maven Plugin</h2>
</div>
</div>
<div class="pull-right"> <div id="bannerRight">
<img src="" />
</div>
</div>
<div class="clear"><hr/></div>
</div>
<div id="breadcrumbs">
<ul class="breadcrumb">
<li id="publishDate">Last Published: 2019-05-23
<span class="divider">|</span>
</li>
<li id="projectVersion">Version: 1.2.7.RELEASE
</li>
</ul>
</div>
<div class="row-fluid">
<div id="leftColumn" class="span2">
<div class="well sidebar-nav">
<ul class="nav nav-list">
<li class="nav-header">Overview</li>
<li>
<a href="index.html" title="Introduction">
<span class="none"></span>
Introduction</a>
</li>
<li>
<a href="usage.html" title="Usage">
<span class="none"></span>
Usage</a>
</li>
<li>
<a href="plugin-info.html" title="Goals">
<span class="none"></span>
Goals</a>
</li>
<li>
<a href="junit.html" title="JUnit Configuration">
<span class="none"></span>
JUnit Configuration</a>
</li>
<li>
<a href="spock.html" title="Spock Configuration">
<span class="none"></span>
Spock Configuration</a>
</li>
<li>
<a href="complex.html" title="Complex Configuration">
<span class="none"></span>
Complex Configuration</a>
</li>
<li>
<a href="configs.html" title="Configuration snippets">
<span class="none"></span>
Configuration snippets</a>
</li>
<li class="nav-header">Related Projects</li>
<li>
<a href="https://github.com/spring-cloud/spring-cloud-contract" title="Spring Cloud Contract">
<span class="none"></span>
Spring Cloud Contract</a>
</li>
<li class="nav-header">Project Documentation</li>
<li>
<a href="project-info.html" title="Project Information">
<span class="icon-chevron-right"></span>
Project Information</a>
</li>
<li>
<a href="project-reports.html" title="Project Reports">
<span class="icon-chevron-right"></span>
Project Reports</a>
</li>
</ul>
<hr />
<div id="poweredBy">
<div class="clear"></div>
<div class="clear"></div>
<div class="clear"></div>
<div class="clear"></div>
<a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy">
<img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" />
</a>
</div>
</div>
</div>
<div id="bodyColumn" class="span10" >
<div class="section">
<h2><a name="spring-cloud-contract:help"></a>spring-cloud-contract:help</h2>
<p><b>Full name</b>:</p>
<p>org.springframework.cloud:spring-cloud-contract-maven-plugin:1.2.7.RELEASE:help</p>
<p><b>Description</b>:</p>
<div>Display help information on
spring-cloud-contract-maven-plugin.<br />
Call <tt>mvn spring-cloud-contract:help -Ddetail=true
-Dgoal=&lt;goal-name&gt;</tt> to display parameter details.</div>
<p><b>Attributes</b>:</p>
<ul>
<li>The goal is thread-safe and supports parallel builds.</li>
</ul>
<div class="section">
<h3><a name="Optional_Parameters"></a>Optional Parameters</h3>
<table class="table table-striped" border="0">
<tr class="a">
<th>Name</th>
<th>Type</th>
<th>Since</th>
<th>Description</th>
</tr>
<tr class="b">
<td><b><a href="#detail">detail</a></b></td>
<td><tt>boolean</tt></td>
<td><tt>-</tt></td>
<td>If <tt>true</tt>, display all settable properties for each
goal.<br /><b>Default value is</b>: <tt>false</tt>.<br /><b>User property is</b>: <tt>detail</tt>.</td>
</tr>
<tr class="a">
<td><b><a href="#goal">goal</a></b></td>
<td><tt>String</tt></td>
<td><tt>-</tt></td>
<td>The name of the goal for which to show help. If unspecified, all
goals will be displayed.<br /><b>User property is</b>: <tt>goal</tt>.</td>
</tr>
<tr class="b">
<td><b><a href="#indentSize">indentSize</a></b></td>
<td><tt>int</tt></td>
<td><tt>-</tt></td>
<td>The number of spaces per indentation level, should be positive.<br /><b>Default value is</b>: <tt>2</tt>.<br /><b>User property is</b>: <tt>indentSize</tt>.</td>
</tr>
<tr class="a">
<td><b><a href="#lineLength">lineLength</a></b></td>
<td><tt>int</tt></td>
<td><tt>-</tt></td>
<td>The maximum length of a display line, should be positive.<br /><b>Default value is</b>: <tt>80</tt>.<br /><b>User property is</b>: <tt>lineLength</tt>.</td>
</tr>
</table>
</div>
<div class="section">
<h3><a name="Parameter_Details"></a>Parameter Details</h3>
<p><b><a name="detail">detail</a>:</b></p>
<div>If <tt>true</tt>, display all settable properties for each
goal.</div>
<ul>
<li><b>Type</b>: <tt>boolean</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>User Property</b>: <tt>detail</tt></li>
<li><b>Default</b>: <tt>false</tt></li>
</ul><hr />
<p><b><a name="goal">goal</a>:</b></p>
<div>The name of the goal for which to show help. If unspecified, all
goals will be displayed.</div>
<ul>
<li><b>Type</b>: <tt>java.lang.String</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>User Property</b>: <tt>goal</tt></li>
</ul><hr />
<p><b><a name="indentSize">indentSize</a>:</b></p>
<div>The number of spaces per indentation level, should be positive.</div>
<ul>
<li><b>Type</b>: <tt>int</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>User Property</b>: <tt>indentSize</tt></li>
<li><b>Default</b>: <tt>2</tt></li>
</ul><hr />
<p><b><a name="lineLength">lineLength</a>:</b></p>
<div>The maximum length of a display line, should be positive.</div>
<ul>
<li><b>Type</b>: <tt>int</tt></li>
<li><b>Required</b>: <tt>No</tt></li>
<li><b>User Property</b>: <tt>lineLength</tt></li>
<li><b>Default</b>: <tt>80</tt></li>
</ul>
</div>
</div>
</div>
</div>
</div>
<hr/>
<footer>
<div class="container-fluid">
<div class="row-fluid">
<p >Copyright &copy; 2016&#x2013;2019
<a href="https://spring.io/">Spring</a>.
All rights reserved.
</p>
</div>
</div>
</footer>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 746 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 397 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 923 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 736 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 577 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 700 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 366 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 633 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 638 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 604 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 625 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 662 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1017 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 536 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 717 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

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