From 3f5b46c78811fc461950d2b661d4297875e9fe14 Mon Sep 17 00:00:00 2001
From: buildmaster
Date: Fri, 23 Sep 2016 08:32:27 +0000
Subject: [PATCH] Sync docs from master to gh-pages
---
spring-cloud-contract.html | 358 +++++++++++++++++++++++++++++++++++++
1 file changed, 358 insertions(+)
diff --git a/spring-cloud-contract.html b/spring-cloud-contract.html
index 262692fa0a..0830821651 100644
--- a/spring-cloud-contract.html
+++ b/spring-cloud-contract.html
@@ -463,6 +463,7 @@ body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-b
API Versioning
JAR versioning
Dev or prod stubs
+Common repo with contracts
@@ -958,6 +959,19 @@ going through the process. CDC is all about communication.
+
+
+
+|
+ Tip
+ |
+
+In this case the ownership of the contracts lays on the producer side. It means that physically
+all the contract are present in the producer’s repository
+ |
+
+
+
Technical note
@@ -1999,6 +2013,310 @@ version. Example for 2.1.1.
You can pass those values also via properties from your deployment pipeline.
+
+
Common repo with contracts
+
+
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 will you break with your local changes.
+
+
+
+
Let’s assume that we have a producer with coordinates com.example:server and 3 consumers: client1,
+client2, client3. Then in the repository with common contracts you would have the following setup
+(which you can checkout here:
+
+
+
+
├── com
+│ └── example
+│ └── server
+│ ├── client1
+│ │ └── expectation.groovy
+│ ├── client2
+│ │ └── expectation.groovy
+│ ├── client3
+│ │ └── expectation.groovy
+│ └── pom.xml
+├── mvnw
+├── mvnw.cmd
+├── pom.xml
+└── src
+ └── assembly
+ └── contracts.xml
+
+
+
+
As you can see the under the slash-delimited groupid / artifact id folder (com/example/server) you have
+expectations of the 3 consumers (client1, client2 and client3). 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.
+
+
+
Example of a pom.xml inside the server folder.
+
+
+
+
<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>com.example</groupId>
+ <artifactId>server</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+
+ <name>Server Stubs</name>
+ <description>POM used to install locally stubs for consumer side</description>
+
+ <parent>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-parent</artifactId>
+ <version>1.4.0.BUILD-SNAPSHOT</version>
+ <relativePath />
+ </parent>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <java.version>1.8</java.version>
+ <spring-cloud-contract.version>1.0.0.BUILD-SNAPSHOT</spring-cloud-contract.version>
+ <spring-cloud-dependencies.version>Camden.BUILD-SNAPSHOT</spring-cloud-dependencies.version>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.springframework.cloud</groupId>
+ <artifactId>spring-cloud-dependencies</artifactId>
+ <version>${spring-cloud-dependencies.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.springframework.cloud</groupId>
+ <artifactId>spring-cloud-contract-maven-plugin</artifactId>
+ <version>${spring-cloud-contract.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <!-- By default it would search under src/test/resources/ -->
+ <contractsDirectory>${project.basedir}</contractsDirectory>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <repositories>
+ <repository>
+ <id>spring-snapshots</id>
+ <name>Spring Snapshots</name>
+ <url>https://repo.spring.io/snapshot</url>
+ <snapshots>
+ <enabled>true</enabled>
+ </snapshots>
+ </repository>
+ <repository>
+ <id>spring-milestones</id>
+ <name>Spring Milestones</name>
+ <url>https://repo.spring.io/milestone</url>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ </repository>
+ <repository>
+ <id>spring-releases</id>
+ <name>Spring Releases</name>
+ <url>https://repo.spring.io/release</url>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ </repository>
+ </repositories>
+ <pluginRepositories>
+ <pluginRepository>
+ <id>spring-snapshots</id>
+ <name>Spring Snapshots</name>
+ <url>https://repo.spring.io/snapshot</url>
+ <snapshots>
+ <enabled>true</enabled>
+ </snapshots>
+ </pluginRepository>
+ <pluginRepository>
+ <id>spring-milestones</id>
+ <name>Spring Milestones</name>
+ <url>https://repo.spring.io/milestone</url>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ </pluginRepository>
+ <pluginRepository>
+ <id>spring-releases</id>
+ <name>Spring Releases</name>
+ <url>https://repo.spring.io/release</url>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ </pluginRepository>
+ </pluginRepositories>
+
+</project>
+
+
+
+
As you can see there are no dependencies other than the Spring Cloud Contract Verifier Maven plugin.
+Those poms are necessary for the consumer side to run mvn clean install -DskipTests to locally install
+ stubs of the producer project.
+
+
+
The pom.xml in the root folder can look like this:
+
+
+
+
<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>com.example.standalone</groupId>
+ <artifactId>contracts</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+
+ <name>Spring Cloud Contract Verifier Http Server Sample</name>
+ <description>Spring Cloud Contract Verifier Http Server Sample</description>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>contracts</id>
+ <phase>prepare-package</phase>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <configuration>
+ <attach>true</attach>
+ <descriptor>${basedir}/src/assembly/contracts.xml</descriptor>
+ <!-- If you want an explicit classifier remove the following line -->
+ <appendAssemblyId>false</appendAssemblyId>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
+
+
+
+
It’s using the assembly plugin in order to build the JAR with all the contracts. Example of such setup is here:
+
+
+
+
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
+ <id>project</id>
+ <formats>
+ <format>jar</format>
+ </formats>
+ <includeBaseDirectory>false</includeBaseDirectory>
+ <fileSets>
+ <fileSet>
+ <directory>${project.basedir}</directory>
+ <outputDirectory>/</outputDirectory>
+ <useDefaultExcludes>true</useDefaultExcludes>
+ <excludes>
+ <exclude>**/${project.build.directory}/**</exclude>
+ <exclude>mvnw</exclude>
+ <exclude>mvnw.cmd</exclude>
+ <exclude>.mvn/**</exclude>
+ <exclude>src/**</exclude>
+ </excludes>
+ </fileSet>
+ </fileSets>
+</assembly>
+
+
+
+
+
The workflow would look similar to the one presented in the Step by step guide to CDC. 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.
+
+
+
+
When the consumer 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. com/example/server)
+and runs mvn clean install -DskipTests to install locally the stubs converted from the contracts.
+
+
+
+
+
As a producer it’s enough to alter the Spring Cloud Contract Verifier to provide the URL and the dependency
+of the JAR containing the contracts:
+
+
+
+
<plugin>
+ <groupId>org.springframework.cloud</groupId>
+ <artifactId>spring-cloud-contract-maven-plugin</artifactId>
+ <configuration>
+ <contractsRepositoryUrl>http://link/to/your/nexus/or/artifactory/or/sth</contractsRepositoryUrl>
+ <contractDependency>
+ <groupId>com.example.standalone</groupId>
+ <artifactId>contracts</artifactId>
+ </contractDependency>
+ </configuration>
+</plugin>
+
+
+
+
With this setup the JAR with groupid com.example.standalone and artifactid contracts will be downloaded
+from http://link/to/your/nexus/or/artifactory/or/sth. It will be then unpacked in a local temporary folder
+and contracts present under the com/example/server 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.
+
+
+
The rest of the flow looks the same.
+
+
@@ -2169,6 +2487,11 @@ src/test/resources/contracts/myservice/shouldReturnUser.groovy
contractsDslDir = "${project.rootDir}/src/test/resources/contracts"
basePackageForTests = 'org.springframework.cloud.verifier.tests'
stubsOutputDir = project.file("${project.buildDir}/stubs")
+
+ // the following properties are used when you want to provide where the JAR with contract lays
+ contractDependency = new org.springframework.cloud.contract.verifier.plugin.ContractVerifierExtension.Dependency()
+ contractsPath = ''
+ contractsWorkOffline = false
}
tasks.create(type: Jar, name: 'verifierStubsJar', dependsOn: 'generateWireMockClientStubs') {
@@ -2252,6 +2575,22 @@ publishing {
+
+
The following properties are used when you want to provide where the JAR with contract lays
+
+
+
+-
+
contractDependency - the Dependency that provides groupid:artifactid:version:classifier coordinates. You can use the contractDependency closure to set it up
+
+-
+
contractsPath - if contract deps are downloaded will default to groupid/artifactid where groupid will be slash separated. Otherwise will scan contracts under provided directory
+
+-
+
contractsWorkOffline - in order not to download the dependencies each time you can download them once and work offline afterwards (reuse local Maven repo)
+
+
+
Base class for tests
@@ -2522,6 +2861,25 @@ src/test/resources/contracts/myservice/shouldReturnUser.groovy
+
If you want to download your contract definitions from a Maven repository you can use
+
+
+
+-
+
contractsRepositoryUrl - URL to a repo with the artifacts with contracts, if not provided should use the current Maven ones
+
+-
+
contractDependency - the contract dependency that contains all the packaged contracts
+
+-
+
contractsPath - path to concrete contracts in the JAR with packaged contracts. Defaults to groupid/artifactid where gropuid is slash separated.
+
+-
+
contractsWorkOffline - if the dependencies should be downloaded or local Maven only should be reused
+
+
+
+