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