From 097377091f38d9f04a7fa51e0116bd157f465c2e Mon Sep 17 00:00:00 2001 From: buildmaster Date: Tue, 7 Feb 2017 06:43:14 +0000 Subject: [PATCH] Sync docs from master to gh-pages --- spring-cloud-contract.html | 1113 ++++++++++++++++++------------------ 1 file changed, 556 insertions(+), 557 deletions(-) diff --git a/spring-cloud-contract.html b/spring-cloud-contract.html index 45d54bd6b5..f28b7c3890 100644 --- a/spring-cloud-contract.html +++ b/spring-cloud-contract.html @@ -796,28 +796,12 @@ $(addBlockSwitches); -
  • Pluggable architecture - -
  • -
  • Links
  • +
  • Converters
  • +
  • Stub converters
  • +
  • Example of a custom HTTP Server Stub
  • +
  • Example of a custom Stub Downloader Provider
  • @@ -1949,12 +1933,7 @@ public class LoanApplicationServiceTests {
    -
    @RequestMapping(
    -		value = "/fraudcheck",
    -		method = PUT,
    -		consumes = FRAUD_SERVICE_JSON_VERSION_1,
    -		produces = FRAUD_SERVICE_JSON_VERSION_1)
    -public FraudCheckResult fraudCheck(@RequestBody FraudCheck fraudCheck) {
    +
    Unresolved directive in verifier/introduction.adoc - include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/1.0.x/samples/standalone/dsl/http-server/src/main/java/com/example/fraud/FraudDetectionController.java[tags=server_api,indent=0]
     return new FraudCheckResult(FraudCheckStatus.OK, NO_REASON);
     }
    @@ -2773,7 +2752,17 @@ of the JAR containing the contracts:

    -
    Unresolved directive in verifier/introduction.adoc - include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/1.0.x/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/basic-remote-contracts/pom-with-repo.xml[tags=remote_config,indent=0]
    +
    <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>
    @@ -7747,70 +7736,26 @@ common jar classes will be visible in your Groovy files.

    -
    package contracts.beer.rest
    +
    Unresolved directive in verifier/contract.adoc - include::https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-contract-samples/master/producer/src/test/resources/contracts/beer/rest/shouldGrantABeerIfOldEnough.groovy[indent=0]
     
    -import org.springframework.cloud.contract.spec.Contract
    +=== Pluggable architecture
     
    -import static com.example.ConsumerUtils.oldEnough
    -import static com.example.ProducerUtils.ok
    -
    -Contract.make {
    -	request {
    -		description("""
    -Represents a successful scenario of getting a beer
    -
    -given:
    -	client is old enough
    -when:
    -	he applies for a beer
    -then:
    -	we'll grant him the beer
    -""")
    -		method 'POST'
    -		url '/check'
    -		body(
    -				age: $(oldEnough())
    -		)
    -		headers {
    -			contentType(applicationJson())
    -		}
    -	}
    -	response {
    -		status 200
    -		body("""
    -			{
    -				"status": "${value(ok())}"
    -			}
    -			""")
    -		headers {
    -			contentType(applicationJson())
    -		}
    -	}
    -}
    -
    -
    - - - - -
    -

    Pluggable architecture

    -
    -

    There are cases where you have your contracts defined in other formats -like YAML, RAML or PACT. On the other hand you’d like to profit from -the test and stubs generation. It’s really easy to add your own implementation +There are cases where you have your contracts defined in other formats +like YAML, RAML or PACT. On the other hand you'd like to profit from +the test and stubs generation. It's really easy to add your own implementation of either of those. Also you can customize the way tests are generated (for example you can generate tests for other languages) and you can do the same for stubs generation (you can generate -stubs for other stub http server implementations).

    +stubs for other stub http server implementations). + +==== Custom contract converter + +Let's assume that your contract is written in a YAML file like this: + +[source,yml]
    +
    -
    -

    Custom contract converter

    -

    Let’s assume that your contract is written in a YAML file like this:

    -
    -
    -
    -
    request:
    +

    request: url: /foo method: PUT headers: @@ -7822,17 +7767,20 @@ response: headers: foo2: bar body: - foo2: bar

    -
    -
    -
    -

    Thanks to the interface

    + foo2: bar

    -
    package org.springframework.cloud.contract.spec
    +
    Thanks to the interface
     
    -/**
    +[source,groovy]
    +
    +
    +
    +

    package org.springframework.cloud.contract.spec

    +
    +
    +

    /** * Converter to be used to convert FROM {@link File} TO {@link Contract} * and from {@link Contract} to {@code T} * @@ -7841,120 +7789,138 @@ response: * @author Marcin Grzejszczak * @since 1.1.0 */ -interface ContractConverter<T> { - - /** - * Should this file be accepted by the converter. Can use the file extension - * to check if the conversion is possible. - * - * @param file - file to be considered for conversion - * @return - {@code true} if the given implementation can convert the file - */ - boolean isAccepted(File file) - - /** - * Converts the given {@link File} to its {@link Contract} representation - * - * @param file - file to convert - * @return - {@link Contract} representation of the file - */ - Collection<Contract> convertFrom(File file) - - /** +interface ContractConverter<T> {

    +
    +
    +
    +
    /**
    + * Should this file be accepted by the converter. Can use the file extension
    + * to check if the conversion is possible.
    + *
    + * @param file - file to be considered for conversion
    + * @return - {@code true} if the given implementation can convert the file
    + */
    +boolean isAccepted(File file)
    +
    +
    +
    +
    +
    /**
    + * Converts the given {@link File} to its {@link Contract} representation
    + *
    + * @param file - file to convert
    + * @return - {@link Contract} representation of the file
    + */
    +Collection<Contract> convertFrom(File file)
    +
    +
    +
    +
    +
    	/**
     	 * Converts the given {@link Contract} to a {@link T} representation
     	 *
     	 * @param contract - the parsed contract
     	 * @return - {@link T} the type to which we do the conversion
     	 */
     	T convertTo(Collection<Contract> contract)
    -}
    +}
    -
    -

    you can register your own implementation of a contract structure converter. +

    +
    +
    you can register your own implementation of a contract structure converter.
     Your implementation needs to state the condition on which it should start the
    -conversion. Also you have to define how to perform that conversion in both ways.

    -
    -
    - - - - - -
    -
    Important
    -
    -Once you create your implementation you have to create a /META-INF/spring.factories -file in which you provide the fully qualified name of your implementation. -
    -
    -
    -

    Example of a spring.factories file

    -
    -
    -
    -
    # Converters
    -org.springframework.cloud.contract.spec.ContractConverter=\
    -org.springframework.cloud.contract.verifier.converter.YamlContractConverter
    -
    -
    -
    -

    and the YAML implementation

    -
    -
    -
    -
    package org.springframework.cloud.contract.verifier.converter
    +conversion. Also you have to define how to perform that conversion in both ways.
     
    -import groovy.transform.CompileStatic
    +IMPORTANT: Once you create your implementation you have to create a `/META-INF/spring.factories`
    +file in which you provide the fully qualified name of your implementation.
    +
    +Example of a `spring.factories` file
    +
    +[source]
    +
    +
    +
    +
    +
    + + + +

    Converters

    +
    +

    org.springframework.cloud.contract.spec.ContractConverter=\ +org.springframework.cloud.contract.verifier.converter.YamlContractConverter

    +
    +
    +
    +
    and the YAML implementation
    +
    +[source,groovy]
    +
    +
    +
    +

    package org.springframework.cloud.contract.verifier.converter

    +
    +
    +

    import groovy.transform.CompileStatic import org.springframework.cloud.contract.spec.Contract import org.springframework.cloud.contract.spec.ContractConverter import org.springframework.cloud.contract.spec.internal.Headers -import org.yaml.snakeyaml.Yaml - -/** +import org.yaml.snakeyaml.Yaml

    +
    +
    +

    /** * Simple converter from and to a {@link YamlContract} to a collection of {@link Contract} */ @CompileStatic -class YamlContractConverter implements ContractConverter<List<YamlContract>> { - - @Override - public boolean isAccepted(File file) { - String name = file.getName() - return name.endsWith(".yml") || name.endsWith(".yaml") - } - - @Override - public Collection<Contract> convertFrom(File file) { - try { - YamlContract yamlContract = new Yaml().loadAs(new FileInputStream(file), YamlContract.class) - return [Contract.make { - request { - method(yamlContract?.request?.method) - url(yamlContract?.request?.url) - headers { - yamlContract?.request?.headers?.each { String key, Object value -> - header(key, value) - } +class YamlContractConverter implements ContractConverter<List<YamlContract>> {

    +
    +
    +
    +
    @Override
    +public boolean isAccepted(File file) {
    +	String name = file.getName()
    +	return name.endsWith(".yml") || name.endsWith(".yaml")
    +}
    +
    +
    +
    +
    +
    @Override
    +public Collection<Contract> convertFrom(File file) {
    +	try {
    +		YamlContract yamlContract = new Yaml().loadAs(new FileInputStream(file), YamlContract.class)
    +		return [Contract.make {
    +			request {
    +				method(yamlContract?.request?.method)
    +				url(yamlContract?.request?.url)
    +				headers {
    +					yamlContract?.request?.headers?.each { String key, Object value ->
    +						header(key, value)
     					}
    -					body(yamlContract?.request?.body)
     				}
    -				response {
    -					status(yamlContract?.response?.status)
    -					headers {
    -						yamlContract?.response?.headers?.each { String key, Object value ->
    -							header(key, value)
    -						}
    +				body(yamlContract?.request?.body)
    +			}
    +			response {
    +				status(yamlContract?.response?.status)
    +				headers {
    +					yamlContract?.response?.headers?.each { String key, Object value ->
    +						header(key, value)
     					}
    -					body(yamlContract?.response?.body)
     				}
    -			}]
    -		}
    -		catch (FileNotFoundException e) {
    -			throw new IllegalStateException(e)
    -		}
    +				body(yamlContract?.response?.body)
    +			}
    +		}]
     	}
    -
    -	@Override
    +	catch (FileNotFoundException e) {
    +		throw new IllegalStateException(e)
    +	}
    +}
    +
    +
    +
    +
    +
    	@Override
     	public List<YamlContract> convertTo(Collection<Contract> contracts) {
     		return contracts.collect { Contract contract ->
     			YamlContract yamlContract = new YamlContract()
    @@ -7972,25 +7938,27 @@ class YamlContractConverter implements ContractConverter<List<YamlContract
     			return yamlContract
     		}
     	}
    -}
    +}
    -
    -
    Pact converter
    -
    -

    Spring Cloud Contract comes with an out of the box support for Pact representation of contracts. -In other words instead of using the Groovy DSL you can use Pact files. In this section -we will present how to add such a support for your project.

    -
    -
    -
    Pact contract
    -
    -

    We will be working on the following example of a Pact contract. We’ve placed this file under -the src/test/resources/contracts folder.

    -
    -
    {
    +
    ===== Pact converter
    +
    +Spring Cloud Contract comes with an out of the box support for https://docs.pact.io/[Pact] representation of contracts.
    +In other words instead of using the Groovy DSL you can use Pact files. In this section
    +we will present how to add such a support for your project.
    +
    +====== Pact contract
    +
    +We will be working on the following example of a Pact contract. We've placed this file under
    +the `src/test/resources/contracts` folder.
    +
    +[source,javascript,indent=0]
    +
    +
    +
    +

    { "provider": { "name": "Provider" }, @@ -8043,21 +8011,22 @@ the src/test/resources/contracts folder.

    "version": "2.4.18" } } -}
    +}

    -
    -
    -
    -
    Pact for producers
    -
    -

    On the producer side you have add to your plugin configuration two additional dependencies. -One is the Spring Cloud Contract Pact support and the other represents the current -Pact version that you’re using.

    -
    -
    -
    Maven
    +
    -
    <plugin>
    +
    ====== Pact for producers
    +
    +On the producer side you have add to your plugin configuration two additional dependencies.
    +One is the Spring Cloud Contract Pact support and the other represents the current
    +Pact version that you're using.
    +
    +[source,xml,indent=0,subs="verbatim,attributes",role="primary"]
    +.Maven
    +
    +
    +
    +

    <plugin> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-contract-maven-plugin</artifactId> <version>${spring-cloud-contract.version}</version> @@ -8077,33 +8046,45 @@ Pact version that you’re using.

    <version>2.4.18</version> </dependency> </dependencies> -</plugin>
    -
    -
    -
    -
    Gradle
    -
    -
    classpath "org.springframework.cloud:spring-cloud-contract-spec-pact:${findProperty('verifierVersion') ?: verifierVersion}"
    -classpath 'au.com.dius:pact-jvm-model:2.4.18'
    -
    -
    -
    -

    When you execute the build of your application a test, looking more or less like this, will be generated

    +</plugin>

    -
    @Test
    +
    [source,groovy,indent=0,subs="verbatim,attributes",role="secondary"]
    +.Gradle
    +
    +
    +
    +

    classpath "org.springframework.cloud:spring-cloud-contract-spec-pact:${findProperty('verifierVersion') ?: verifierVersion}" +classpath 'au.com.dius:pact-jvm-model:2.4.18'

    +
    +
    +
    +
    When you execute the build of your application a test, looking more or less like this, will be generated
    +
    +[source,java,indent=0]
    +
    +
    +
    +
    +
    @Test
     public void validate_shouldMarkClientAsFraud() throws Exception {
     	// given:
     		MockMvcRequestSpecification request = given()
     				.header("Content-Type", "application/vnd.fraud.v1+json")
    -				.body("{\"clientId\":\"1234567890\",\"loanAmount\":99999}");
    -
    -	// when:
    -		ResponseOptions response = given().spec(request)
    -				.put("/fraudcheck");
    -
    -	// then:
    +				.body("{\"clientId\":\"1234567890\",\"loanAmount\":99999}");
    +
    +
    +
    +
    +
    // when:
    +	ResponseOptions response = given().spec(request)
    +			.put("/fraudcheck");
    +
    +
    +
    +
    +
    	// then:
     		assertThat(response.statusCode()).isEqualTo(200);
     		assertThat(response.header("Content-Type")).isEqualTo("application/vnd.fraud.v1+json;charset=UTF-8");
     	// and:
    @@ -8111,15 +8092,18 @@ public void validate_shouldMarkClientAsFraud() throws Exception {
     		assertThatJson(parsedJson).field("rejectionReason").isEqualTo("Amount too high");
     	// and:
     		assertThat(parsedJson.read("$.fraudCheckStatus", String.class)).matches("FRAUD");
    -}
    +}
    -
    -

    and the stub looking like this

    -
    -
    {
    +
    and the stub looking like this
    +
    +[source,javascript,indent=0]
    +
    +
    +
    +

    { "uuid" : "996ae5ae-6834-4db6-8fac-358ca187ab62", "request" : { "url" : "/fraudcheck", @@ -8142,21 +8126,22 @@ public void validate_shouldMarkClientAsFraud() throws Exception { "Content-Type" : "application/vnd.fraud.v1+json;charset=UTF-8" } } -} +}

    -
    - -
    -
    Pact for consumers
    -
    -

    On the producer side you have add to your project dependencies two additional dependencies. -One is the Spring Cloud Contract Pact support and the other represents the current -Pact version that you’re using.

    -
    -
    -
    Maven
    +
    -
    <dependency>
    +
    ====== Pact for consumers
    +
    +On the producer side you have add to your project dependencies two additional dependencies.
    +One is the Spring Cloud Contract Pact support and the other represents the current
    +Pact version that you're using.
    +
    +[source,xml,indent=0,subs="verbatim,attributes",role="primary"]
    +.Maven
    +
    +
    +
    +

    <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-contract-spec-pact</artifactId> <scope>test</scope> @@ -8166,46 +8151,51 @@ Pact version that you’re using.

    <artifactId>pact-jvm-model</artifactId> <version>2.4.18</version> <scope>test</scope> -</dependency>
    -
    -
    -
    -
    Gradle
    -
    -
    testCompile "org.springframework.cloud:spring-cloud-contract-spec-pact"
    -testCompile 'au.com.dius:pact-jvm-model:2.4.18'
    -
    -
    -
    - - -
    -

    Custom test generator

    -
    -

    If you want to generate tests for different languages than Java or you’re -not happy with the way we’re building Java tests for you then you can register -your own implementation to do that.

    -
    -
    -

    Thanks to the interface

    +</dependency>

    -
    package org.springframework.cloud.contract.verifier.builder
    +
    [source,groovy,indent=0,subs="verbatim,attributes",role="secondary"]
    +.Gradle
    +
    +
    +
    +

    testCompile "org.springframework.cloud:spring-cloud-contract-spec-pact" +testCompile 'au.com.dius:pact-jvm-model:2.4.18'

    +
    +
    +
    +
    ==== Custom test generator
     
    -import groovy.transform.CompileStatic
    +If you want to generate tests for different languages than Java or you're
    +not happy with the way we're building Java tests for you then you can register
    +your own implementation to do that.
    +
    +Thanks to the interface
    +
    +[source,groovy]
    +
    +
    +
    +

    package org.springframework.cloud.contract.verifier.builder

    +
    +
    +

    import groovy.transform.CompileStatic import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties -import org.springframework.cloud.contract.verifier.file.ContractMetadata - -/** +import org.springframework.cloud.contract.verifier.file.ContractMetadata

    +
    +
    +

    /** * Builds a single test. * * @since 1.1.0 */ @CompileStatic -interface SingleTestGenerator { - - /** +interface SingleTestGenerator {

    +
    +
    +
    +
    	/**
     	 * Creates contents of a single test class in which all test scenarios from
     	 * the contract metadata should be placed.
     	 *
    @@ -8218,54 +8208,68 @@ interface SingleTestGenerator {
     	 */
     	String buildClass(ContractVerifierConfigProperties properties, Collection<ContractMetadata> listOfFiles,
     					  String className, String classPackage, String includedDirectoryRelativePath)
    -}
    +}
    -
    -

    you can register your own implementation that generates a test. Again, it’s enough to provide -a proper spring.factories file. Example:

    -
    -
    org.springframework.cloud.contract.verifier.builder.SingleTestGenerator=/
    -com.example.MyGenerator
    -
    -
    -
    -
    -

    Custom stub generator

    -
    -

    If you want to generate stubs for other stub server than WireMock it’s enough to - plug in your own implementation of this interface:

    -
    -
    -
    -
    package org.springframework.cloud.contract.verifier.converter
    +
    you can register your own implementation that generates a test. Again, it's enough to provide
    +a proper `spring.factories` file. Example:
     
    -import groovy.transform.CompileStatic
    +[source]
    +
    +
    +
    +

    org.springframework.cloud.contract.verifier.builder.SingleTestGenerator=/ +com.example.MyGenerator

    +
    +
    +
    +
    ==== Custom stub generator
    +
    +If you want to generate stubs for other stub server than WireMock it's enough to
    + plug in your own implementation of this interface:
    +
    +[source,groovy]
    +
    +
    +
    +

    package org.springframework.cloud.contract.verifier.converter

    +
    +
    +

    import groovy.transform.CompileStatic import org.springframework.cloud.contract.spec.Contract -import org.springframework.cloud.contract.verifier.file.ContractMetadata - -/** +import org.springframework.cloud.contract.verifier.file.ContractMetadata

    +
    +
    +

    /** * Converts contracts into their stub representation. * * @since 1.1.0 */ @CompileStatic -interface StubGenerator { - - /** - * Returns {@code true} if the converter can handle the file to convert it into a stub. - */ - boolean canHandleFileName(String fileName) - - /** - * Returns the collection of converted contracts into stubs. One contract can - * result in multiple stubs. - */ - Map<Contract, String> convertContents(String rootName, ContractMetadata content) - - /** +interface StubGenerator {

    +
    +
    +
    +
    /**
    + * Returns {@code true} if the converter can handle the file to convert it into a stub.
    + */
    +boolean canHandleFileName(String fileName)
    +
    +
    +
    +
    +
    /**
    + * Returns the collection of converted contracts into stubs. One contract can
    + * result in multiple stubs.
    + */
    +Map<Contract, String> convertContents(String rootName, ContractMetadata content)
    +
    +
    +
    +
    +
    	/**
     	 * Returns the name of the converted stub file. If you have multiple contracts
     	 * in a single file then a prefix will be added to the generated file. If you
     	 * provide the {@link Contract#name} field then that field will override the
    @@ -8276,220 +8280,246 @@ interface StubGenerator {
     	 * converter will create two files {@code 0_foo.json} and {@code 1_foo.json}
     	 */
     	String generateOutputFileNameForInput(String inputFileName)
    -}
    +}
    -
    -

    you can register your own implementation that generate Stubs. Again, it’s enough to provide -a proper spring.factories file. Example:

    -
    -
    # Stub converters
    -org.springframework.cloud.contract.verifier.converter.StubGenerator=\
    -org.springframework.cloud.contract.verifier.wiremock.DslToWireMockClientConverter
    -
    -
    -
    -

    The default implementation is the WireMock stub generation.

    -
    -
    - - - - - -
    -
    Tip
    -
    -You can provide multiple stub generator implementations. That way for example from a single -DSL as input you can e.g. produce WireMock stubs and Pact files too! -
    -
    -
    -
    -

    Custom Stub Runner

    -
    -

    If you decide to have a custom stub generation you also need a custom way of running -stubs with your different stub provider.

    -
    -
    -

    Let us assume that you’re using Moco to build your stubs. -You wrote a proper stub generator and your stubs got placed in a JAR file.

    -
    -
    -

    In order for Stub Runner to know how to run your stubs you have to define a custom - HTTP Stub server implementation. It can look like this:

    -
    -
    -
    -
    package org.springframework.cloud.contract.stubrunner.provider.moco
    +
    you can register your own implementation that generate Stubs. Again, it's enough to provide
    +a proper `spring.factories` file. Example:
     
    -import com.github.dreamhead.moco.bootstrap.arg.HttpArgs
    +[source]
    +
    +
    +

    Stub converters

    +
    +

    org.springframework.cloud.contract.verifier.converter.StubGenerator=\ +org.springframework.cloud.contract.verifier.wiremock.DslToWireMockClientConverter

    +
    +
    +
    +
    The default implementation is the WireMock stub generation.
    +
    +TIP: You can provide multiple stub generator implementations. That way for example from a single
    +DSL as input you can e.g. produce WireMock stubs and Pact files too!
    +
    +==== Custom Stub Runner
    +
    +If you decide to have a custom stub generation you also need a custom way of running
    +stubs with your different stub provider.
    +
    +Let us assume that you're using https://github.com/dreamhead/moco[Moco] to build your stubs.
    +You wrote a proper stub generator and your stubs got placed in a JAR file.
    +
    +In order for Stub Runner to know how to run your stubs you have to define a custom
    + HTTP Stub server implementation. It can look like this:
    +
    +[source,groovy]
    +
    +
    +
    +

    package org.springframework.cloud.contract.stubrunner.provider.moco

    +
    +
    +

    import com.github.dreamhead.moco.bootstrap.arg.HttpArgs import com.github.dreamhead.moco.runner.JsonRunner import org.springframework.cloud.contract.stubrunner.HttpServerStub -import org.springframework.util.SocketUtils - -class MocoHttpServerStub implements HttpServerStub { - - private boolean started - private JsonRunner runner - private int port - - @Override - int port() { - if (!isRunning()) { - return -1 - } - return port +import org.springframework.util.SocketUtils

    +
    +
    +

    class MocoHttpServerStub implements HttpServerStub {

    +
    +
    +
    +
    private boolean started
    +private JsonRunner runner
    +private int port
    +
    +
    +
    +
    +
    @Override
    +int port() {
    +	if (!isRunning()) {
    +		return -1
     	}
    -
    -	@Override
    -	boolean isRunning() {
    -		return started
    -	}
    -
    -	@Override
    -	HttpServerStub start() {
    -		return start(SocketUtils.findAvailableTcpPort())
    -	}
    -
    -	@Override
    -	HttpServerStub start(int port) {
    -		this.port = port
    +	return port
    +}
    +
    +
    +
    +
    +
    @Override
    +boolean isRunning() {
    +	return started
    +}
    +
    +
    +
    +
    +
    @Override
    +HttpServerStub start() {
    +	return start(SocketUtils.findAvailableTcpPort())
    +}
    +
    +
    +
    +
    +
    @Override
    +HttpServerStub start(int port) {
    +	this.port = port
    +	return this
    +}
    +
    +
    +
    +
    +
    @Override
    +HttpServerStub stop() {
    +	if (!isRunning()) {
     		return this
     	}
    -
    -	@Override
    -	HttpServerStub stop() {
    -		if (!isRunning()) {
    -			return this
    -		}
    -		this.runner.stop()
    -		return this
    -	}
    -
    -	@Override
    -	HttpServerStub registerMappings(Collection<File> stubFiles) {
    -		List<InputStream> streams = stubFiles.collect { it.newInputStream() }
    -		this.runner = JsonRunner.newJsonRunnerWithStreams(streams,
    -				HttpArgs.httpArgs().withPort(this.port).build())
    -		this.runner.run()
    -		this.started = true
    -		return this
    -	}
    -
    -	@Override
    +	this.runner.stop()
    +	return this
    +}
    +
    +
    +
    +
    +
    @Override
    +HttpServerStub registerMappings(Collection<File> stubFiles) {
    +	List<InputStream> streams = stubFiles.collect { it.newInputStream() }
    +	this.runner = JsonRunner.newJsonRunnerWithStreams(streams,
    +			HttpArgs.httpArgs().withPort(this.port).build())
    +	this.runner.run()
    +	this.started = true
    +	return this
    +}
    +
    +
    +
    +
    +
    	@Override
     	boolean isAccepted(File file) {
     		return file.name.endsWith(".json")
     	}
    -}
    +}
    -
    -

    and just register it in your spring.factories file

    -
    -
    # Example of a custom HTTP Server Stub
    -org.springframework.cloud.contract.stubrunner.HttpServerStub=\
    -org.springframework.cloud.contract.stubrunner.provider.moco.MocoHttpServerStub
    -
    -
    -
    -

    that way you’ll be able to run stubs using Moco.

    -
    -
    - - - - - -
    -
    Important
    -
    -If you don’t provide any implementation then the default one - WireMock based -will be picked. If you provide more than one then the first one on the list will be picked. -
    -
    -
    -
    -

    Custom Stub Downloader

    -
    -

    You can customize the way your stubs are downloaded. If you don’t want to download the JARs -from Nexus / Artifactory in the way we do by default you can set your own implementation. -Below you can find an example of a Stub Downloader Provider that takes json files from the test resources -from classpath, copies them to a temp file and then passes that temporary folder - as a root for the stubs.

    -
    -
    -
    -
    package org.springframework.cloud.contract.stubrunner.provider.moco
    +
    and just register it in your `spring.factories` file
     
    -import org.springframework.cloud.contract.stubrunner.StubConfiguration
    +[source]
    +
    +
    +

    Example of a custom HTTP Server Stub

    +
    +

    org.springframework.cloud.contract.stubrunner.HttpServerStub=\ +org.springframework.cloud.contract.stubrunner.provider.moco.MocoHttpServerStub

    +
    +
    +
    +
    that way you'll be able to run stubs using Moco.
    +
    +IMPORTANT: If you don't provide any implementation then the default one - WireMock based
    +will be picked. If you provide more than one then the first one on the list will be picked.
    +
    +==== Custom Stub Downloader
    +
    +You can customize the way your stubs are downloaded. If you don't want to download the JARs
    +from Nexus / Artifactory in the way we do by default you can set your own implementation.
    +Below you can find an example of a Stub Downloader Provider that takes `json` files from the test resources
    +from classpath, copies them to a temp file and then passes that temporary folder
    + as a root for the stubs.
    +
    +[source,java]
    +
    +
    +
    +

    package org.springframework.cloud.contract.stubrunner.provider.moco

    +
    +
    +

    import org.springframework.cloud.contract.stubrunner.StubConfiguration import org.springframework.cloud.contract.stubrunner.StubDownloader import org.springframework.cloud.contract.stubrunner.StubDownloaderBuilder import org.springframework.cloud.contract.stubrunner.StubRunnerOptions import org.springframework.core.io.DefaultResourceLoader import org.springframework.core.io.Resource -import org.springframework.core.io.support.PathMatchingResourcePatternResolver - -import java.nio.file.Files - -/** - * Poor man's version of taking stubs from classpath. It needs much more +import org.springframework.core.io.support.PathMatchingResourcePatternResolver

    +
    +
    +

    import java.nio.file.Files

    +
    +
    +

    /** + * Poor man’s version of taking stubs from classpath. It needs much more * love and attention to go to the main sources. * * @author Marcin Grzejszczak */ -class ClasspathStubProvider implements StubDownloaderBuilder { - - private static final int TEMP_DIR_ATTEMPTS = 10000 - - @Override - public StubDownloader build(StubRunnerOptions stubRunnerOptions) { - final StubConfiguration configuration = stubRunnerOptions.getDependencies().first() - PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver( - new DefaultResourceLoader()) - try { - String rootFolder = repoRoot(stubRunnerOptions) ?: "**/" + separatedArtifact(configuration) + "/**/*.json" - Resource[] resources = resolver.getResources(rootFolder) - final File tmp = createTempDir() - tmp.deleteOnExit() - // you'd have to write an impl to maintain the folder structure - // this is just for demo - resources.each { Resource resource -> - Files.copy(resource.getInputStream(), new File(tmp, resource.getFile().getName()).toPath()) - } - return new StubDownloader() { - @Override - public Map.Entry<StubConfiguration, File> downloadAndUnpackStubJar( - StubConfiguration stubConfiguration) { - return new AbstractMap.SimpleEntry(configuration, tmp) - } - } - } catch (IOException e) { - throw new IllegalStateException(e) +class ClasspathStubProvider implements StubDownloaderBuilder {

    +
    +
    +
    +
    private static final int TEMP_DIR_ATTEMPTS = 10000
    +
    +
    +
    +
    +
    @Override
    +public StubDownloader build(StubRunnerOptions stubRunnerOptions) {
    +	final StubConfiguration configuration = stubRunnerOptions.getDependencies().first()
    +	PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(
    +			new DefaultResourceLoader())
    +	try {
    +		String rootFolder = repoRoot(stubRunnerOptions) ?: "**/" + separatedArtifact(configuration) + "/**/*.json"
    +		Resource[] resources = resolver.getResources(rootFolder)
    +		final File tmp = createTempDir()
    +		tmp.deleteOnExit()
    +		// you'd have to write an impl to maintain the folder structure
    +		// this is just for demo
    +		resources.each { Resource resource ->
    +			Files.copy(resource.getInputStream(), new File(tmp, resource.getFile().getName()).toPath())
     		}
    -	}
    -
    -	private String repoRoot(StubRunnerOptions stubRunnerOptions) {
    -		switch (stubRunnerOptions.stubRepositoryRoot) {
    -			case { !it }:
    -				return ""
    -			case { String root -> root.endsWith("**/*.json") }:
    -				return stubRunnerOptions.stubRepositoryRoot
    -			default:
    -				return stubRunnerOptions.stubRepositoryRoot + "/**/*.json"
    +		return new StubDownloader() {
    +			@Override
    +			public Map.Entry<StubConfiguration, File> downloadAndUnpackStubJar(
    +					StubConfiguration stubConfiguration) {
    +				return new AbstractMap.SimpleEntry(configuration, tmp)
    +			}
     		}
    +	} catch (IOException e) {
    +		throw new IllegalStateException(e)
     	}
    -
    -	private String separatedArtifact(StubConfiguration configuration) {
    -		return configuration.getGroupId().replace(".", File.separator) +
    -				File.separator + configuration.getArtifactId()
    +}
    +
    +
    +
    +
    +
    private String repoRoot(StubRunnerOptions stubRunnerOptions) {
    +	switch (stubRunnerOptions.stubRepositoryRoot) {
    +		case { !it }:
    +			return ""
    +		case { String root -> root.endsWith("**/*.json") }:
    +			return stubRunnerOptions.stubRepositoryRoot
    +		default:
    +			return stubRunnerOptions.stubRepositoryRoot + "/**/*.json"
     	}
    -
    -	// Taken from Guava
    +}
    +
    +
    +
    +
    +
    private String separatedArtifact(StubConfiguration configuration) {
    +	return configuration.getGroupId().replace(".", File.separator) +
    +			File.separator + configuration.getArtifactId()
    +}
    +
    +
    +
    +
    +
    	// Taken from Guava
     	private File createTempDir() {
     		File baseDir = new File(System.getProperty("java.io.tmpdir"))
     		String baseName = System.currentTimeMillis() + "-"
    @@ -8503,71 +8533,40 @@ class ClasspathStubProvider implements StubDownloaderBuilder {
     				"Failed to create directory within " + TEMP_DIR_ATTEMPTS + " attempts (tried " + baseName + "0 to " + baseName + (
     						TEMP_DIR_ATTEMPTS - 1) + ")")
     	}
    -}
    +}
    -
    -

    and just register it in your spring.factories file

    -
    -
    # Example of a custom Stub Downloader Provider
    -org.springframework.cloud.contract.stubrunner.StubDownloaderBuilder=\
    -org.springframework.cloud.contract.stubrunner.provider.moco.ClasspathStubProvider
    +
    and just register it in your `spring.factories` file
    +
    +[source]
    +

    Example of a custom Stub Downloader Provider

    -

    that way you’ll be able to pick a folder with the source of your stubs.

    +

    org.springframework.cloud.contract.stubrunner.StubDownloaderBuilder=\ +org.springframework.cloud.contract.stubrunner.provider.moco.ClasspathStubProvider

    -
    - - - - - -
    -
    Important
    -
    -If you don’t provide any implementation then the default one - Aether based that will download stubs from a remote repo +
    +
    +
    that way you'll be able to pick a folder with the source of your stubs.
    +
    +IMPORTANT: If you don't provide any implementation then the default one - Aether based that will download stubs from a remote repo
     will be picked. If you provide more than one then the first one on the list will be picked.
    -
    -
    -
    - - + +=== Links + +Here you can find interesting links related to Spring Cloud Contract Verifier: + +- https://github.com/spring-cloud/spring-cloud-contract/[Spring Cloud Contract Github Repository] +- https://github.com/spring-cloud-samples/spring-cloud-contract-samples/[Spring Cloud Contract Samples] +- https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html[Spring Cloud Contract Documentation] +- https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html/deprecated[Accurest Legacy Documentation] +- https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html/#spring-cloud-contract-stub-runner[Spring Cloud Contract Stub Runner Documentation] +- https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html/#stub-runner-for-messaging[Spring Cloud Contract Stub Runner Messaging Documentation] +- https://gitter.im/spring-cloud/spring-cloud-contract[Spring Cloud Contract Gitter] +- https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract-maven-plugin/[Spring Cloud Contract Maven Plugin]