702 lines
103 KiB
HTML
702 lines
103 KiB
HTML
<html><head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
|
<title>3. Spring Cloud Contract FAQ</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.79.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. Spring Cloud Contract Verifier Introduction"><link rel="next" href="multi__spring_cloud_contract_verifier_setup.html" title="4. 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. 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> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <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. 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 Why use Spring Cloud Contract Verifier and not X ?</h2></div></div></div><p>For the time being Spring Cloud Contract is a JVM based tool. So it could be your first pick when you’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><li class="listitem">Spring Cloud Contract integrates with Pact out of the box and provides easy hooks to extend its functionality</li><li class="listitem">Via Docker adds support for any language & framework used</li></ul></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_i_dont_want_to_write_a_contract_in_groovy" href="#_i_dont_want_to_write_a_contract_in_groovy"></a>3.2 I don’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_valueconsumer_producer" href="#_what_is_this_valueconsumer_producer"></a>3.3 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’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…​</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’t have to stub anything out. Let’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’s side the situation looks
|
|
much different. We’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’t have any sort of matching. We need concrete values that the
|
|
producer’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’t necessarily have to
|
|
contain concrete values of <code class="literal">time</code> or <code class="literal">id</code>. Let’s say that you generate those on the producer side - again, you’d
|
|
have to do a lot of stubbing to ensure that you always return the same values. That’s why from the producer’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’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="xref" href="multi_contract-dsl.html" title="8. Contract DSL">Chapter 8, <i>Contract DSL</i></a> section.</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’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 OK()
|
|
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 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 API Versioning</h3></div></div></div><p>Let’s try to answer a question what versioning really means. If you’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 suits your needs and allows you to generate
|
|
business value should be picked.</p><p>Let’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 the 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 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’s assume that you’re doing Continuous Delivery / Deployment which means that you’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 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 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’t clone the producer’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 you will 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 Repo structure</h3></div></div></div><p>Let’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/2.1.x/samples/standalone/contracts" target="_top">here</a>):</p><pre class="programlisting">├── com
|
|
│ └── example
|
|
│ └── server
|
|
│ ├── client1
|
|
│ │ └── expectation.groovy
|
|
│ ├── client2
|
|
│ │ └── expectation.groovy
|
|
│ ├── client3
|
|
│ │ └── expectation.groovy
|
|
│ └── pom.xml
|
|
├── mvnw
|
|
├── mvnw.cmd
|
|
├── pom.xml
|
|
└── src
|
|
└── assembly
|
|
└── contracts.xml</pre><p>As you can see 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/"><?xml version="1.0" encoding="UTF-8"?></xslthl:directive>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><project</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</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">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">></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><modelVersion></span>4.0.0<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></modelVersion></span>
|
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>com.example<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>server<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>0.0.1-SNAPSHOT<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><name></span>Server Stubs<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></name></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><description></span>POM used to install locally stubs for consumer side<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></description></span>
|
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><parent></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.boot<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-boot-starter-parent<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>2.1.3.RELEASE<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><relativePath/></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></parent></span>
|
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><properties></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><project.build.sourceEncoding></span>UTF-8<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></project.build.sourceEncoding></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><java.version></span>1.8<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></java.version></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><spring-cloud-contract.version></span>2.1.2.BUILD-SNAPSHOT<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></spring-cloud-contract.version></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><spring-cloud-release.version></span>Greenwich.BUILD-SNAPSHOT
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></spring-cloud-release.version></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><excludeBuildFolders></span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></excludeBuildFolders></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></properties></span>
|
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependencyManagement></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependencies></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-dependencies<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>${spring-cloud-release.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><type></span>pom<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></type></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><scope></span>import<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></scope></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependencies></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependencyManagement></span>
|
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><build></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><plugins></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><plugin></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-contract-maven-plugin<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>${spring-cloud-contract.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><extensions></span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></extensions></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><configuration></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!-- By default it would search under src/test/resources/ --></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><contractsDirectory></span>${project.basedir}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></contractsDirectory></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></configuration></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></plugin></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></plugins></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></build></span>
|
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><repositories></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><repository></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><id></span>spring-snapshots<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></id></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><name></span>Spring Snapshots<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></name></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><url></span>https://repo.spring.io/snapshot<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></url></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><snapshots></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><enabled></span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></enabled></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></snapshots></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></repository></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><repository></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><id></span>spring-milestones<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></id></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><name></span>Spring Milestones<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></name></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><url></span>https://repo.spring.io/milestone<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></url></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><snapshots></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><enabled></span>false<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></enabled></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></snapshots></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></repository></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><repository></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><id></span>spring-releases<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></id></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><name></span>Spring Releases<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></name></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><url></span>https://repo.spring.io/release<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></url></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><snapshots></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><enabled></span>false<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></enabled></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></snapshots></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></repository></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></repositories></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><pluginRepositories></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><pluginRepository></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><id></span>spring-snapshots<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></id></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><name></span>Spring Snapshots<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></name></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><url></span>https://repo.spring.io/snapshot<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></url></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><snapshots></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><enabled></span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></enabled></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></snapshots></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></pluginRepository></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><pluginRepository></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><id></span>spring-milestones<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></id></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><name></span>Spring Milestones<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></name></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><url></span>https://repo.spring.io/milestone<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></url></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><snapshots></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><enabled></span>false<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></enabled></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></snapshots></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></pluginRepository></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><pluginRepository></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><id></span>spring-releases<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></id></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><name></span>Spring Releases<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></name></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><url></span>https://repo.spring.io/release<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></url></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><snapshots></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><enabled></span>false<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></enabled></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></snapshots></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></pluginRepository></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></pluginRepositories></span>
|
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></project></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/"><?xml version="1.0" encoding="UTF-8"?></xslthl:directive>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><project</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</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">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">></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><modelVersion></span>4.0.0<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></modelVersion></span>
|
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>com.example.standalone<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>contracts<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>0.0.1-SNAPSHOT<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><name></span>Contracts<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></name></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><description></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"></description></span>
|
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><properties></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><project.build.sourceEncoding></span>UTF-8<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></project.build.sourceEncoding></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></properties></span>
|
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><build></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><plugins></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><plugin></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.apache.maven.plugins<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>maven-assembly-plugin<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><executions></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><execution></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><id></span>contracts<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></id></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><phase></span>prepare-package<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></phase></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><goals></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><goal></span>single<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></goal></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></goals></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><configuration></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><attach></span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></attach></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><descriptor></span>${basedir}/src/assembly/contracts.xml<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></descriptor></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!-- If you want an explicit classifier remove the following line --></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><appendAssemblyId></span>false<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></appendAssemblyId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></configuration></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></execution></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></executions></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></plugin></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></plugins></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></build></span>
|
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></project></span></pre><p>It’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"><assembly</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</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">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">></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><id></span>project<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></id></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><formats></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><format></span>jar<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></format></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></formats></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><includeBaseDirectory></span>false<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></includeBaseDirectory></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><fileSets></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><fileSet></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><directory></span>${project.basedir}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></directory></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><outputDirectory></span>/<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></outputDirectory></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><useDefaultExcludes></span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></useDefaultExcludes></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><excludes></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><exclude></span>**/${project.build.directory}/**<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></exclude></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><exclude></span>mvnw<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></exclude></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><exclude></span>mvnw.cmd<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></exclude></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><exclude></span>.mvn/**<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></exclude></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><exclude></span>src/**<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></exclude></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></excludes></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></fileSet></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></fileSets></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></assembly></span></pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_workflow" href="#_workflow"></a>3.5.2 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’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 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’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 Producer</h3></div></div></div><p>As a <span class="strong"><strong>producer</strong></span> it’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"><plugin></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-contract-maven-plugin<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><configuration></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><contractsMode></span>REMOTE<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></contractsMode></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><contractsRepositoryUrl></span>
|
|
https://link/to/your/nexus/or/artifactory/or/sth
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></contractsRepositoryUrl></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><contractDependency></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>com.example.standalone<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>contracts<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></contractDependency></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></configuration></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></plugin></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 class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_how_can_i_define_messaging_contracts_per_topic_not_per_producer" href="#_how_can_i_define_messaging_contracts_per_topic_not_per_producer"></a>3.5.5 How can I define messaging contracts per topic not per producer?</h3></div></div></div><p>To avoid messaging contracts duplication in the common repo, when few producers writing messages to one topic,
|
|
we could create the structure when the rest contracts would be placed in a folder per producer and messaging
|
|
contracts in the folder per topic.</p><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_for_maven_project" href="#_for_maven_project"></a>For Maven Project</h4></div></div></div><p>To make it possible to work on the producer side we should specify an inclusion pattern for
|
|
filtering common repository jar by messaging topics we are interested in. <code class="literal"><code class="literal">includedFiles</code></code> property of <code class="literal"><code class="literal">Maven Spring Cloud Contract plugin</code></code>
|
|
allows us to do that. Also <code class="literal"><code class="literal">contractsPath</code></code> need to be specified since the default path would be the common repository <code class="literal"><code class="literal">groupid/artifactid</code></code>.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><plugin></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-contract-maven-plugin<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>${spring-cloud-contract.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><configuration></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><contractsMode></span>REMOTE<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></contractsMode></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><contractsRepositoryUrl></span>http://link/to/your/nexus/or/artifactory/or/sth<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></contractsRepositoryUrl></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><contractDependency></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>com.example<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>common-repo-with-contracts<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>+<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></contractDependency></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><contractsPath></span>/<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></contractsPath></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><baseClassMappings></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><baseClassMapping></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><contractPackageRegex></span>.*messaging.*<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></contractPackageRegex></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><baseClassFQN></span>com.example.services.MessagingBase<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></baseClassFQN></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></baseClassMapping></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><baseClassMapping></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><contractPackageRegex></span>.*rest.*<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></contractPackageRegex></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><baseClassFQN></span>com.example.services.TestBase<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></baseClassFQN></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></baseClassMapping></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></baseClassMappings></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><includedFiles></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><includedFile></span>**/${project.artifactId}/**<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></includedFile></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><includedFile></span>**/${first-topic}/**<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></includedFile></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><includedFile></span>**/${second-topic}/**<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></includedFile></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></includedFiles></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></configuration></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></plugin></span></pre></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_for_gradle_project" href="#_for_gradle_project"></a>For Gradle Project</h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Add a custom configuration for the common-repo dependency:</li></ul></div><pre class="programlisting">ext {
|
|
conractsGroupId = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"com.example"</span>
|
|
contractsArtifactId = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"common-repo"</span>
|
|
contractsVersion = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"1.2.3"</span>
|
|
}
|
|
|
|
configurations {
|
|
contracts {
|
|
transitive = false
|
|
}
|
|
}</pre><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Add the common-repo dependency to your classpath:</li></ul></div><pre class="programlisting">dependencies {
|
|
contracts <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"${conractsGroupId}:${contractsArtifactId}:${contractsVersion}"</span>
|
|
testCompile <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"${conractsGroupId}:${contractsArtifactId}:${contractsVersion}"</span>
|
|
}</pre><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Download the dependency to an appropriate folder:</li></ul></div><pre class="programlisting">task getContracts(type: Copy) {
|
|
from configurations.contracts
|
|
into <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> File(project.buildDir, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"downloadedContracts"</span>)
|
|
}</pre><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Unzip JAR:</li></ul></div><pre class="programlisting">task unzipContracts(type: Copy) {
|
|
def zipFile = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> File(project.buildDir, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"downloadedContracts/${contractsArtifactId}-${contractsVersion}.jar"</span>)
|
|
def outputDir = file(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"${buildDir}/unpackedContracts"</span>)
|
|
|
|
from zipTree(zipFile)
|
|
into outputDir
|
|
}</pre><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Cleanup unused contracts:</li></ul></div><pre class="programlisting">task deleteUnwantedContracts(type: Delete) {
|
|
delete fileTree(dir: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"${buildDir}/unpackedContracts"</span>,
|
|
include: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"**/*"</span>,
|
|
excludes: [
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"**/${project.name}/**"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">",
|
|
</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"**/${first-topic}/**"</span>,
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"**/${second-topic}/**"</span>])
|
|
}</pre><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Create task dependencies:</li></ul></div><pre class="programlisting">unzipContracts.dependsOn(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"getContracts"</span>)
|
|
deleteUnwantedContracts.dependsOn(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"unzipContracts"</span>)
|
|
build.dependsOn(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"deleteUnwantedContracts"</span>)</pre><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Configure plugin by specifying the directory containing contracts using <code class="literal">contractsDslDir</code> property</li></ul></div><pre class="programlisting">contracts {
|
|
contractsDslDir = <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">"${buildDir}/unpackedContracts"</span>)
|
|
}</pre></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_do_i_need_a_binary_storage_cant_i_use_git" href="#_do_i_need_a_binary_storage_cant_i_use_git"></a>3.6 Do I need a Binary Storage? Can’t I use Git?</h2></div></div></div><p>In the polyglot world, there are languages that don’t use binary storages like
|
|
Artifactory or Nexus. Starting from Spring Cloud Contract version 2.0.0 we provide
|
|
mechanisms to store contracts and stubs in a SCM repository. Currently the
|
|
only supported SCM is Git.</p><p>The repository would have to the following setup
|
|
(which you can checkout <a class="link" href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/2.1.x/contracts_git/" target="_top">here</a>):</p><pre class="screen">.
|
|
└── META-INF
|
|
└── com.example
|
|
└── beer-api-producer-git
|
|
└── 0.0.1-SNAPSHOT
|
|
├── contracts
|
|
│ └── beer-api-consumer
|
|
│ ├── messaging
|
|
│ │ ├── shouldSendAcceptedVerification.groovy
|
|
│ │ └── shouldSendRejectedVerification.groovy
|
|
│ └── rest
|
|
│ ├── shouldGrantABeerIfOldEnough.groovy
|
|
│ └── shouldRejectABeerIfTooYoung.groovy
|
|
└── mappings
|
|
└── beer-api-consumer
|
|
└── rest
|
|
├── shouldGrantABeerIfOldEnough.json
|
|
└── shouldRejectABeerIfTooYoung.json</pre><p>Under <code class="literal">META-INF</code> folder:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">we group applications via <code class="literal">groupId</code> (e.g. <code class="literal">com.example</code>)</li><li class="listitem">then each application is represented via the <code class="literal">artifactId</code> (e.g. <code class="literal">beer-api-producer-git</code>)</li><li class="listitem"><p class="simpara">next, the version of the application (e.g. <code class="literal">0.0.1-SNAPSHOT</code>). Starting from Spring Cloud Contract version <code class="literal">2.1.0</code>, you can specify the versions as follows (assuming that your versions follow the semantic versioning)</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p class="simpara"><code class="literal">+</code> or <code class="literal">latest</code> - to find the latest version of your stubs (assuming that the snapshots are always the latest artifact for a given revision number). That means:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: square; "><li class="listitem">if you have a version <code class="literal">1.0.0.RELEASE</code>, <code class="literal">2.0.0.BUILD-SNAPSHOT</code> and <code class="literal">2.0.0.RELEASE</code> we will assume that the latest is <code class="literal">2.0.0.BUILD-SNAPSHOT</code></li><li class="listitem">if you have a version <code class="literal">1.0.0.RELEASE</code> and <code class="literal">2.0.0.RELEASE</code> we will assume that the latest is <code class="literal">2.0.0.RELEASE</code></li><li class="listitem">if you have a version called <code class="literal">latest</code> or <code class="literal">+</code> we will pick that folder</li></ul></div></li><li class="listitem"><p class="simpara"><code class="literal">release</code> - to find the latest release version of your stubs. That means:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: square; "><li class="listitem">if you have a version <code class="literal">1.0.0.RELEASE</code>, <code class="literal">2.0.0.BUILD-SNAPSHOT</code> and <code class="literal">2.0.0.RELEASE</code> we will assume that the latest is <code class="literal">2.0.0.RELEASE</code></li><li class="listitem">if you have a version called <code class="literal">release</code> we will pick that folder</li></ul></div></li></ul></div></li><li class="listitem"><p class="simpara">finally, there are two folders:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><code class="literal">contracts</code> - the good practice is to store the contracts required by each
|
|
consumer in the folder with the consumer name (e.g. <code class="literal">beer-api-consumer</code>). That way you
|
|
can use the <code class="literal">stubs-per-consumer</code> feature. Further directory structure is arbitrary.</li><li class="listitem"><code class="literal">mappings</code> - in this folder the Maven / Gradle Spring Cloud Contract plugins will push
|
|
the stub server mappings. On the consumer side, Stub Runner will scan this folder
|
|
to start stub servers with stub definitions. The folder structure will be a copy
|
|
of the one created in the <code class="literal">contracts</code> subfolder.</li></ul></div></li></ul></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_protocol_convention" href="#_protocol_convention"></a>3.6.1 Protocol convention</h3></div></div></div><p>In order to control the type and location of the source of contracts (whether it’s
|
|
a binary storage or an SCM repository), you can use the protocol in the URL of
|
|
the repository. Spring Cloud Contract iterates over registered protocol resolvers
|
|
and tries to fetch the contracts (via a plugin) or stubs (via Stub Runner).</p><p>For the SCM functionality, currently, we support the Git repository. To use it,
|
|
in the property, where the repository URL needs to be placed you just have to prefix
|
|
the connection URL with <code class="literal">git://</code>. Here you can find a couple of examples:</p><pre class="screen">git://file:///foo/bar
|
|
git://https://github.com/spring-cloud-samples/spring-cloud-contract-nodejs-contracts-git.git
|
|
git://git@github.com:spring-cloud-samples/spring-cloud-contract-nodejs-contracts-git.git</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_producer_2" href="#_producer_2"></a>3.6.2 Producer</h3></div></div></div><p>For the producer, to use the SCM approach, we can reuse the
|
|
same mechanism we use for external contracts. We route Spring Cloud Contract
|
|
to use the SCM implementation via the URL that contains
|
|
the <code class="literal">git://</code> protocol.</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>You have to manually add the <code class="literal">pushStubsToScm</code>
|
|
goal in Maven or execute (bind) the <code class="literal">pushStubsToScm</code> task in
|
|
Gradle. We don’t push stubs to <code class="literal">origin</code> of your git
|
|
repository out of the box.</p></td></tr></table></div><p><b>Maven. </b>
|
|
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><plugin></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-contract-maven-plugin<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>${spring-cloud-contract.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><extensions></span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></extensions></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><configuration></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!-- Base class mappings etc. --></span>
|
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!-- We want to pick contracts from a Git repository --></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><contractsRepositoryUrl></span>git://https://github.com/spring-cloud-samples/spring-cloud-contract-nodejs-contracts-git.git<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></contractsRepositoryUrl></span>
|
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!-- We reuse the contract dependency section to set up the path
|
|
to the folder that contains the contract definitions. In our case the
|
|
path will be /groupId/artifactId/version/contracts --></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><contractDependency></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>${project.groupId}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>${project.artifactId}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>${project.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></contractDependency></span>
|
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!-- The contracts mode can't be classpath --></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><contractsMode></span>REMOTE<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></contractsMode></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></configuration></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><executions></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><execution></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><phase></span>package<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></phase></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><goals></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!-- By default we will not push the stubs back to SCM,
|
|
you have to explicitly add it as a goal --></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><goal></span>pushStubsToScm<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></goal></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></goals></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></execution></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></executions></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></plugin></span></pre><p>
|
|
</p><p><b>Gradle. </b>
|
|
</p><pre class="programlisting">contracts {
|
|
// We want to pick contracts from a Git repository
|
|
contractDependency {
|
|
stringNotation = "${project.group}:${project.name}:${project.version}"
|
|
}
|
|
/*
|
|
We reuse the contract dependency section to set up the path
|
|
to the folder that contains the contract definitions. In our case the
|
|
path will be /groupId/artifactId/version/contracts
|
|
*/
|
|
contractRepository {
|
|
repositoryUrl = "git://https://github.com/spring-cloud-samples/spring-cloud-contract-nodejs-contracts-git.git"
|
|
}
|
|
// The mode can't be classpath
|
|
contractsMode = "REMOTE"
|
|
// Base class mappings etc.
|
|
}
|
|
|
|
/*
|
|
In this scenario we want to publish stubs to SCM whenever
|
|
the `publish` task is executed
|
|
*/
|
|
publish.dependsOn("publishStubsToScm")</pre><p>
|
|
</p><p>With such a setup:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Git project will be cloned to a temporary directory</li><li class="listitem">The SCM stub downloader will go to <code class="literal">META-INF/groupId/artifactId/version/contracts</code> folder
|
|
to find contracts. E.g. for <code class="literal">com.example:foo:1.0.0</code> the path would be
|
|
<code class="literal">META-INF/com.example/foo/1.0.0/contracts</code></li><li class="listitem">Tests will be generated from the contracts</li><li class="listitem">Stubs will be created from the contracts</li><li class="listitem">Once the tests pass, the stubs will be committed in the cloned repository</li><li class="listitem">Finally, a push will be done to that repo’s <code class="literal">origin</code></li></ul></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_producer_with_contracts_stored_locally" href="#_producer_with_contracts_stored_locally"></a>3.6.3 Producer with contracts stored locally</h3></div></div></div><p>Another option to use the SCM as the destination for stubs and contracts is to store the contracts locally, with the producer, and only push the contracts and the stubs to SCM. Below, you can find the setup required to achieve this using Maven and Gradle.</p><p><b>Maven. </b>
|
|
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><plugin></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-contract-maven-plugin<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>${spring-cloud-contract.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><extensions></span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></extensions></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!-- In the default configuration, we want to use the contracts stored locally --></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><configuration></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><baseClassMappings></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><baseClassMapping></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><contractPackageRegex></span>.*messaging.*<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></contractPackageRegex></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><baseClassFQN></span>com.example.BeerMessagingBase<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></baseClassFQN></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></baseClassMapping></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><baseClassMapping></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><contractPackageRegex></span>.*rest.*<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></contractPackageRegex></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><baseClassFQN></span>com.example.BeerRestBase<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></baseClassFQN></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></baseClassMapping></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></baseClassMappings></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><basePackageForTests></span>com.example<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></basePackageForTests></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></configuration></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><executions></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><execution></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><phase></span>package<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></phase></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><goals></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!-- By default we will not push the stubs back to SCM,
|
|
you have to explicitly add it as a goal --></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><goal></span>pushStubsToScm<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></goal></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></goals></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><configuration></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!-- We want to pick contracts from a Git repository --></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><contractsRepositoryUrl></span>git://file://${env.ROOT}/target/contract_empty_git/
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></contractsRepositoryUrl></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!-- Example of URL via git protocol --></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!--<contractsRepositoryUrl>git://git@github.com:spring-cloud-samples/spring-cloud-contract-samples.git</contractsRepositoryUrl>--></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!-- Example of URL via http protocol --></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!--<contractsRepositoryUrl>git://https://github.com/spring-cloud-samples/spring-cloud-contract-samples.git</contractsRepositoryUrl>--></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!-- We reuse the contract dependency section to set up the path
|
|
to the folder that contains the contract definitions. In our case the
|
|
path will be /groupId/artifactId/version/contracts --></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><contractDependency></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>${project.groupId}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>${project.artifactId}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>${project.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></contractDependency></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!-- The mode can't be classpath --></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><contractsMode></span>LOCAL<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></contractsMode></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></configuration></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></execution></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></executions></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></plugin></span></pre><p>
|
|
</p><p><b>Gradle. </b>
|
|
</p><pre class="programlisting">contracts {
|
|
// Base package for generated tests
|
|
basePackageForTests = "com.example"
|
|
baseClassMappings {
|
|
baseClassMapping(".*messaging.*", "com.example.BeerMessagingBase")
|
|
baseClassMapping(".*rest.*", "com.example.BeerRestBase")
|
|
}
|
|
}
|
|
|
|
/*
|
|
In this scenario we want to publish stubs to SCM whenever
|
|
the `publish` task is executed
|
|
*/
|
|
publishStubsToScm {
|
|
// We want to modify the default set up of the plugin when publish stubs to scm is called
|
|
customize {
|
|
// We want to pick contracts from a Git repository
|
|
contractDependency {
|
|
stringNotation = "${project.group}:${project.name}:${project.version}"
|
|
}
|
|
/*
|
|
We reuse the contract dependency section to set up the path
|
|
to the folder that contains the contract definitions. In our case the
|
|
path will be /groupId/artifactId/version/contracts
|
|
*/
|
|
contractRepository {
|
|
repositoryUrl = "git://file://${System.getenv("ROOT")}/target/contract_empty_git/"
|
|
}
|
|
// The mode can't be classpath
|
|
contractsMode = "LOCAL"
|
|
}
|
|
}
|
|
|
|
publish.dependsOn("publishStubsToScm")
|
|
publishToMavenLocal.dependsOn("publishStubsToScm")</pre><p>
|
|
</p><p>With such a setup:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Contracts from the default <code class="literal">src/test/resources/contracts</code> directory will be picked</li><li class="listitem">Tests will be generated from the contracts</li><li class="listitem">Stubs will be created from the contracts</li><li class="listitem"><p class="simpara">Once the tests pass</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem">Git project will be cloned to a temporary directory</li><li class="listitem">The stubs and contracts will be committed in the cloned repository</li></ul></div></li><li class="listitem">Finally, a push will be done to that repo’s <code class="literal">origin</code></li></ul></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_keeping_contracts_with_the_producer_and_stubs_in_an_external_repository" href="#_keeping_contracts_with_the_producer_and_stubs_in_an_external_repository"></a>Keeping contracts with the producer and stubs in an external repository</h4></div></div></div><p>It is also possible to keep the contracts in the producer repository, but keep the stubs in an external git repo.
|
|
This is most useful when you want to use the base consumer-producer collaboration flow, but do not have a possibility to
|
|
use an artifact repository for storing the stubs.</p><p>In order to do that, use the usual producer setup, and then add the <code class="literal">pushStubsToScm</code> goal and set
|
|
<code class="literal">contractsRepositoryUrl</code> to the repository where you want to keep the stubs.</p></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_consumer_2" href="#_consumer_2"></a>3.6.4 Consumer</h3></div></div></div><p>On the consumer side when passing the <code class="literal">repositoryRoot</code> parameter,
|
|
either from the <code class="literal">@AutoConfigureStubRunner</code> annotation, the
|
|
JUnit rule, JUnit 5 extension or properties, it’s enough to pass the URL of the
|
|
SCM repository, prefixed with the protocol. For example</p><pre class="programlisting">@AutoConfigureStubRunner(
|
|
stubsMode=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"REMOTE"</span>,
|
|
repositoryRoot=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"git://https://github.com/spring-cloud-samples/spring-cloud-contract-nodejs-contracts-git.git"</span>,
|
|
ids=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"com.example:bookstore:0.0.1.RELEASE"</span>
|
|
)</pre><p>With such a setup:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Git project will be cloned to a temporary directory</li><li class="listitem">The SCM stub downloader will go to <code class="literal">META-INF/groupId/artifactId/version/</code> folder
|
|
to find stub definitions and contracts. E.g. for <code class="literal">com.example:foo:1.0.0</code> the path would be
|
|
<code class="literal">META-INF/com.example/foo/1.0.0/</code></li><li class="listitem">Stub servers will be started and fed with mappings</li><li class="listitem">Messaging definitions will be read and used in the messaging tests</li></ul></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_can_i_use_the_pact_broker" href="#_can_i_use_the_pact_broker"></a>3.7 Can I use the Pact Broker?</h2></div></div></div><p>When using <a class="link" href="https://pact.io/" target="_top">Pact</a> you can use the <a class="link" href="https://github.com/pact-foundation/pact_broker" target="_top">Pact Broker</a>
|
|
to store and share Pact definitions. Starting from Spring Cloud Contract
|
|
2.0.0 one can fetch Pact files from the Pact Broker to generate
|
|
tests and stubs.</p><p>As a prerequisite the Pact Converter and Pact Stub Downloader
|
|
are required. You have to add them via the <code class="literal">spring-cloud-contract-pact</code> dependency.
|
|
You can read more about it in the <a class="xref" href="multi__using_the_pluggable_architecture.html#pact-converter" title="10.1.1 Pact Converter">Section 10.1.1, “Pact Converter”</a> section.</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>Pact follows the Consumer Contract convention. That means
|
|
that the Consumer creates the Pact definitions first, then
|
|
shares the files with the Producer. Those expectations are generated
|
|
from the Consumer’s code and can break the Producer if the expectations
|
|
are not met.</p></td></tr></table></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_pact_consumer" href="#_pact_consumer"></a>3.7.1 Pact Consumer</h3></div></div></div><p>The consumer uses Pact framework to generate Pact files. The
|
|
Pact files are sent to the Pact Broker. An example of such
|
|
setup can be found <a class="link" href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/2.1.x/consumer_pact" target="_top">here</a>.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_producer_3" href="#_producer_3"></a>3.7.2 Producer</h3></div></div></div><p>For the producer, to use the Pact files from the Pact Broker, we can reuse the
|
|
same mechanism we use for external contracts. We route Spring Cloud Contract
|
|
to use the Pact implementation via the URL that contains
|
|
the <code class="literal">pact://</code> protocol. It’s enough to pass the URL to the
|
|
Pact Broker. An example of such setup can be found <a class="link" href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/2.1.x/producer_pact" target="_top">here</a>.</p><p><b>Maven. </b>
|
|
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><plugin></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-contract-maven-plugin<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>${spring-cloud-contract.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><extensions></span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></extensions></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><configuration></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!-- Base class mappings etc. --></span>
|
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!-- We want to pick contracts from a Git repository --></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><contractsRepositoryUrl></span>pact://http://localhost:8085<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></contractsRepositoryUrl></span>
|
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!-- We reuse the contract dependency section to set up the path
|
|
to the folder that contains the contract definitions. In our case the
|
|
path will be /groupId/artifactId/version/contracts --></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><contractDependency></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>${project.groupId}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>${project.artifactId}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!-- When + is passed, a latest tag will be applied when fetching pacts --></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>+<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></contractDependency></span>
|
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!-- The contracts mode can't be classpath --></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><contractsMode></span>REMOTE<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></contractsMode></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></configuration></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!-- Don't forget to add spring-cloud-contract-pact to the classpath! --></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependencies></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-contract-pact<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>${spring-cloud-contract.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependencies></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></plugin></span></pre><p>
|
|
</p><p><b>Gradle. </b>
|
|
</p><pre class="programlisting">buildscript {
|
|
repositories {
|
|
//...
|
|
}
|
|
|
|
dependencies {
|
|
// ...
|
|
// Don't forget to add spring-cloud-contract-pact to the classpath!
|
|
classpath "org.springframework.cloud:spring-cloud-contract-pact:${contractVersion}"
|
|
}
|
|
}
|
|
|
|
contracts {
|
|
// When + is passed, a latest tag will be applied when fetching pacts
|
|
contractDependency {
|
|
stringNotation = "${project.group}:${project.name}:+"
|
|
}
|
|
contractRepository {
|
|
repositoryUrl = "pact://http://localhost:8085"
|
|
}
|
|
// The mode can't be classpath
|
|
contractsMode = "REMOTE"
|
|
// Base class mappings etc.
|
|
}</pre><p>
|
|
</p><p>With such a setup:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Pact files will be downloaded from the Pact Broker</li><li class="listitem">Spring Cloud Contract will convert the Pact files into tests and stubs</li><li class="listitem">The JAR with the stubs gets automatically created as usual</li></ul></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_pact_consumer_producer_contract_approach" href="#_pact_consumer_producer_contract_approach"></a>3.7.3 Pact Consumer (Producer Contract approach)</h3></div></div></div><p>In the scenario where you don’t want to do Consumer Contract approach
|
|
(for every single consumer define the expectations) but you’d prefer
|
|
to do Producer Contracts (the producer provides the contracts and
|
|
publishes stubs), it’s enough to use Spring Cloud Contract with
|
|
Stub Runner option. An example of such setup can be found <a class="link" href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/2.1.x/consumer_pact_stubrunner" target="_top">here</a>.</p><p>First, remember to add Stub Runner and Spring Cloud Contract Pact module
|
|
as test dependencies.</p><p><b>Maven. </b>
|
|
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependencyManagement></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependencies></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-dependencies<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>${spring-cloud.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><type></span>pom<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></type></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><scope></span>import<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></scope></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependencies></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependencyManagement></span>
|
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!-- Don't forget to add spring-cloud-contract-pact to the classpath! --></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependencies></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!-- ... --></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-starter-contract-stub-runner<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><scope></span>test<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></scope></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-contract-pact<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><scope></span>test<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></scope></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependencies></span></pre><p>
|
|
</p><p><b>Gradle. </b>
|
|
</p><pre class="programlisting">dependencyManagement {
|
|
imports {
|
|
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
|
|
}
|
|
}
|
|
|
|
dependencies {
|
|
//...
|
|
testCompile("org.springframework.cloud:spring-cloud-starter-contract-stub-runner")
|
|
// Don't forget to add spring-cloud-contract-pact to the classpath!
|
|
testCompile("org.springframework.cloud:spring-cloud-contract-pact")
|
|
}</pre><p>
|
|
</p><p>Next, just pass the URL of the Pact Broker to <code class="literal">repositoryRoot</code>, prefixed
|
|
with <code class="literal">pact://</code> protocol. E.g. <code class="literal">pact://http://localhost:8085</code></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/">@AutoConfigureStubRunner(stubsMode = StubRunnerProperties.StubsMode.REMOTE,
|
|
ids = "com.example:beer-api-producer-pact",
|
|
repositoryRoot = "pact://http://localhost:8085")</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> BeerControllerTest {
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//Inject the port of the running stub</span>
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@StubRunnerPort("beer-api-producer-pact")</xslthl:annotation> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">int</span> producerPort;
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//...</span>
|
|
}</pre><p>With such a setup:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Pact files will be downloaded from the Pact Broker</li><li class="listitem">Spring Cloud Contract will convert the Pact files into stub definitions</li><li class="listitem">The stub servers will be started and fed with stubs</li></ul></div><p>For more information about Pact support you can go to
|
|
the <a class="xref" href="multi__using_the_pluggable_architecture.html#pact-stub-downloader" title="10.7 Using the Pact Stub Downloader">Section 10.7, “Using the Pact Stub Downloader”</a> section.</p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_how_can_i_debug_the_requestresponse_being_sent_by_the_generated_tests_client" href="#_how_can_i_debug_the_requestresponse_being_sent_by_the_generated_tests_client"></a>3.8 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_mappingrequestresponse_being_sent_by_wiremock" href="#_how_can_i_debug_the_mappingrequestresponse_being_sent_by_wiremock"></a>3.8.1 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.8.2 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>, <code class="literal">StubRunnerRule</code> or
|
|
`StubRunnerExtension`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_text_from_file" href="#_can_i_reference_text_from_file"></a>3.8.3 Can I reference text from file?</h3></div></div></div><p>Yes! With version 1.2.0 we’ve added such a possibility. It’s enough to call <code class="literal">file(…​)</code> method in the
|
|
DSL and provide a path relative to where the contract lays.
|
|
If you’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> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__spring_cloud_contract_verifier_setup.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">2. Spring Cloud Contract Verifier Introduction </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"> 4. Spring Cloud Contract Verifier Setup</td></tr></table></div></body></html> |