Sync docs from master to gh-pages

This commit is contained in:
buildmaster
2017-10-25 15:44:34 +00:00
parent 638c7bddf9
commit ca473fa4ea
15 changed files with 272 additions and 1027 deletions

View File

@@ -844,463 +844,6 @@ constant development.</simpara>
<link xl:href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples">samples</link>.</simpara>
</section>
</chapter>
<chapter xml:id="_spring_cloud_contract_faq">
<title>Spring Cloud Contract FAQ</title>
<section xml:id="_why_use_spring_cloud_contract_verifier_and_not_x">
<title>Why use Spring Cloud Contract Verifier and not X ?</title>
<simpara>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:</simpara>
<itemizedlist>
<listitem>
<simpara>Possibility to do CDC with messaging</simpara>
</listitem>
<listitem>
<simpara>Clear and easy to use, statically typed DSL</simpara>
</listitem>
<listitem>
<simpara>Possibility to copy paste your current JSON file to the contract and only edit its elements</simpara>
</listitem>
<listitem>
<simpara>Automatic generation of tests from the defined Contract</simpara>
</listitem>
<listitem>
<simpara>Stub Runner functionality - the stubs are automatically downloaded at runtime from Nexus / Artifactory</simpara>
</listitem>
<listitem>
<simpara>Spring Cloud integration - no discovery service is needed for integration tests</simpara>
</listitem>
</itemizedlist>
</section>
<section xml:id="_what_is_this_value_consumer_producer">
<title>What is this value(consumer(), producer()) ?</title>
<simpara>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</simpara>
<programlisting language="json" linenumbering="unnumbered">{
"time" : "2016-10-10 20:10:15",
"id" : "9febab1c-6f36-4a0b-88d6-3b6a6d81cd4a",
"body" : "foo"
}</programlisting>
<simpara>and JSON response</simpara>
<programlisting language="json" linenumbering="unnumbered">{
"time" : "2016-10-10 21:10:15",
"id" : "c4231e1f-3ca9-48d3-b7e7-567d55f0d051",
"body" : "bar"
}</programlisting>
<simpara>Imagine the pain required to set proper value of the <literal>time</literal> 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 <literal>id</literal>. Will you create a stubbed implementation of UUID generator? Makes little sense&#8230;&#8203;</simpara>
<simpara>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 <literal>body</literal> field. You can focus on that and provide matching for other fields. In other words
you would like the stub to work like this:</simpara>
<programlisting language="json" linenumbering="unnumbered">{
"time" : "SOMETHING THAT MATCHES TIME",
"id" : "SOMETHING THAT MATCHES UUID",
"body" : "foo"
}</programlisting>
<simpara>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</simpara>
<programlisting language="json" linenumbering="unnumbered">{
"time" : "2016-10-10 21:10:15",
"id" : "c4231e1f-3ca9-48d3-b7e7-567d55f0d051",
"body" : "bar"
}</programlisting>
<simpara>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:</simpara>
<programlisting language="json" linenumbering="unnumbered">{
"time" : "2016-10-10 20:10:15",
"id" : "9febab1c-6f36-4a0b-88d6-3b6a6d81cd4a",
"body" : "foo"
}</programlisting>
<simpara>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 <literal>time</literal> or <literal>id</literal>. 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:</simpara>
<programlisting language="json" linenumbering="unnumbered">{
"time" : "SOMETHING THAT MATCHES TIME",
"id" : "SOMETHING THAT MATCHES UUID",
"body" : "bar"
}</programlisting>
<simpara>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 <emphasis role="strong">dynamic value</emphasis>. That means that it can differ for both
sides of the communication. You can pass the values:</simpara>
<simpara>Either via the <literal>value</literal> method</simpara>
<programlisting language="groovy" linenumbering="unnumbered">value(consumer(...), producer(...))
value(stub(...), test(...))
value(client(...), server(...))</programlisting>
<simpara>or using the <literal>$()</literal> method</simpara>
<programlisting language="groovy" linenumbering="unnumbered">$(consumer(...), producer(...))
$(stub(...), test(...))
$(client(...), server(...))</programlisting>
<simpara>You can read more about this in the <link xl:href="https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html#_contract_dsl">Contract DSL section</link>.</simpara>
<simpara>Calling <literal>value()</literal> or <literal>$()</literal> tells Spring Cloud Contract that you will be passing a dynamic value.
Inside the <literal>consumer()</literal> method you pass the value that should be used on the consumer side (in the generated stub).
Inside the <literal>producer()</literal> method you pass the value that should be used on the producer side (in the generated test).</simpara>
<tip>
<simpara>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.</simpara>
</tip>
<simpara>Most often you will use that method together with the <literal>regex</literal> helper method. E.g. <literal>consumer(regex('[0-9]{10}'))</literal>.</simpara>
<simpara>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):</simpara>
<programlisting language="groovy" linenumbering="unnumbered">org.springframework.cloud.contract.spec.Contract.make {
request {
method 'GET'
url '/someUrl'
body([
time : value(consumer(regex('[0-9]{4}-[0-9]{2}-[0-9]{2} [0-2][0-9]-[0-5][0-9]-[0-5][0-9]')),
id: value(consumer(regex('[0-9a-zA-z]{8}-[0-9a-zA-z]{4}-[0-9a-zA-z]{4}-[0-9a-zA-z]{12}'))
body: "foo"
])
}
response {
status 200
body([
time : value(producer(regex('[0-9]{4}-[0-9]{2}-[0-9]{2} [0-2][0-9]-[0-5][0-9]-[0-5][0-9]')),
id: value([producer(regex('[0-9a-zA-z]{8}-[0-9a-zA-z]{4}-[0-9a-zA-z]{4}-[0-9a-zA-z]{12}'))
body: "bar"
])
}
}</programlisting>
<important>
<simpara>Please read the <link xl:href="http://groovy-lang.org/json.html">Groovy docs related to JSON</link> to understand how to
properly structure the request / response bodies.</simpara>
</important>
</section>
<section xml:id="_how_to_do_stubs_versioning">
<title>How to do Stubs versioning?</title>
<section xml:id="_api_versioning">
<title>API Versioning</title>
<simpara>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.</simpara>
<itemizedlist>
<listitem>
<simpara>use Hypermedia, links and do not version your API by any means</simpara>
</listitem>
<listitem>
<simpara>pass versions through headers / urls</simpara>
</listitem>
</itemizedlist>
<simpara>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.</simpara>
<simpara>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.</simpara>
</section>
<section xml:id="_jar_versioning">
<title>JAR versioning</title>
<simpara>If by versioning you mean the version of the JAR that contains the stubs then there are essentially two main approaches.</simpara>
<simpara>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) :</simpara>
<programlisting language="groovy" linenumbering="unnumbered">1.0.0.20161020-201521-RELEASE</programlisting>
<simpara>In that case your generated stub jar will look like this.</simpara>
<programlisting language="groovy" linenumbering="unnumbered">1.0.0.20161020-201521-RELEASE-stubs.jar</programlisting>
<simpara>In this case you should inside your <literal>application.yml</literal> or <literal>@AutoConfigureStubRunner</literal> when referencing stubs provide the
latest version of the stubs. You can do that by passing the <literal>+</literal> sign. Example</simpara>
<programlisting language="java" linenumbering="unnumbered">@AutoConfigureStubRunner(ids = {"com.example:http-server-dsl:+:stubs:8080"})</programlisting>
<simpara>If the versioning however is fixed (e.g. <literal>1.0.4.RELEASE</literal> or <literal>2.1.1</literal>) then you have to set the concrete value of the jar
version. Example for 2.1.1.</simpara>
<programlisting language="java" linenumbering="unnumbered">@AutoConfigureStubRunner(ids = {"com.example:http-server-dsl:2.1.1:stubs:8080"})</programlisting>
</section>
<section xml:id="_dev_or_prod_stubs">
<title>Dev or prod stubs</title>
<simpara>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 <literal>prod-stubs</literal> classifier
once you reach production deployment then you can run tests in one case with dev stubs and one with prod stubs.</simpara>
<simpara>Example of tests using development version of stubs</simpara>
<programlisting language="java" linenumbering="unnumbered">@AutoConfigureStubRunner(ids = {"com.example:http-server-dsl:+:stubs:8080"})</programlisting>
<simpara>Example of tests using production version of stubs</simpara>
<programlisting language="java" linenumbering="unnumbered">@AutoConfigureStubRunner(ids = {"com.example:http-server-dsl:+:prod-stubs:8080"})</programlisting>
<simpara>You can pass those values also via properties from your deployment pipeline.</simpara>
</section>
</section>
<section xml:id="_common_repo_with_contracts">
<title>Common repo with contracts</title>
<simpara>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.</simpara>
<section xml:id="_repo_structure">
<title>Repo structure</title>
<simpara>Let&#8217;s assume that we have a producer with coordinates <literal>com.example:server</literal> and 3 consumers: <literal>client1</literal>,
<literal>client2</literal>, <literal>client3</literal>. Then in the repository with common contracts you would have the following setup
(which you can checkout <link xl:href="https://github.com/spring-cloud/spring-cloud-contract/tree/1.0.x/samples/standalone/contracts">here</link>:</simpara>
<programlisting language="bash" linenumbering="unnumbered">├── com
│   └── example
│   └── server
│   ├── client1
│   │   └── expectation.groovy
│   ├── client2
│   │   └── expectation.groovy
│   ├── client3
│   │   └── expectation.groovy
│   └── pom.xml
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
└── assembly
└── contracts.xml</programlisting>
<simpara>As you can see the under the slash-delimited groupid <literal>/</literal> artifact id folder (<literal>com/example/server</literal>) you have
expectations of the 3 consumers (<literal>client1</literal>, <literal>client2</literal> and <literal>client3</literal>). 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.</simpara>
<simpara>Example of a <literal>pom.xml</literal> inside the <literal>server</literal> folder.</simpara>
<programlisting language="xml" linenumbering="unnumbered">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"&gt;
&lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
&lt;groupId&gt;com.example&lt;/groupId&gt;
&lt;artifactId&gt;server&lt;/artifactId&gt;
&lt;version&gt;0.0.1-SNAPSHOT&lt;/version&gt;
&lt;name&gt;Server Stubs&lt;/name&gt;
&lt;description&gt;POM used to install locally stubs for consumer side&lt;/description&gt;
&lt;parent&gt;
&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
&lt;artifactId&gt;spring-boot-starter-parent&lt;/artifactId&gt;
&lt;version&gt;1.5.4.RELEASE&lt;/version&gt;
&lt;relativePath /&gt;
&lt;/parent&gt;
&lt;properties&gt;
&lt;project.build.sourceEncoding&gt;UTF-8&lt;/project.build.sourceEncoding&gt;
&lt;java.version&gt;1.8&lt;/java.version&gt;
&lt;spring-cloud-contract.version&gt;1.2.0.BUILD-SNAPSHOT&lt;/spring-cloud-contract.version&gt;
&lt;spring-cloud-dependencies.version&gt;Edgware.BUILD-SNAPSHOT&lt;/spring-cloud-dependencies.version&gt;
&lt;excludeBuildFolders&gt;true&lt;/excludeBuildFolders&gt;
&lt;/properties&gt;
&lt;dependencyManagement&gt;
&lt;dependencies&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
&lt;artifactId&gt;spring-cloud-dependencies&lt;/artifactId&gt;
&lt;version&gt;${spring-cloud-dependencies.version}&lt;/version&gt;
&lt;type&gt;pom&lt;/type&gt;
&lt;scope&gt;import&lt;/scope&gt;
&lt;/dependency&gt;
&lt;/dependencies&gt;
&lt;/dependencyManagement&gt;
&lt;build&gt;
&lt;plugins&gt;
&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;!-- By default it would search under src/test/resources/ --&gt;
&lt;contractsDirectory&gt;${project.basedir}&lt;/contractsDirectory&gt;
&lt;/configuration&gt;
&lt;/plugin&gt;
&lt;/plugins&gt;
&lt;/build&gt;
&lt;repositories&gt;
&lt;repository&gt;
&lt;id&gt;spring-snapshots&lt;/id&gt;
&lt;name&gt;Spring Snapshots&lt;/name&gt;
&lt;url&gt;https://repo.spring.io/snapshot&lt;/url&gt;
&lt;snapshots&gt;
&lt;enabled&gt;true&lt;/enabled&gt;
&lt;/snapshots&gt;
&lt;/repository&gt;
&lt;repository&gt;
&lt;id&gt;spring-milestones&lt;/id&gt;
&lt;name&gt;Spring Milestones&lt;/name&gt;
&lt;url&gt;https://repo.spring.io/milestone&lt;/url&gt;
&lt;snapshots&gt;
&lt;enabled&gt;false&lt;/enabled&gt;
&lt;/snapshots&gt;
&lt;/repository&gt;
&lt;repository&gt;
&lt;id&gt;spring-releases&lt;/id&gt;
&lt;name&gt;Spring Releases&lt;/name&gt;
&lt;url&gt;https://repo.spring.io/release&lt;/url&gt;
&lt;snapshots&gt;
&lt;enabled&gt;false&lt;/enabled&gt;
&lt;/snapshots&gt;
&lt;/repository&gt;
&lt;/repositories&gt;
&lt;pluginRepositories&gt;
&lt;pluginRepository&gt;
&lt;id&gt;spring-snapshots&lt;/id&gt;
&lt;name&gt;Spring Snapshots&lt;/name&gt;
&lt;url&gt;https://repo.spring.io/snapshot&lt;/url&gt;
&lt;snapshots&gt;
&lt;enabled&gt;true&lt;/enabled&gt;
&lt;/snapshots&gt;
&lt;/pluginRepository&gt;
&lt;pluginRepository&gt;
&lt;id&gt;spring-milestones&lt;/id&gt;
&lt;name&gt;Spring Milestones&lt;/name&gt;
&lt;url&gt;https://repo.spring.io/milestone&lt;/url&gt;
&lt;snapshots&gt;
&lt;enabled&gt;false&lt;/enabled&gt;
&lt;/snapshots&gt;
&lt;/pluginRepository&gt;
&lt;pluginRepository&gt;
&lt;id&gt;spring-releases&lt;/id&gt;
&lt;name&gt;Spring Releases&lt;/name&gt;
&lt;url&gt;https://repo.spring.io/release&lt;/url&gt;
&lt;snapshots&gt;
&lt;enabled&gt;false&lt;/enabled&gt;
&lt;/snapshots&gt;
&lt;/pluginRepository&gt;
&lt;/pluginRepositories&gt;
&lt;/project&gt;</programlisting>
<simpara>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 <literal>mvn clean install -DskipTests</literal> to locally install
stubs of the producer project.</simpara>
<simpara>The <literal>pom.xml</literal> in the root folder can look like this:</simpara>
<programlisting language="xml" linenumbering="unnumbered">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"&gt;
&lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
&lt;groupId&gt;com.example.standalone&lt;/groupId&gt;
&lt;artifactId&gt;contracts&lt;/artifactId&gt;
&lt;version&gt;0.0.1-SNAPSHOT&lt;/version&gt;
&lt;name&gt;Contracts&lt;/name&gt;
&lt;description&gt;Contains all the Spring Cloud Contracts, well, contracts. JAR used by the producers to generate tests and stubs&lt;/description&gt;
&lt;properties&gt;
&lt;project.build.sourceEncoding&gt;UTF-8&lt;/project.build.sourceEncoding&gt;
&lt;/properties&gt;
&lt;build&gt;
&lt;plugins&gt;
&lt;plugin&gt;
&lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
&lt;artifactId&gt;maven-assembly-plugin&lt;/artifactId&gt;
&lt;executions&gt;
&lt;execution&gt;
&lt;id&gt;contracts&lt;/id&gt;
&lt;phase&gt;prepare-package&lt;/phase&gt;
&lt;goals&gt;
&lt;goal&gt;single&lt;/goal&gt;
&lt;/goals&gt;
&lt;configuration&gt;
&lt;attach&gt;true&lt;/attach&gt;
&lt;descriptor&gt;${basedir}/src/assembly/contracts.xml&lt;/descriptor&gt;
&lt;!-- If you want an explicit classifier remove the following line --&gt;
&lt;appendAssemblyId&gt;false&lt;/appendAssemblyId&gt;
&lt;/configuration&gt;
&lt;/execution&gt;
&lt;/executions&gt;
&lt;/plugin&gt;
&lt;/plugins&gt;
&lt;/build&gt;
&lt;/project&gt;</programlisting>
<simpara>It&#8217;s using the assembly plugin in order to build the JAR with all the contracts. Example of such setup is here:</simpara>
<programlisting language="xml" linenumbering="unnumbered">&lt;assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd"&gt;
&lt;id&gt;project&lt;/id&gt;
&lt;formats&gt;
&lt;format&gt;jar&lt;/format&gt;
&lt;/formats&gt;
&lt;includeBaseDirectory&gt;false&lt;/includeBaseDirectory&gt;
&lt;fileSets&gt;
&lt;fileSet&gt;
&lt;directory&gt;${project.basedir}&lt;/directory&gt;
&lt;outputDirectory&gt;/&lt;/outputDirectory&gt;
&lt;useDefaultExcludes&gt;true&lt;/useDefaultExcludes&gt;
&lt;excludes&gt;
&lt;exclude&gt;**/${project.build.directory}/**&lt;/exclude&gt;
&lt;exclude&gt;mvnw&lt;/exclude&gt;
&lt;exclude&gt;mvnw.cmd&lt;/exclude&gt;
&lt;exclude&gt;.mvn/**&lt;/exclude&gt;
&lt;exclude&gt;src/**&lt;/exclude&gt;
&lt;/excludes&gt;
&lt;/fileSet&gt;
&lt;/fileSets&gt;
&lt;/assembly&gt;</programlisting>
</section>
<section xml:id="_workflow">
<title>Workflow</title>
<simpara>The workflow would look similar to the one presented in the <literal>Step by step guide to CDC</literal>. 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.</simpara>
</section>
<section xml:id="_consumer">
<title>Consumer</title>
<simpara>When the <emphasis role="strong">consumer</emphasis> 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. <literal>com/example/server</literal>)
and runs <literal>mvn clean install -DskipTests</literal> to install locally the stubs converted from the contracts.</simpara>
<tip>
<simpara>You need to have <link xl:href="http://maven.apache.org/download.cgi">Maven installed locally</link></simpara>
</tip>
</section>
<section xml:id="_producer">
<title>Producer</title>
<simpara>As a <emphasis role="strong">producer</emphasis> it&#8217;s enough to alter the Spring Cloud Contract Verifier to provide the URL and the dependency
of the JAR containing the contracts:</simpara>
<programlisting language="xml" linenumbering="unnumbered">&lt;plugin&gt;
&lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
&lt;artifactId&gt;spring-cloud-contract-maven-plugin&lt;/artifactId&gt;
&lt;configuration&gt;
&lt;contractsRepositoryUrl&gt;http://link/to/your/nexus/or/artifactory/or/sth&lt;/contractsRepositoryUrl&gt;
&lt;contractDependency&gt;
&lt;groupId&gt;com.example.standalone&lt;/groupId&gt;
&lt;artifactId&gt;contracts&lt;/artifactId&gt;
&lt;/contractDependency&gt;
&lt;/configuration&gt;
&lt;/plugin&gt;</programlisting>
<simpara>With this setup the JAR with groupid <literal>com.example.standalone</literal> and artifactid <literal>contracts</literal> will be downloaded
from <literal><link xl:href="http://link/to/your/nexus/or/artifactory/or/sth">http://link/to/your/nexus/or/artifactory/or/sth</link></literal>. It will be then unpacked in a local temporary folder
and contracts present under the <literal>com/example/server</literal> 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.</simpara>
<simpara>The rest of the flow looks the same.</simpara>
</section>
</section>
<section xml:id="_can_i_have_multiple_base_classes_for_tests">
<title>Can I have multiple base classes for tests?</title>
<simpara>Yes! Check out the <link xl:href="https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html#_different_base_classes_for_contracts">Different base classes for contracts</link> sections
of either Gradle or Maven plugins.</simpara>
</section>
<section xml:id="_how_can_i_debug_the_request_response_being_sent_by_the_generated_tests_client">
<title>How can I debug the request/response being sent by the generated tests client?</title>
<simpara>The generated tests all boil down to RestAssured in some form or fashion which relies on <link xl:href="https://hc.apache.org/httpcomponents-client-ga/">Apache HttpClient</link>. HttpClient has a facility called <link xl:href="https://hc.apache.org/httpcomponents-client-ga/logging.html#Wire_Logging">wire logging</link> which logs the entire request and response to HttpClient. Spring Boot has a logging <link xl:href="https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html">common application property</link> for doing this sort of thing, just add this to your application properties</simpara>
<programlisting language="properties" linenumbering="unnumbered">logging.level.org.apache.http.wire=DEBUG</programlisting>
<section xml:id="_how_can_i_debug_the_mapping_request_response_being_sent_by_wiremock">
<title>How can I debug the mapping/request/response being sent by WireMock?</title>
<simpara>Starting from version <literal>1.2.0</literal> 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.</simpara>
<simpara>To turn off this feature just bump WireMock logging to <literal>ERROR</literal></simpara>
<programlisting language="properties" linenumbering="unnumbered">logging.level.com.github.tomakehurst.wiremock=ERROR</programlisting>
</section>
<section xml:id="_how_can_i_see_what_got_registered_in_the_http_server_stub">
<title>How can I see what got registered in the HTTP server stub?</title>
<simpara>You can use the <literal>mappingsOutputFolder</literal> property on <literal>@AutoConfigureStubRunner</literal> or <literal>StubRunnerRule</literal>
to dump all mappings per artifact id. Also the port at which the given stub server was
started will be attached.</simpara>
</section>
<section xml:id="_can_i_reference_the_request_from_the_response">
<title>Can I reference the request from the response?</title>
<simpara>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.</simpara>
</section>
<section xml:id="_can_i_reference_text_from_file">
<title>Can I reference text from file?</title>
<simpara>Yes! With version 1.2.0 we&#8217;ve added such a possibility. It&#8217;s enough to call <literal>file(&#8230;&#8203;)</literal> method in the
DSL and provide a path relative to where the contract lays.</simpara>
</section>
</section>
</chapter>
<chapter xml:id="_spring_cloud_contract_verifier_setup">
<title>Spring Cloud Contract Verifier Setup</title>
<simpara>You can set up Spring Cloud Contract Verifier in either of two ways</simpara>