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.

    The server side code is available here and the client side code here.

    +
    + + + + + +
    +
    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.

    +
    +
    +
      +
    • +

      Repo structure *

      +
    • +
    +
    +
    +

    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>
    +
    +
    +
    +

    Workflow

    +
    +
    +

    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.

    +
    +
    +

    Consumer

    +
    +
    +

    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.

    +
    +
    + + + + + +
    +
    Tip
    +
    +You need to have Maven installed locally +
    +
    +
    +

    Producer

    +
    +
    +

    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

    +
    +
    + +
    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

    +
    +
    + +
    +

    For complete information take a look at Plugin Documentation