:spring_version: current
:spring_boot_version: 2.1.4.RELEASE
:Controller: https://docs.spring.io/spring/docs/{spring_version}/javadoc-api/org/springframework/stereotype/Controller.html
:DispatcherServlet: https://docs.spring.io/spring/docs/{spring_version}/javadoc-api/org/springframework/web/servlet/DispatcherServlet.html
:SpringApplication: https://docs.spring.io/spring-boot/docs/{spring_boot_version}/api/org/springframework/boot/SpringApplication.html
:ResponseBody: https://docs.spring.io/spring/docs/{spring_version}/javadoc-api/org/springframework/web/bind/annotation/ResponseBody.html
:toc:
:icons: font
:source-highlighter: prettify
:project_id: gs-contract-rest
This guide walks you through the process of creating a Spring REST application with its contract stubs and consuming the contract within an other Spring application. https://cloud.spring.io/spring-cloud-contract[Spring Cloud Contract Project]
== What you'll build
You'll setup two micro services one providing its contract, and the other one consuming this contract to make sure that the integration to the contract provider service is aligned with the specifications. If in the future, the contract of the producer service changes, then the consumer service's tests fail catching the potential incompatibility.
== What you'll need
:java_version: 1.8
include::https://raw.githubusercontent.com/spring-guides/getting-started-macros/master/prereq_editor_jdk_buildtools.adoc[]
include::https://raw.githubusercontent.com/spring-guides/getting-started-macros/master/how_to_complete_this_guide.adoc[]
[[reveal-gradle]]
[.reveal-gradle]
== Build with Gradle
[[scratch]]
[.use-gradle]
== Build with Gradle
include::https://raw.githubusercontent.com/spring-guides/getting-started-macros/master/build_system_intro.adoc[]
include::https://raw.githubusercontent.com/spring-guides/getting-started-macros/master/create_directory_structure_hello.adoc[]
include::https://raw.githubusercontent.com/spring-guides/getting-started-macros/master/create_both_builds.adoc[]
`contract-rest-service/build.gradle`
// AsciiDoc source formatting doesn't support groovy, so using java instead
[source,java]
----
include::https://raw.githubusercontent.com/spring-guides/{project_id}/master/initial/contract-rest-service/build.gradle[]
----
`contract-rest-client/build.gradle`
// AsciiDoc source formatting doesn't support groovy, so using java instead
[source,java]
----
include::https://raw.githubusercontent.com/spring-guides/{project_id}/master/initial/contract-rest-client/build.gradle[]
----
include::https://raw.githubusercontent.com/spring-guides/getting-started-macros/master/spring-boot-gradle-plugin.adoc[]
[[reveal-maven]]
[.reveal-maven]
== Build with Maven
[[use-maven]]
[.use-maven]
== Build with Maven
include::https://raw.githubusercontent.com/spring-guides/getting-started-macros/master/build_system_intro_maven.adoc[]
include::https://raw.githubusercontent.com/spring-guides/getting-started-macros/master/create_directory_structure_hello.adoc[]
To get you started quickly, here are the complete configurations for the server and client applications:
`contract-rest-service/pom.xml`
[source,xml]
----
include::https://raw.githubusercontent.com/spring-guides/{project_id}/master/initial/contract-rest-service/pom.xml[]
----
`contract-rest-client/pom.xml`
[source,xml]
----
include::https://raw.githubusercontent.com/spring-guides/{project_id}/master/initial/contract-rest-client/pom.xml[]
----
include::https://raw.githubusercontent.com/spring-guides/getting-started-macros/master/spring-boot-maven-plugin.adoc[]
include::https://raw.githubusercontent.com/spring-guides/getting-started-macros/master/hide-show-sts.adoc[]
[[initial]]
== Create contract producer service
You'll first need to create the service which produces the contract. This is a regular Spring Boot application providing a very simple REST service. The rest service simply returns a `Person` object in JSON.
`contract-rest-service/src/main/java/hello/ContractRestServiceApplication.java`
[source,java]
----
include::complete/contract-rest-service/src/main/java/hello/ContractRestServiceApplication.java[]
----
=== Create the contract of the REST service
The contract of the REST service can be defined as a `.groovy` script. This contract specifies that if there is a `GET` request to url `/person/1`, sample data `id=1`, `name=foo` and `surname=bee` representing a `Person` entity will be returned in the response body of content-type `application/json` .
`contract-rest-service/src/test/resources/contracts/hello/find_person_by_id.groovy`
[source,java]
----
include::complete/contract-rest-service/src/test/resources/contracts/hello/find_person_by_id.groovy[]
----
At the `test` phase, automatic test classes will be created for the contract specified in the groovy file. The auto generated test java classes will extend the `hello.BaseClass`.
[source,xml]
----
<plugin>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
<version>${spring-cloud-contract.version}</version>
<extensions>true</extensions>
<configuration>
<baseClassForTests>hello.BaseClass</baseClassForTests>
</configuration>
</plugin>
----
`contract-rest-service/src/test/java/hello/BaseClass.java`
[source,java]
----
include::complete/contract-rest-service/src/test/java/hello/BaseClass.java[]
----
At this step, when the tests are executed, test results should be GREEN indicating that the REST controller is aligned with the contract and you have a fully functioning service.
==== Check the simple Person query business logic
Model class `Person.java`
`contract-rest-service/src/main/java/hello/Person.java`
[source,java]
----
include::complete/contract-rest-service/src/main/java/hello/Person.java[]
----
Service bean `PersonService.java` which just populates a few Person entity in memory and returns the one when asked.
`contract-rest-service/src/main/java/hello/PersonService.java`
[source,java]
----
include::complete/contract-rest-service/src/main/java/hello/PersonService.java[]
----
RestController bean `PersonRestController.java` which calls `PersonService` bean when a REST request is received for a person with the id.
`contract-rest-service/src/main/java/hello/PersonRestController.java`
[source,java]
----
include::complete/contract-rest-service/src/main/java/hello/PersonRestController.java[]
----
=== Test the contract-rest-service application
Run the `ContractRestServiceApplication.java` class as a Java Application or Spring Boot Application. The service should start at port `8000`.
Visit the service in the browser `http://localhost:8000/person/1`, `http://localhost:8000/person/2`, etc.
== Create contract consumer service
With the contract producer service ready, now we need to crate the client application which consumes the contract provided. This is a regular Spring Boot application providing a very simple REST service. The rest service simply returns a message with the queried Person's name, e.g. `Hello Anna`.
`contract-rest-client/src/main/java/hello/ContractRestClientApplication.java`
[source,java]
----
include::complete/contract-rest-client/src/main/java/hello/ContractRestClientApplication.java[]
----
=== Create the contract test
The contract provided by the producer should be consumed as a simple Spring test.
`contract-rest-client/src/test/java/hello/ContractRestClientApplicationTest.java`
[source,java]
----
include::complete/contract-rest-client/src/test/java/hello/ContractRestClientApplicationTest.java[]
----
This test class will load the stubs of the contract producer service and make sure that the integration to the service is aligned with the contract.
In case the communication is faulty between the consumer service's test and the producer's contract, tests will fail and the problem will need to be fixed before making a new change on production.
=== Test the contract-rest-client application
Run the `ContractRestClientApplication.java` class as a Java Application or Spring Boot Application. The service should start at port `9000`.
Visit the service in the browser `http://localhost:9000/message/1`, `http://localhost:9000/message/2`, etc.
== Summary
Congratulations! You've just used Spring to make your REST services declare their contract and consumer service be aligned with this contract.
== See Also
The following guides may also be helpful:
* https://spring.io/guides/gs/spring-boot/[Building an Application with Spring Boot]
* https://spring.io/guides/gs/multi-module/[Creating a Multi Module Project]
include::https://raw.githubusercontent.com/spring-guides/getting-started-macros/master/footer.adoc[]