SlideShare a Scribd company logo
1 of 191
Download to read offline
Documenting RESTful APIs with
Spring REST Docs
By Jenn Strater
@codeJENNerator
1
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Notes For Those Viewing These Slides Online
• Bulleted text like this indicates the key points mentioned on a previous slide.
They may not have been included in the official presentation.
• If this view does not support links, the links will work in the pdf. In speakerdeck,
you can click the ‘download pdf’ button at the right.
X
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Outline
• API Documentation Background
• Approaches to Documentation
• Considerations
2
• Test-Driven Documentation
• Spring REST Docs
• Examples
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Follow Along
https://speakerdeck.com/jlstrater/test-driven-docs-springone-2017
https://github.com/jlstrater/groovy-spring-boot-restdocs-example
https://github.com/ratpack/example-books
https://github.com/jlstrater/spring-restdocs-public-api-example
3
About Me
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Follow Along
https://speakerdeck.com/jlstrater/test-driven-docs-springone-2017
https://github.com/jlstrater/groovy-spring-boot-restdocs-example
https://github.com/ratpack/example-books
https://github.com/jlstrater/spring-restdocs-public-api-example
5
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
6
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
About Me
• Co-founder of Gr8Ladies and talk about women in the Groovy Community all
over the world
• Passionate about bring new people into the Groovy community through free
introductory workshops called Gr8Workshops.
• Senior Engineer at Zenjob as of June 2017. We’re hiring! zenjob.de/careers
• Spent the 2016-2017 academic year in Copenhagen working on OSS and
taking classes through a Fulbright Grant.
• Prior to the Fulbright Grant, I was a senior consultant at Object Partners, Inc. in
Minneapolis, MN, USA. My work with Spring REST Docs started on a project at
my client through them.
X
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Audience Background
• Creating RESTful APIs
• Spring Boot
• Grails
• Ratpack
7
• API Documentation
• Wiki Pages, Word Documents,
Confluence, etc
• Asciidoc / Asciidoctor
• Swagger / RAML
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
8
src: https://flic.kr/p/rehEf5
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
8
src: https://flic.kr/p/rehEf5
I hate writing documentation!*
Case Study
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
REST Maturity Model
10
src: http://martinfowler.com/articles/richardsonMaturityModel.html
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
REST Maturity Model
10
src: http://martinfowler.com/articles/richardsonMaturityModel.html
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
REST Maturity Model
• I’m not really a fan of the right vs wrong REST debate, but I like this
categorization of APIs.
• Most of our APIS were level one or two, but we wanted to have the flexibility to
use hypermedia
• Spring REST docs includes support for level 3 / hypermedia
• Swagger 2.0 did not support hypermedia. Swagger 3.0 (released end of July
2017) now does
X
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
11
Attribution: @Alvaro_Sanchez
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Monolith vs Microservices
As architecture evolves, many companies move from a central monolith to micro
services or maybe even gateways and multi-tiered architectures.
• For documentation, it was important to have:
• a consistent look and feel
• a way to show how the services can work together
X
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Central Information
12
Security
Http Verbs
Error
Handling
Http
Status
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Central Information
Central Information
• For example, security tokens, patterns for error messages, http verbs/status codes,
etc
• This information needs to be written out and defined once; not on every endpoint.
X
Document Design
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
14
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
15
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Central Information
Who’s seen this before? Of the people who have never used swagger before, how many
understand what this means? Even our CTO who is technical, didn’t want to spend time figuring
it out. Also, product teams.
This is a swagger ui example but the concept is not limited to Swagger. I have seen many
different APIs document in this way. It’s not just URI centric, but also very developer centric. No
matter whether you leave here choosing Swagger or Spring REST Docs, think about your users!
This is an example from Spring Rest Docs using Asciidoc.
Notice the very different way of organizing information on the second slide. Resource centric
document design organizes information by topic and includes urls in the examples only. The
information from generated solutions isn’t enough. We need the handwritten information too!
X
Available Tools
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
17
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
17
Definitions
Swagger (OpenAPI Specification)
RAML
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
17
Definitions
Swagger (OpenAPI Specification)
RAML
Documentation
AsciiDoc
Markdown
Wikis
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
17
Definitions
Swagger (OpenAPI Specification)
RAML
Documentation
AsciiDoc
Markdown
Wikis
Swagger UI
Swagger2Markup
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
17
Definitions
Swagger (OpenAPI Specification)
RAML
Testing
MockMVC
RestAssured
Documentation
AsciiDoc
Markdown
Wikis
Swagger UI
Swagger2Markup
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
17
Definitions
Swagger (OpenAPI Specification)
RAML
Testing
MockMVC
RestAssured
Documentation
AsciiDoc
Markdown
Wikis
Swagger UI
Swagger2Markup
AssertJ-
Swagger
Contract-First
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
17
Definitions
Swagger (OpenAPI Specification)
RAML
Testing
MockMVC
RestAssured
Documentation
AsciiDoc
Markdown
Wikis
Swagger UI
Swagger2Markup
Spring
REST
Docs
AssertJ-
Swagger
Contract-First
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
17
Definitions
Swagger (OpenAPI Specification)
RAML
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
18
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
18
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Swagger
Swagger is: — a lot of things
• At the core, it is a way to standardize and define HTTP APIs over RPC.
• It is very popular because of the many plugins built on top of it for things such
as generating client libraries, generating docs, and much more.
• In earlier versions, it did not support hypermedia. Documenting across micro
services was possible, but required a bit of setup. Depending on the library,
some central information is duplicated.
X
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Body Slide - Dark Background
All body text is Proxima Nova Regular
• Subhead (18pt)
• Level Two (18pt)
• Level Three (18pt)
• Level Four (18pt)
Use the “Decrease/Increase Indent” 

tools to change bullet levels
• Click on the Home ribbon, Paragraph tab
Line spacing is set in master slides
19
Automation
img src: https://flic.kr/p/eduUfU
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Body Slide - Dark Background
All body text is Proxima Nova Regular
• Subhead (18pt)
• Level Two (18pt)
• Level Three (18pt)
• Level Four (18pt)
Use the “Decrease/Increase Indent” 

tools to change bullet levels
• Click on the Home ribbon, Paragraph tab
Line spacing is set in master slides
20
img src: https://www.flickr.com/photos/
24874528@N04/17125924230
SpringFox
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
SpringFox
SpringFox:
• Generates a Swagger Specification from source
• Is very easy to setup (in simple cases)
• No OpenAPI Spec 3.0 support!
X
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Custom Swagger Specification
21
{
"swagger": "2.0",
"info": {
"version": "1",
"title": "My Service",
"contact": {
"name": "Company Name"
},
"license": {}
},
"host": "example.com",
"basepath": "/docs"
}
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Swagger UI
22
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
23
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
SpringFox UI approaches
• Use SpringFox library
• Copy static files and customize
X
Considerations
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Customization
25
img src: http://sergiodelamo.es/how-to-secure-your-grails-3-api-with-spring-security-rest-for-grails/
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Customization
• For any non-standard configuration, you may have to override the UI.
• As one example, we were adding custom headers for oauth jwt tokens. At the
time, it was not supported with springfox-ui.
X
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Object Mapping
26
img src: https://github.com/springfox/springfox/issues/281
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
27
https://github.com/swagger-api/swagger-core/issues/97
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Customization
• In Swagger/OpenAPI Spec 2.0, there was no hypermedia support.
• In OpenAPI Spec 3.0, there is some support for links
X
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
1 @Secured(‘ROLE_ALLOWED_TO_PERFORM_ACTION’)

2 @RequestMapping(value = '/v1/serviceName/actionName', method =
3 RequestMethod.POST)

4 @ApiOperation(value = '/actionName',

5 notes = 'Enables or disables setting via "1" or "0", respectively')

6 @ApiResponses(value = [

7 @ApiResponse(code = 200, response = CustomSettingResponse, message =
8 ‘Successful setting update'),

9 @ApiResponse(code = 400, response = ErrorResponse, message = 'Invalid
10 user input'),

11 @ApiResponse(code = 500, response = ErrorResponse, message = 'Unexpected
12 server error')

13 ])

14 CustomSettingResponse setSetting(@RequestBody CustomModel settingsValue) {

15 SaveSettingUpdateRequest request = new SaveSettingUpdateRequest (

16 settingsValue.fieldOne,

17 [new TransformedSetting(SettingEnum.POSSIBLE_ENUM_VALUE,
18 new Double(settingsValue.value))]

19 )

20 api.saveUpdatedSetting(request)

21 }
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
1 @Secured(‘ROLE_ALLOWED_TO_PERFORM_ACTION’)

2 @RequestMapping(value = '/v1/serviceName/actionName', method =
3 RequestMethod.POST)

4 @ApiOperation(value = '/actionName',

5 notes = 'Enables or disables setting via "1" or "0", respectively')

6 @ApiResponses(value = [

7 @ApiResponse(code = 200, response = CustomSettingResponse, message =
8 ‘Successful setting update'),

9 @ApiResponse(code = 400, response = ErrorResponse, message = 'Invalid
10 user input'),

11 @ApiResponse(code = 500, response = ErrorResponse, message = 'Unexpected
12 server error')

13 ])

14 CustomSettingResponse setSetting(@RequestBody CustomModel settingsValue) {

15 SaveSettingUpdateRequest request = new SaveSettingUpdateRequest (

16 settingsValue.fieldOne,

17 [new TransformedSetting(SettingEnum.POSSIBLE_ENUM_VALUE,
18 new Double(settingsValue.value))]

19 )

20 api.saveUpdatedSetting(request)

21 }
Annotation Hell
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
1 @Secured(‘ROLE_ALLOWED_TO_PERFORM_ACTION’)

2 @RequestMapping(value = '/v1/serviceName/actionName', method =
3 RequestMethod.POST)

4 @ApiOperation(value = '/actionName',

5 notes = 'Enables or disables setting via "1" or "0", respectively')

6 @ApiResponses(value = [

7 @ApiResponse(code = 200, response = CustomSettingResponse, message =
8 ‘Successful setting update'),

9 @ApiResponse(code = 400, response = ErrorResponse, message = 'Invalid
10 user input'),

11 @ApiResponse(code = 500, response = ErrorResponse, message = 'Unexpected
12 server error')

13 ])

14 CustomSettingResponse setSetting(@RequestBody CustomModel settingsValue) {

15 SaveSettingUpdateRequest request = new SaveSettingUpdateRequest (

16 settingsValue.fieldOne,

17 [new TransformedSetting(SettingEnum.POSSIBLE_ENUM_VALUE,
18 new Double(settingsValue.value))]

19 )

20 api.saveUpdatedSetting(request)

21 }
Annotation Hell
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
1 @Secured(‘ROLE_ALLOWED_TO_PERFORM_ACTION’)

2 @RequestMapping(value = '/v1/serviceName/actionName', method =
3 RequestMethod.POST)

4 @ApiOperation(value = '/actionName',

5 notes = 'Enables or disables setting via "1" or "0", respectively')

6 @ApiResponses(value = [

7 @ApiResponse(code = 200, response = CustomSettingResponse, message =
8 ‘Successful setting update'),

9 @ApiResponse(code = 400, response = ErrorResponse, message = 'Invalid
10 user input'),

11 @ApiResponse(code = 500, response = ErrorResponse, message = 'Unexpected
12 server error')

13 ])

14 CustomSettingResponse setSetting(@RequestBody CustomModel settingsValue) {

15 SaveSettingUpdateRequest request = new SaveSettingUpdateRequest (

16 settingsValue.fieldOne,

17 [new TransformedSetting(SettingEnum.POSSIBLE_ENUM_VALUE,
18 new Double(settingsValue.value))]

19 )

20 api.saveUpdatedSetting(request)

21 }
Annotation Hell
X
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
1 @Secured(‘ROLE_ALLOWED_TO_PERFORM_ACTION’)

2 @RequestMapping(value = '/v1/serviceName/actionName', method =
3 RequestMethod.POST)
4 CustomSettingResponse setSetting(@RequestBody CustomModel settingsValue) {

5 SaveSettingUpdateRequest request = new SaveSettingUpdateRequest (

6 settingsValue.fieldOne,

7 [new TransformedSetting(SettingEnum.POSSIBLE_ENUM_VALUE,
8 new Double(settingsValue.value))]

9 )

10 api.saveUpdatedSetting(request)

11 }
Swagger Advantages
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
31
“Try it” Button Alternatives
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
33
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
34
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Curl
-> curl 'http://localhost:8080/greetings' -i -H 'Content-Type: text/plain'
HTTP/1.1 200
X-Application-Context: application:8080
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date:Thu, 26 Jan 2017 13:28:19 GMT
[{"id":1,"message":"Hello"},{"id":2,"message":"Hi"},{"id":3,"message":"Hola"},{"id":4,"message":"Olá"},{"id":5,"message":"Hej"}]
35
Mix and Match
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
37
Swagger2Markup
https://github.com/Swagger2Markup/swagger2markup
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
img src: http://www.elvenspirit.com/elf/wp-content/uploads/2011/10/IMG_3013.jpg
FAIL!
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
img src: http://www.elvenspirit.com/elf/wp-content/uploads/2011/10/IMG_3013.jpg
FAIL!
AssertJ-Swagger
https://github.com/RobWin/assertj-swagger
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Spring Cloud Contract
39
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
40
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
40
Definitions
Swagger (OpenAPI Specification)
RAML
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
40
Definitions
Swagger (OpenAPI Specification)
RAML
Documentation
AsciiDoc
Markdown
Wikis
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
40
Definitions
Swagger (OpenAPI Specification)
RAML
Documentation
AsciiDoc
Markdown
Wikis
Swagger UI
Swagger2Markup
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
40
Definitions
Swagger (OpenAPI Specification)
RAML
Testing
MockMVC
RestAssured
Documentation
AsciiDoc
Markdown
Wikis
Swagger UI
Swagger2Markup
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
40
Definitions
Swagger (OpenAPI Specification)
RAML
Testing
MockMVC
RestAssured
Documentation
AsciiDoc
Markdown
Wikis
Swagger UI
Swagger2Markup
AssertJ-
Swagger
Contract-First
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
40
Definitions
Swagger (OpenAPI Specification)
RAML
Testing
MockMVC
RestAssured
Documentation
AsciiDoc
Markdown
Wikis
Swagger UI
Swagger2Markup
Spring
REST
Docs
AssertJ-
Swagger
Contract-First
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Spring
REST
Docs
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Test-Driven Development
Green
Red Refactor
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Test-Driven Documentation
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Test-Driven Documentation
Red
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Test-Driven Documentation
Red
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Test-Driven Documentation
Document
Red
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Test-Driven Documentation
Document
Red
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Test-Driven Documentation
Document Green
Red
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Test-Driven Documentation
Document Green
Red
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Test-Driven Documentation
Document Green
Red Refactor
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Test-Driven Documentation
Document Green
Red Refactor
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Winning Solution
https://flic.kr/p/5XiKxU
Winning Solution
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Winning Solution
• Ensures documentation matches implementation
• Encourages writing more tests
• Reduces duplication in docs and tests
• Removes annotations from source
X
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Spring REST Docs
44
https://flic.kr/p/5XiKxU
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Game Changers
45
https://flic.kr/p/9Tiv3U
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Game Changers
•Generated code snippets
•Tests fail when documentation is missing or out-of-date
•Rest APIs with Hypermedia
•Ratpack
•Dynamic routing doesn’t work with Swagger
X
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
About Spring REST Docs
46
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
About Spring REST Docs
projects.spring.io/spring-restdocs
46
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
About Spring REST Docs
projects.spring.io/spring-restdocs
@springrestdocs
46
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
About Spring REST Docs
projects.spring.io/spring-restdocs
@springrestdocs
https://github.com/spring-projects/spring-restdocs
46
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
About Spring REST Docs
•Start with reading the docs; The written docs are good!
•Overview
•Sponsored by Pivotal
•Project Lead - Andy Wilkinson
•Current Version - 2.0.0 released Nov 28
•Twitter Account and Official Logo
X
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
About Spring REST Docs
• Test-Driven Documentation with Spring REST Docs (Java and Spring Boot) - Spring
I/O 2016 Andy Wilkinson
• Writing comprehensive and guaranteed up-to-date REST API documentation -
SpringOne Platform 2016 Anders Evers
X
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Out of the Box
47
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Out of the Box
Testing Frameworks
• MockMVC
• RestAssured
• WebTestClient - NEW!
47
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Out of the Box
Testing Frameworks
• MockMVC
• RestAssured
• WebTestClient - NEW!
47
Build Tools
• Gradle
• Maven
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Out of the Box
48
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Out of the Box
Documentation Format
• AsciiDoc
• Markdown
48
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Out of the Box
Documentation Format
• AsciiDoc
• Markdown
48
Sample Projects
• Spring Boot
• Grails
• Slate
• TestNG
• And more!
Examples
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Groovier Spring REST Docs
• Spring Boot
• Ratpack
• Grails
50
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Groovier Spring REST Docs Example - Spring Boot
Groovy Spring Boot Project
+ Asciidoctor Gradle plugin
+ Spring REST Docs WebTestClient to Spock tests
+ Add to static assets during build and publish to GitHub pages
51
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
52
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
52
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
52
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Groovier Spring REST Docs Example - Spring Boot
• Start with lazybones spring boot app
• Add mock endpoints for example
https://github.com/jlstrater/groovy-spring-boot-restdocs-example
Updated to Spring Boot 2.0.0.M7 and thanks to: https://www.callicoder.com/
reactive-rest-apis-spring-webflux-reactive-mongo/
53
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
54
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Endpoints
@RestController
@RequestMapping('/greetings')
class GreetingsController {
@Autowired
GreetingRepository greetingsRepository
@PostMapping()
Mono<Greeting> createGreeting(@Valid @RequestBody Greeting greeting) {
return greetingsRepository.save(greeting)
}
@GetMapping()
Flux<Greeting> listAllGreetings() {
return greetingsRepository.findAll()
}
@GetMapping('/{id}')
Mono<Greeting> getGreetingById(@PathVariable(value = 'id') String greetingId) {
greetingsRepository.findById(greetingId)
}
}
55
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Endpoints
@RestController
@RequestMapping('/greetings')
class GreetingsController {
@Autowired
GreetingRepository greetingsRepository
@PostMapping()
Mono<Greeting> createGreeting(@Valid @RequestBody Greeting greeting) {
return greetingsRepository.save(greeting)
}
@GetMapping()
Flux<Greeting> listAllGreetings() {
return greetingsRepository.findAll()
}
@GetMapping('/{id}')
Mono<Greeting> getGreetingById(@PathVariable(value = 'id') String greetingId) {
greetingsRepository.findById(greetingId)
}
}
55
Create a new Greeting
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Endpoints
@RestController
@RequestMapping('/greetings')
class GreetingsController {
@Autowired
GreetingRepository greetingsRepository
@PostMapping()
Mono<Greeting> createGreeting(@Valid @RequestBody Greeting greeting) {
return greetingsRepository.save(greeting)
}
@GetMapping()
Flux<Greeting> listAllGreetings() {
return greetingsRepository.findAll()
}
@GetMapping('/{id}')
Mono<Greeting> getGreetingById(@PathVariable(value = 'id') String greetingId) {
greetingsRepository.findById(greetingId)
}
}
55
Create a new Greeting
List all greetings
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Endpoints
@RestController
@RequestMapping('/greetings')
class GreetingsController {
@Autowired
GreetingRepository greetingsRepository
@PostMapping()
Mono<Greeting> createGreeting(@Valid @RequestBody Greeting greeting) {
return greetingsRepository.save(greeting)
}
@GetMapping()
Flux<Greeting> listAllGreetings() {
return greetingsRepository.findAll()
}
@GetMapping('/{id}')
Mono<Greeting> getGreetingById(@PathVariable(value = 'id') String greetingId) {
greetingsRepository.findById(greetingId)
}
}
55
Create a new Greeting
List all greetings
Get a greeting by id
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
56
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
56
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
AsciiDoc
[introduction]
= Introduction
The Example API is a RESTful web service that shows how Spring REST docs works.
[[overview-http-verbs]]
== HTTP verbs
The Example API tries to adhere as closely as possible to standard HTTP and REST conventions in its
use of HTTP verbs.
|===
| Verb | Usage
| `GET`
| Used to retrieve a resource
| `POST`
| Used to create a new resource
| `PUT`
| Used to update an existing resource, overwrites all fields
57
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Asciidoctor Gradle Plugin
58
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
AsciiDoc Gradle Configuration
apply plugin: 'org.asciidoctor.convert'
asciidoctor {
backends 'html5'
attributes 'source-highlighter' : 'prettify',
'imagesdir':'images',
'toc':'left',
'icons': 'font',
'setanchors':'true',
'idprefix':'',
'idseparator':'-',
'docinfo1':'true',
}
59
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
60
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
60
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
62
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
62
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Project Reactor and the WebTestClient
63
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Setup
@CompileStatic
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class BaseControllerSpec extends Specification {
@Autowired
ApplicationContext context
protected WebTestClient webTestClient
void setup() {
this.webTestClient = WebTestClient.bindToApplicationContext(this.context)
.configureClient()
.baseUrl('/greetings')
.build()
}
}
64
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Setup
@CompileStatic
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class BaseControllerSpec extends Specification {
@Autowired
ApplicationContext context
protected WebTestClient webTestClient
void setup() {
this.webTestClient = WebTestClient.bindToApplicationContext(this.context)
.configureClient()
.baseUrl('/greetings')
.build()
}
}
64
If context is null,
remember to use
spock-spring!!
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
WebTestClient Call and Assertions
this.webTestClient.post().uri('/')
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromObject('{"message": "Hello SpringOne Platform!"}'))
.exchange()
.expectStatus().isOk()
.expectBody()
.jsonPath('$.id').isNotEmpty()
.jsonPath('$.message').isEqualTo('Hello SpringOne Platform!')
65
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
66
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
66
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Spring REST Docs Gradle Configuration
dependencies {
…
testCompile "org.springframework.restdocs:spring-restdocs-webtestclient:${springRestDocsVersion}"
asciidoctor "org.springframework.restdocs:spring-restdocs-asciidoctor:${springRestDocsVersion}"
}
ext {
snippetsDir = file('build/generated-snippets')
}
test {
outputs.dir "$projectDir/src/main/resources/public"
}
asciidoctor {
dependsOn test
inputs.dir snippetsDir
}
build {
dependsOn asciidoctor
}
ext['spring-restdocs.version'] = springRestDocsVersion
67
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Spring REST Docs with WebTestClient (setup)
@CompileStatic
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class BaseControllerSpec extends Specification {
@Rule
JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation()
@Autowired
ApplicationContext context
protected WebTestClient webTestClient
void setup() {
this.webTestClient = WebTestClient.bindToApplicationContext(this.context)
.configureClient()
.baseUrl('/greetings')
.filter(documentationConfiguration(restDocumentation))
.build()
}
}
68
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Spring REST Docs with WebTestClient (setup)
@CompileStatic
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class BaseControllerSpec extends Specification {
@Rule
JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation()
@Autowired
ApplicationContext context
protected WebTestClient webTestClient
void setup() {
this.webTestClient = WebTestClient.bindToApplicationContext(this.context)
.configureClient()
.baseUrl('/greetings')
.filter(documentationConfiguration(restDocumentation))
.build()
}
}
68
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Spring REST Docs with WebTestClient (setup)
@CompileStatic
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class BaseControllerSpec extends Specification {
@Rule
JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation()
@Autowired
ApplicationContext context
protected WebTestClient webTestClient
void setup() {
this.webTestClient = WebTestClient.bindToApplicationContext(this.context)
.configureClient()
.baseUrl('/greetings')
.filter(documentationConfiguration(restDocumentation))
.build()
}
}
68
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Spring REST Docs with WebTestClient (tests)
void 'test and document creating a greeting with a custom name'() {
expect:
this.webTestClient.post().uri('/')
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromObject('{"message": "Hello SpringOne Platform!"}'))
.exchange()
.expectStatus().isOk()
.expectBody()
.jsonPath('$.id').isNotEmpty()
.jsonPath('$.message').isEqualTo('Hello SpringOne Platform!')
.consumeWith(document('greetings-post-example',
preprocessRequest(prettyPrint()),
requestFields(
fieldWithPath('message').type(JsonFieldType.STRING)
.description("The greeting's message"))))
}`
69
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Spring REST Docs with WebTestClient (tests)
void 'test and document creating a greeting with a custom name'() {
expect:
this.webTestClient.post().uri('/')
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromObject('{"message": "Hello SpringOne Platform!"}'))
.exchange()
.expectStatus().isOk()
.expectBody()
.jsonPath('$.id').isNotEmpty()
.jsonPath('$.message').isEqualTo('Hello SpringOne Platform!')
.consumeWith(document('greetings-post-example',
preprocessRequest(prettyPrint()),
requestFields(
fieldWithPath('message').type(JsonFieldType.STRING)
.description("The greeting's message"))))
}`
69
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Spring REST Docs with WebTestClient (tests)
void 'test and document get of a list of greetings'() {
expect:
this.webTestClient.get().uri('/').accept(MediaType.APPLICATION_JSON)
.exchange()
.expectStatus().isOk()
.expectBody()
.consumeWith(document('greetings-list-example',
preprocessResponse(prettyPrint()),
responseFields(greetingList)))
}
FieldDescriptor[] greetingList = new FieldDescriptor().with {
[fieldWithPath('[].id').type(JsonFieldType.STRING).optional()
.description("The greeting's id"),
fieldWithPath('[].message').type(JsonFieldType.STRING)
.description("The greeting's message")]
}
70
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Spring REST Docs with WebTestClient (tests)
void 'test and document get of a list of greetings'() {
expect:
this.webTestClient.get().uri('/').accept(MediaType.APPLICATION_JSON)
.exchange()
.expectStatus().isOk()
.expectBody()
.consumeWith(document('greetings-list-example',
preprocessResponse(prettyPrint()),
responseFields(greetingList)))
}
FieldDescriptor[] greetingList = new FieldDescriptor().with {
[fieldWithPath('[].id').type(JsonFieldType.STRING).optional()
.description("The greeting's id"),
fieldWithPath('[].message').type(JsonFieldType.STRING)
.description("The greeting's message")]
}
70
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Spring REST Docs with WebTestClient (tests)
void 'test and document get of a list of greetings'() {
expect:
this.webTestClient.get().uri('/').accept(MediaType.APPLICATION_JSON)
.exchange()
.expectStatus().isOk()
.expectBody()
.consumeWith(document('greetings-list-example',
preprocessResponse(prettyPrint()),
responseFields(greetingList)))
}
FieldDescriptor[] greetingList = new FieldDescriptor().with {
[fieldWithPath('[].id').type(JsonFieldType.STRING).optional()
.description("The greeting's id"),
fieldWithPath('[].message').type(JsonFieldType.STRING)
.description("The greeting's message")]
}
70
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Error Messages
71
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Error Messages
71
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Error Messages
71
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Error Messages
71
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Error Messages
71
Special Use Case
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/


+@WebMvcTest(controllers = GreetingsController)

+@AutoConfigureRestDocs(

+ outputDir = "build/generated-snippets",

+ uriHost = “api.example.com”,

+ uriPort = 8080

)
class BaseControllerSpec extends Specification {


// @Rule

// JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation('src/docs/generated-snippets')



+ @Autowired

protected MockMvc mockMvc

//

// @Autowired

// private WebApplicationContext context

//

// void setup() {

// this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)

// .apply(documentationConfiguration(this.restDocumentation))

// .build()

// }
}
73
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
74
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
74
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Generated Snippets
75
By Default When Specified
curl-request.adoc response-fields.adoc
http-request.adoc request-parameters.adoc
httpie-request.adoc request-parts.adoc
http-response.adoc path-parameters.adoc
request body request-parts.adoc
response body
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
http-request.adoc
[source,http,options="nowrap"]
----
POST /greetings/ HTTP/1.1
Content-Type: application/json
Accept: application/json
Host: localhost:8080
Content-Length: 45
{
"message" : "Hello SpringOne Platform!"
}
----
76
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
response-fields.adoc
|===
|Path|Type|Description
|`id`
|`String`
|The greeting's id
|`message`
|`String`
|The greeting's message
|===
77
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
78
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
79
+
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
79
+
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Adding The Snippets
[[overview-errors]]
== Errors
Whenever an error response (status code >= 400) is returned, the body will contain a JSON
object
that describes the problem. The error object has the following structure:
include::{snippets}/error-example/response-fields.adoc[]
For example, a request that attempts to delete on the greetings endpoint will produce a
`405 Method Not Allowed` response:
operation::error-example[snippets='curl-request,http-request,http-response']
[[resources]]
= Resources
include::resources/greetings.adoc[]
80
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Adding The Snippets
[[overview-errors]]
== Errors
Whenever an error response (status code >= 400) is returned, the body will contain a JSON
object
that describes the problem. The error object has the following structure:
include::{snippets}/error-example/response-fields.adoc[]
For example, a request that attempts to delete on the greetings endpoint will produce a
`405 Method Not Allowed` response:
operation::error-example[snippets='curl-request,http-request,http-response']
[[resources]]
= Resources
include::resources/greetings.adoc[]
80
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Adding The Snippets
[[overview-errors]]
== Errors
Whenever an error response (status code >= 400) is returned, the body will contain a JSON
object
that describes the problem. The error object has the following structure:
include::{snippets}/error-example/response-fields.adoc[]
For example, a request that attempts to delete on the greetings endpoint will produce a
`405 Method Not Allowed` response:
operation::error-example[snippets='curl-request,http-request,http-response']
[[resources]]
= Resources
include::resources/greetings.adoc[]
80
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Adding The Snippets
[[overview-errors]]
== Errors
Whenever an error response (status code >= 400) is returned, the body will contain a JSON
object
that describes the problem. The error object has the following structure:
include::{snippets}/error-example/response-fields.adoc[]
For example, a request that attempts to delete on the greetings endpoint will produce a
`405 Method Not Allowed` response:
operation::error-example[snippets='curl-request,http-request,http-response']
[[resources]]
= Resources
include::resources/greetings.adoc[]
80
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
81
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
81
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Building the docs
.
82
src/docs/
asciidoc
index.adoc
build/asciidoc/
html5
index.html
.gradlew asciidoctor
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Publishing Strategies
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Publishing Strategies
• Hook in asciidoctor with the gradle build task
• Run the asciidoctor test separately (but make sure to run AFTER the tests)
• Send to static resources directory in the current app or send to a remote site (for
example Github Pages
X
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
85
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
85
http://api.example.com/docs
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
publish.gradle
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'org.ajoberstar:gradle-git:1.1.0'
}
}
apply plugin: 'org.ajoberstar.github-pages'
githubPages {
repoUri = 'git@github.com:jlstrater/groovy-spring-boot-restdocs-example.git'
pages {
from(file('build/asciidoc/html5'))
}
}
86
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
publish.gradle
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'org.ajoberstar:gradle-git:1.1.0'
}
}
apply plugin: 'org.ajoberstar.github-pages'
githubPages {
repoUri = 'git@github.com:jlstrater/groovy-spring-boot-restdocs-example.git'
pages {
from(file('build/asciidoc/html5'))
}
}
86
If you use this method,
remember to deploy docs at the
same time as the project!
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
87
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
87
http://jlstrater.github.io/groovy-
spring-boot-restdocs-example
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
87
http://jlstrater.github.io/groovy-
spring-boot-restdocs-example
./gradlew publish
Support for Rest-Assured
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Groovier Spring REST Docs
• Ratpack
• Grails
89
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Groovier Spring REST Docs Example - Ratpack
• Ratpack Example Project
• https://github.com/ratpack/example-books
• Spring RESTdocs RestAssured
• https://github.com/ratpack/example-books/pull/25
92
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Groovier Spring REST Docs Example - Ratpack
path(":isbn") {

def isbn = pathTokens["isbn"]



byMethod {

get {

bookService.find(isbn).

single().

subscribe { Book book ->

if (book == null) {

clientError 404

} else {

render book

}

}

}
...
}

}
93
byMethod {

get {

bookService.all().

toList().

subscribe { List<Book> books ->

render json(books)

}

}

post {

parse(jsonNode()).

observe().

flatMap { input ->

bookService.insert(

input.get("isbn").asText(),

input.get("quantity").asLong(),

input.get("price").asDouble()

)

}.

single().

flatMap {

bookService.find(it)

}.

single().

subscribe { Book createdBook ->

render createdBook

}

}
}
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Groovier Spring REST Docs Example - Ratpack
path(":isbn") {

def isbn = pathTokens["isbn"]



byMethod {

get {

bookService.find(isbn).

single().

subscribe { Book book ->

if (book == null) {

clientError 404

} else {

render book

}

}

}
...
}

}
93
byMethod {

get {

bookService.all().

toList().

subscribe { List<Book> books ->

render json(books)

}

}

post {

parse(jsonNode()).

observe().

flatMap { input ->

bookService.insert(

input.get("isbn").asText(),

input.get("quantity").asLong(),

input.get("price").asDouble()

)

}.

single().

flatMap {

bookService.find(it)

}.

single().

subscribe { Book createdBook ->

render createdBook

}

}
}
Get a book by ISBN
/api/books/1932394842
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Groovier Spring REST Docs Example - Ratpack
path(":isbn") {

def isbn = pathTokens["isbn"]



byMethod {

get {

bookService.find(isbn).

single().

subscribe { Book book ->

if (book == null) {

clientError 404

} else {

render book

}

}

}
...
}

}
93
byMethod {

get {

bookService.all().

toList().

subscribe { List<Book> books ->

render json(books)

}

}

post {

parse(jsonNode()).

observe().

flatMap { input ->

bookService.insert(

input.get("isbn").asText(),

input.get("quantity").asLong(),

input.get("price").asDouble()

)

}.

single().

flatMap {

bookService.find(it)

}.

single().

subscribe { Book createdBook ->

render createdBook

}

}
}
Get a book by ISBN
/api/books/1932394842
Get all books
/api/books
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Groovier Spring REST Docs Example - Ratpack
path(":isbn") {

def isbn = pathTokens["isbn"]



byMethod {

get {

bookService.find(isbn).

single().

subscribe { Book book ->

if (book == null) {

clientError 404

} else {

render book

}

}

}
...
}

}
93
byMethod {

get {

bookService.all().

toList().

subscribe { List<Book> books ->

render json(books)

}

}

post {

parse(jsonNode()).

observe().

flatMap { input ->

bookService.insert(

input.get("isbn").asText(),

input.get("quantity").asLong(),

input.get("price").asDouble()

)

}.

single().

flatMap {

bookService.find(it)

}.

single().

subscribe { Book createdBook ->

render createdBook

}

}
}
Get a book by ISBN
/api/books/1932394842
Get all books
/api/books
Post to create a new book
/api/books
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
94
https://github.com/jayway/rest-assured
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
abstract class BaseDocumentationSpec extends Specification {



@Shared

ApplicationUnderTest aut = new ExampleBooksApplicationUnderTest()



@Rule

JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation()



protected RequestSpecification documentationSpec



void setup() {

this.documentationSpec = new RequestSpecBuilder()

.addFilter(documentationConfiguration(restDocumentation))

.build()

}

}
95
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
96
Documenting Public APIs
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Blog Post
https://jennstrater.blogspot.com/2017/01/using-spring-rest-docs-to-document.html
98
Outcomes
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Outcomes
• Made it to production! :)
• Team was happy with Spring REST Docs
• Other dev teams like to see the examples
X
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Read the Docs for More On…
• Adding Security and Headers
• Documenting Constraints
• Hypermedia Support
• XML Support
• Using Markdown instead of Asciidoc
• Third Party Extensions for WireMock, Jersey, Spring Cloud Contracts, AutoRestDocs
100
Conclusion
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
102
Definitions
Swagger (OpenAPI Specification)
RAML
Testing
MockMVC
RestAssured
Documentation
AsciiDoc
Markdown
Wikis
Swagger UI
Swagger2Markup
Spring
REST
Docs
AssertJ-
Swagger
Contract-First
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Conclusion
• API documentation is complex
• Choosing the right tool for the job not just about the easiest one to setup
• Spring REST Docs is a promising tool to enforce good testing and documentation
practices without muddying source code.
• I still hate writing boilerplate documentation, but at least it’s a little less painful now.
X
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Next Steps
• Join the Groovy Community on Slack groovycommunity.com
• Join #spring-restdocs on gitter https://gitter.im/spring-projects/spring-restdocs
103
Learn More. Stay Connected.
https://speakerdeck.com/jlstrater/test-driven-docs-springone-2017
Follow on Twitter @codeJENNerator
104
#springone@s1p

More Related Content

What's hot

Git Merge and Rebase | Git Merge vs Rebase | Which One to Choose? | Devops Tr...
Git Merge and Rebase | Git Merge vs Rebase | Which One to Choose? | Devops Tr...Git Merge and Rebase | Git Merge vs Rebase | Which One to Choose? | Devops Tr...
Git Merge and Rebase | Git Merge vs Rebase | Which One to Choose? | Devops Tr...Edureka!
 
MicroProfile: Optimizing Java EE for a Microservices Architecture
MicroProfile: Optimizing Java EE for a Microservices ArchitectureMicroProfile: Optimizing Java EE for a Microservices Architecture
MicroProfile: Optimizing Java EE for a Microservices Architecturejclingan
 
The API Lifecycle Series: Exploring Design-First and Code-First Approaches to...
The API Lifecycle Series: Exploring Design-First and Code-First Approaches to...The API Lifecycle Series: Exploring Design-First and Code-First Approaches to...
The API Lifecycle Series: Exploring Design-First and Code-First Approaches to...SmartBear
 
MicroProfile Devoxx.us
MicroProfile Devoxx.usMicroProfile Devoxx.us
MicroProfile Devoxx.usjclingan
 
Testing strategies and best practices using MUnit
Testing strategies and best practices using MUnitTesting strategies and best practices using MUnit
Testing strategies and best practices using MUnitJimmy Attia
 
Nexus Pro Customer Survey Findings
Nexus Pro Customer Survey FindingsNexus Pro Customer Survey Findings
Nexus Pro Customer Survey FindingsSonatype
 
MuleSoft CloudHub API Versioning
MuleSoft CloudHub API VersioningMuleSoft CloudHub API Versioning
MuleSoft CloudHub API VersioningPatryk Bandurski
 
The API Lifecycle Series: Evolving API Development and Testing from Open Sour...
The API Lifecycle Series: Evolving API Development and Testing from Open Sour...The API Lifecycle Series: Evolving API Development and Testing from Open Sour...
The API Lifecycle Series: Evolving API Development and Testing from Open Sour...SmartBear
 
Introducing DevOps
Introducing DevOpsIntroducing DevOps
Introducing DevOpsMoataz Nabil
 
CICD Pipeline - AWS Azure
CICD Pipeline - AWS AzureCICD Pipeline - AWS Azure
CICD Pipeline - AWS AzureRatan Das
 
OpenAPI v.Next - Events, Alternative Schemas & the Road Ahead
OpenAPI v.Next - Events, Alternative Schemas & the Road AheadOpenAPI v.Next - Events, Alternative Schemas & the Road Ahead
OpenAPI v.Next - Events, Alternative Schemas & the Road AheadTed Epstein
 
Enabing DevOps in an SDN World
Enabing DevOps in an SDN WorldEnabing DevOps in an SDN World
Enabing DevOps in an SDN WorldCisco DevNet
 
Java cloud service 발표자료
Java cloud service 발표자료Java cloud service 발표자료
Java cloud service 발표자료Mee Nam Lee
 
不只自動化而且更敏捷的Android開發工具 gradle
不只自動化而且更敏捷的Android開發工具 gradle不只自動化而且更敏捷的Android開發工具 gradle
不只自動化而且更敏捷的Android開發工具 gradlesam chiu
 
Laravel CI / CD in Azure Web Apps - Global Azure Bootcamp Jakarta
Laravel CI / CD in Azure Web Apps -  Global Azure Bootcamp JakartaLaravel CI / CD in Azure Web Apps -  Global Azure Bootcamp Jakarta
Laravel CI / CD in Azure Web Apps - Global Azure Bootcamp JakartaBilly Riantono
 

What's hot (20)

Git Merge and Rebase | Git Merge vs Rebase | Which One to Choose? | Devops Tr...
Git Merge and Rebase | Git Merge vs Rebase | Which One to Choose? | Devops Tr...Git Merge and Rebase | Git Merge vs Rebase | Which One to Choose? | Devops Tr...
Git Merge and Rebase | Git Merge vs Rebase | Which One to Choose? | Devops Tr...
 
MicroProfile: Optimizing Java EE for a Microservices Architecture
MicroProfile: Optimizing Java EE for a Microservices ArchitectureMicroProfile: Optimizing Java EE for a Microservices Architecture
MicroProfile: Optimizing Java EE for a Microservices Architecture
 
The API Lifecycle Series: Exploring Design-First and Code-First Approaches to...
The API Lifecycle Series: Exploring Design-First and Code-First Approaches to...The API Lifecycle Series: Exploring Design-First and Code-First Approaches to...
The API Lifecycle Series: Exploring Design-First and Code-First Approaches to...
 
MicroProfile Devoxx.us
MicroProfile Devoxx.usMicroProfile Devoxx.us
MicroProfile Devoxx.us
 
Testing strategies and best practices using MUnit
Testing strategies and best practices using MUnitTesting strategies and best practices using MUnit
Testing strategies and best practices using MUnit
 
Nexus Pro Customer Survey Findings
Nexus Pro Customer Survey FindingsNexus Pro Customer Survey Findings
Nexus Pro Customer Survey Findings
 
MuleSoft CloudHub API Versioning
MuleSoft CloudHub API VersioningMuleSoft CloudHub API Versioning
MuleSoft CloudHub API Versioning
 
The API Lifecycle Series: Evolving API Development and Testing from Open Sour...
The API Lifecycle Series: Evolving API Development and Testing from Open Sour...The API Lifecycle Series: Evolving API Development and Testing from Open Sour...
The API Lifecycle Series: Evolving API Development and Testing from Open Sour...
 
Introducing DevOps
Introducing DevOpsIntroducing DevOps
Introducing DevOps
 
CICD Pipeline - AWS Azure
CICD Pipeline - AWS AzureCICD Pipeline - AWS Azure
CICD Pipeline - AWS Azure
 
OpenAPI v.Next - Events, Alternative Schemas & the Road Ahead
OpenAPI v.Next - Events, Alternative Schemas & the Road AheadOpenAPI v.Next - Events, Alternative Schemas & the Road Ahead
OpenAPI v.Next - Events, Alternative Schemas & the Road Ahead
 
Enabing DevOps in an SDN World
Enabing DevOps in an SDN WorldEnabing DevOps in an SDN World
Enabing DevOps in an SDN World
 
Docker introduction
Docker introductionDocker introduction
Docker introduction
 
How to Build a DevOps Toolchain
How to Build a DevOps ToolchainHow to Build a DevOps Toolchain
How to Build a DevOps Toolchain
 
Java cloud service 발표자료
Java cloud service 발표자료Java cloud service 발표자료
Java cloud service 발표자료
 
Devops and git basics
Devops and git basicsDevops and git basics
Devops and git basics
 
不只自動化而且更敏捷的Android開發工具 gradle
不只自動化而且更敏捷的Android開發工具 gradle不只自動化而且更敏捷的Android開發工具 gradle
不只自動化而且更敏捷的Android開發工具 gradle
 
Laravel CI / CD in Azure Web Apps - Global Azure Bootcamp Jakarta
Laravel CI / CD in Azure Web Apps -  Global Azure Bootcamp JakartaLaravel CI / CD in Azure Web Apps -  Global Azure Bootcamp Jakarta
Laravel CI / CD in Azure Web Apps - Global Azure Bootcamp Jakarta
 
From Continuous Integration to DevOps
From Continuous Integration to DevOpsFrom Continuous Integration to DevOps
From Continuous Integration to DevOps
 
Leveling Up Deployment Infrastructure
Leveling Up Deployment InfrastructureLeveling Up Deployment Infrastructure
Leveling Up Deployment Infrastructure
 

Similar to Documenting RESTful APIs with Spring REST Docs

New in Spring Framework 5.0: Functional Web Framework
New in Spring Framework 5.0: Functional Web FrameworkNew in Spring Framework 5.0: Functional Web Framework
New in Spring Framework 5.0: Functional Web FrameworkVMware Tanzu
 
SpringOnePlatform2017 recap
SpringOnePlatform2017 recapSpringOnePlatform2017 recap
SpringOnePlatform2017 recapminseok kim
 
Migrating to Angular 4 for Spring Developers
Migrating to Angular 4 for Spring Developers Migrating to Angular 4 for Spring Developers
Migrating to Angular 4 for Spring Developers VMware Tanzu
 
Migrating to Angular 5 for Spring Developers
Migrating to Angular 5 for Spring DevelopersMigrating to Angular 5 for Spring Developers
Migrating to Angular 5 for Spring DevelopersGunnar Hillert
 
Intro To Reactive Programming
Intro To Reactive ProgrammingIntro To Reactive Programming
Intro To Reactive ProgrammingRossen Stoyanchev
 
Intro to Reactive Programming
Intro to Reactive ProgrammingIntro to Reactive Programming
Intro to Reactive ProgrammingStéphane Maldini
 
Latency analysis for your microservices using Spring Cloud & Zipkin
Latency analysis for your microservices using Spring Cloud & ZipkinLatency analysis for your microservices using Spring Cloud & Zipkin
Latency analysis for your microservices using Spring Cloud & ZipkinVMware Tanzu
 
Cloud-Native Streaming and Event-Driven Microservices
Cloud-Native Streaming and Event-Driven MicroservicesCloud-Native Streaming and Event-Driven Microservices
Cloud-Native Streaming and Event-Driven MicroservicesVMware Tanzu
 
In the workshop with GCP, Home Depot & Cloud Foundry
In the workshop with GCP, Home Depot & Cloud FoundryIn the workshop with GCP, Home Depot & Cloud Foundry
In the workshop with GCP, Home Depot & Cloud FoundryChristopher Grant
 
Resource Handling in Spring MVC 4.1
Resource Handling in Spring MVC 4.1Resource Handling in Spring MVC 4.1
Resource Handling in Spring MVC 4.1Rossen Stoyanchev
 
How to Build More Secure Service Brokers
How to Build More Secure Service BrokersHow to Build More Secure Service Brokers
How to Build More Secure Service BrokersVMware Tanzu
 
Implementing microservices tracing with spring cloud and zipkin (spring one)
Implementing microservices tracing with spring cloud and zipkin (spring one)Implementing microservices tracing with spring cloud and zipkin (spring one)
Implementing microservices tracing with spring cloud and zipkin (spring one)Reshmi Krishna
 
Continuous Delivery for Microservice Architectures with Concourse & Cloud Fou...
Continuous Delivery for Microservice Architectures with Concourse & Cloud Fou...Continuous Delivery for Microservice Architectures with Concourse & Cloud Fou...
Continuous Delivery for Microservice Architectures with Concourse & Cloud Fou...VMware Tanzu
 
Who Does What? Mapping Cloud Foundry Activities and Entitlements to IT Roles
Who Does What? Mapping Cloud Foundry Activities and Entitlements to IT RolesWho Does What? Mapping Cloud Foundry Activities and Entitlements to IT Roles
Who Does What? Mapping Cloud Foundry Activities and Entitlements to IT RolesVMware Tanzu
 
Building a Secure App with Google Polymer and Java / Spring
Building a Secure App with Google Polymer and Java / SpringBuilding a Secure App with Google Polymer and Java / Spring
Building a Secure App with Google Polymer and Java / Springsdeeg
 
Developing Real-Time Data Pipelines with Apache Kafka
Developing Real-Time Data Pipelines with Apache KafkaDeveloping Real-Time Data Pipelines with Apache Kafka
Developing Real-Time Data Pipelines with Apache KafkaJoe Stein
 
The Beginner’s Guide To Spring Cloud
The Beginner’s Guide To Spring CloudThe Beginner’s Guide To Spring Cloud
The Beginner’s Guide To Spring CloudVMware Tanzu
 
Managing the Complexity of Microservices Deployments
Managing the Complexity of Microservices DeploymentsManaging the Complexity of Microservices Deployments
Managing the Complexity of Microservices DeploymentsVMware Tanzu
 
IO State In Distributed API Architecture
IO State In Distributed API ArchitectureIO State In Distributed API Architecture
IO State In Distributed API ArchitectureOwen Rubel
 
Lattice: A Cloud-Native Platform for Your Spring Applications
Lattice: A Cloud-Native Platform for Your Spring ApplicationsLattice: A Cloud-Native Platform for Your Spring Applications
Lattice: A Cloud-Native Platform for Your Spring ApplicationsMatt Stine
 

Similar to Documenting RESTful APIs with Spring REST Docs (20)

New in Spring Framework 5.0: Functional Web Framework
New in Spring Framework 5.0: Functional Web FrameworkNew in Spring Framework 5.0: Functional Web Framework
New in Spring Framework 5.0: Functional Web Framework
 
SpringOnePlatform2017 recap
SpringOnePlatform2017 recapSpringOnePlatform2017 recap
SpringOnePlatform2017 recap
 
Migrating to Angular 4 for Spring Developers
Migrating to Angular 4 for Spring Developers Migrating to Angular 4 for Spring Developers
Migrating to Angular 4 for Spring Developers
 
Migrating to Angular 5 for Spring Developers
Migrating to Angular 5 for Spring DevelopersMigrating to Angular 5 for Spring Developers
Migrating to Angular 5 for Spring Developers
 
Intro To Reactive Programming
Intro To Reactive ProgrammingIntro To Reactive Programming
Intro To Reactive Programming
 
Intro to Reactive Programming
Intro to Reactive ProgrammingIntro to Reactive Programming
Intro to Reactive Programming
 
Latency analysis for your microservices using Spring Cloud & Zipkin
Latency analysis for your microservices using Spring Cloud & ZipkinLatency analysis for your microservices using Spring Cloud & Zipkin
Latency analysis for your microservices using Spring Cloud & Zipkin
 
Cloud-Native Streaming and Event-Driven Microservices
Cloud-Native Streaming and Event-Driven MicroservicesCloud-Native Streaming and Event-Driven Microservices
Cloud-Native Streaming and Event-Driven Microservices
 
In the workshop with GCP, Home Depot & Cloud Foundry
In the workshop with GCP, Home Depot & Cloud FoundryIn the workshop with GCP, Home Depot & Cloud Foundry
In the workshop with GCP, Home Depot & Cloud Foundry
 
Resource Handling in Spring MVC 4.1
Resource Handling in Spring MVC 4.1Resource Handling in Spring MVC 4.1
Resource Handling in Spring MVC 4.1
 
How to Build More Secure Service Brokers
How to Build More Secure Service BrokersHow to Build More Secure Service Brokers
How to Build More Secure Service Brokers
 
Implementing microservices tracing with spring cloud and zipkin (spring one)
Implementing microservices tracing with spring cloud and zipkin (spring one)Implementing microservices tracing with spring cloud and zipkin (spring one)
Implementing microservices tracing with spring cloud and zipkin (spring one)
 
Continuous Delivery for Microservice Architectures with Concourse & Cloud Fou...
Continuous Delivery for Microservice Architectures with Concourse & Cloud Fou...Continuous Delivery for Microservice Architectures with Concourse & Cloud Fou...
Continuous Delivery for Microservice Architectures with Concourse & Cloud Fou...
 
Who Does What? Mapping Cloud Foundry Activities and Entitlements to IT Roles
Who Does What? Mapping Cloud Foundry Activities and Entitlements to IT RolesWho Does What? Mapping Cloud Foundry Activities and Entitlements to IT Roles
Who Does What? Mapping Cloud Foundry Activities and Entitlements to IT Roles
 
Building a Secure App with Google Polymer and Java / Spring
Building a Secure App with Google Polymer and Java / SpringBuilding a Secure App with Google Polymer and Java / Spring
Building a Secure App with Google Polymer and Java / Spring
 
Developing Real-Time Data Pipelines with Apache Kafka
Developing Real-Time Data Pipelines with Apache KafkaDeveloping Real-Time Data Pipelines with Apache Kafka
Developing Real-Time Data Pipelines with Apache Kafka
 
The Beginner’s Guide To Spring Cloud
The Beginner’s Guide To Spring CloudThe Beginner’s Guide To Spring Cloud
The Beginner’s Guide To Spring Cloud
 
Managing the Complexity of Microservices Deployments
Managing the Complexity of Microservices DeploymentsManaging the Complexity of Microservices Deployments
Managing the Complexity of Microservices Deployments
 
IO State In Distributed API Architecture
IO State In Distributed API ArchitectureIO State In Distributed API Architecture
IO State In Distributed API Architecture
 
Lattice: A Cloud-Native Platform for Your Spring Applications
Lattice: A Cloud-Native Platform for Your Spring ApplicationsLattice: A Cloud-Native Platform for Your Spring Applications
Lattice: A Cloud-Native Platform for Your Spring Applications
 

More from VMware Tanzu

What AI Means For Your Product Strategy And What To Do About It
What AI Means For Your Product Strategy And What To Do About ItWhat AI Means For Your Product Strategy And What To Do About It
What AI Means For Your Product Strategy And What To Do About ItVMware Tanzu
 
Make the Right Thing the Obvious Thing at Cardinal Health 2023
Make the Right Thing the Obvious Thing at Cardinal Health 2023Make the Right Thing the Obvious Thing at Cardinal Health 2023
Make the Right Thing the Obvious Thing at Cardinal Health 2023VMware Tanzu
 
Enhancing DevEx and Simplifying Operations at Scale
Enhancing DevEx and Simplifying Operations at ScaleEnhancing DevEx and Simplifying Operations at Scale
Enhancing DevEx and Simplifying Operations at ScaleVMware Tanzu
 
Spring Update | July 2023
Spring Update | July 2023Spring Update | July 2023
Spring Update | July 2023VMware Tanzu
 
Platforms, Platform Engineering, & Platform as a Product
Platforms, Platform Engineering, & Platform as a ProductPlatforms, Platform Engineering, & Platform as a Product
Platforms, Platform Engineering, & Platform as a ProductVMware Tanzu
 
Building Cloud Ready Apps
Building Cloud Ready AppsBuilding Cloud Ready Apps
Building Cloud Ready AppsVMware Tanzu
 
Spring Boot 3 And Beyond
Spring Boot 3 And BeyondSpring Boot 3 And Beyond
Spring Boot 3 And BeyondVMware Tanzu
 
Spring Cloud Gateway - SpringOne Tour 2023 Charles Schwab.pdf
Spring Cloud Gateway - SpringOne Tour 2023 Charles Schwab.pdfSpring Cloud Gateway - SpringOne Tour 2023 Charles Schwab.pdf
Spring Cloud Gateway - SpringOne Tour 2023 Charles Schwab.pdfVMware Tanzu
 
Simplify and Scale Enterprise Apps in the Cloud | Boston 2023
Simplify and Scale Enterprise Apps in the Cloud | Boston 2023Simplify and Scale Enterprise Apps in the Cloud | Boston 2023
Simplify and Scale Enterprise Apps in the Cloud | Boston 2023VMware Tanzu
 
Simplify and Scale Enterprise Apps in the Cloud | Seattle 2023
Simplify and Scale Enterprise Apps in the Cloud | Seattle 2023Simplify and Scale Enterprise Apps in the Cloud | Seattle 2023
Simplify and Scale Enterprise Apps in the Cloud | Seattle 2023VMware Tanzu
 
tanzu_developer_connect.pptx
tanzu_developer_connect.pptxtanzu_developer_connect.pptx
tanzu_developer_connect.pptxVMware Tanzu
 
Tanzu Virtual Developer Connect Workshop - French
Tanzu Virtual Developer Connect Workshop - FrenchTanzu Virtual Developer Connect Workshop - French
Tanzu Virtual Developer Connect Workshop - FrenchVMware Tanzu
 
Tanzu Developer Connect Workshop - English
Tanzu Developer Connect Workshop - EnglishTanzu Developer Connect Workshop - English
Tanzu Developer Connect Workshop - EnglishVMware Tanzu
 
Virtual Developer Connect Workshop - English
Virtual Developer Connect Workshop - EnglishVirtual Developer Connect Workshop - English
Virtual Developer Connect Workshop - EnglishVMware Tanzu
 
Tanzu Developer Connect - French
Tanzu Developer Connect - FrenchTanzu Developer Connect - French
Tanzu Developer Connect - FrenchVMware Tanzu
 
Simplify and Scale Enterprise Apps in the Cloud | Dallas 2023
Simplify and Scale Enterprise Apps in the Cloud | Dallas 2023Simplify and Scale Enterprise Apps in the Cloud | Dallas 2023
Simplify and Scale Enterprise Apps in the Cloud | Dallas 2023VMware Tanzu
 
SpringOne Tour: Deliver 15-Factor Applications on Kubernetes with Spring Boot
SpringOne Tour: Deliver 15-Factor Applications on Kubernetes with Spring BootSpringOne Tour: Deliver 15-Factor Applications on Kubernetes with Spring Boot
SpringOne Tour: Deliver 15-Factor Applications on Kubernetes with Spring BootVMware Tanzu
 
SpringOne Tour: The Influential Software Engineer
SpringOne Tour: The Influential Software EngineerSpringOne Tour: The Influential Software Engineer
SpringOne Tour: The Influential Software EngineerVMware Tanzu
 
SpringOne Tour: Domain-Driven Design: Theory vs Practice
SpringOne Tour: Domain-Driven Design: Theory vs PracticeSpringOne Tour: Domain-Driven Design: Theory vs Practice
SpringOne Tour: Domain-Driven Design: Theory vs PracticeVMware Tanzu
 
SpringOne Tour: Spring Recipes: A Collection of Common-Sense Solutions
SpringOne Tour: Spring Recipes: A Collection of Common-Sense SolutionsSpringOne Tour: Spring Recipes: A Collection of Common-Sense Solutions
SpringOne Tour: Spring Recipes: A Collection of Common-Sense SolutionsVMware Tanzu
 

More from VMware Tanzu (20)

What AI Means For Your Product Strategy And What To Do About It
What AI Means For Your Product Strategy And What To Do About ItWhat AI Means For Your Product Strategy And What To Do About It
What AI Means For Your Product Strategy And What To Do About It
 
Make the Right Thing the Obvious Thing at Cardinal Health 2023
Make the Right Thing the Obvious Thing at Cardinal Health 2023Make the Right Thing the Obvious Thing at Cardinal Health 2023
Make the Right Thing the Obvious Thing at Cardinal Health 2023
 
Enhancing DevEx and Simplifying Operations at Scale
Enhancing DevEx and Simplifying Operations at ScaleEnhancing DevEx and Simplifying Operations at Scale
Enhancing DevEx and Simplifying Operations at Scale
 
Spring Update | July 2023
Spring Update | July 2023Spring Update | July 2023
Spring Update | July 2023
 
Platforms, Platform Engineering, & Platform as a Product
Platforms, Platform Engineering, & Platform as a ProductPlatforms, Platform Engineering, & Platform as a Product
Platforms, Platform Engineering, & Platform as a Product
 
Building Cloud Ready Apps
Building Cloud Ready AppsBuilding Cloud Ready Apps
Building Cloud Ready Apps
 
Spring Boot 3 And Beyond
Spring Boot 3 And BeyondSpring Boot 3 And Beyond
Spring Boot 3 And Beyond
 
Spring Cloud Gateway - SpringOne Tour 2023 Charles Schwab.pdf
Spring Cloud Gateway - SpringOne Tour 2023 Charles Schwab.pdfSpring Cloud Gateway - SpringOne Tour 2023 Charles Schwab.pdf
Spring Cloud Gateway - SpringOne Tour 2023 Charles Schwab.pdf
 
Simplify and Scale Enterprise Apps in the Cloud | Boston 2023
Simplify and Scale Enterprise Apps in the Cloud | Boston 2023Simplify and Scale Enterprise Apps in the Cloud | Boston 2023
Simplify and Scale Enterprise Apps in the Cloud | Boston 2023
 
Simplify and Scale Enterprise Apps in the Cloud | Seattle 2023
Simplify and Scale Enterprise Apps in the Cloud | Seattle 2023Simplify and Scale Enterprise Apps in the Cloud | Seattle 2023
Simplify and Scale Enterprise Apps in the Cloud | Seattle 2023
 
tanzu_developer_connect.pptx
tanzu_developer_connect.pptxtanzu_developer_connect.pptx
tanzu_developer_connect.pptx
 
Tanzu Virtual Developer Connect Workshop - French
Tanzu Virtual Developer Connect Workshop - FrenchTanzu Virtual Developer Connect Workshop - French
Tanzu Virtual Developer Connect Workshop - French
 
Tanzu Developer Connect Workshop - English
Tanzu Developer Connect Workshop - EnglishTanzu Developer Connect Workshop - English
Tanzu Developer Connect Workshop - English
 
Virtual Developer Connect Workshop - English
Virtual Developer Connect Workshop - EnglishVirtual Developer Connect Workshop - English
Virtual Developer Connect Workshop - English
 
Tanzu Developer Connect - French
Tanzu Developer Connect - FrenchTanzu Developer Connect - French
Tanzu Developer Connect - French
 
Simplify and Scale Enterprise Apps in the Cloud | Dallas 2023
Simplify and Scale Enterprise Apps in the Cloud | Dallas 2023Simplify and Scale Enterprise Apps in the Cloud | Dallas 2023
Simplify and Scale Enterprise Apps in the Cloud | Dallas 2023
 
SpringOne Tour: Deliver 15-Factor Applications on Kubernetes with Spring Boot
SpringOne Tour: Deliver 15-Factor Applications on Kubernetes with Spring BootSpringOne Tour: Deliver 15-Factor Applications on Kubernetes with Spring Boot
SpringOne Tour: Deliver 15-Factor Applications on Kubernetes with Spring Boot
 
SpringOne Tour: The Influential Software Engineer
SpringOne Tour: The Influential Software EngineerSpringOne Tour: The Influential Software Engineer
SpringOne Tour: The Influential Software Engineer
 
SpringOne Tour: Domain-Driven Design: Theory vs Practice
SpringOne Tour: Domain-Driven Design: Theory vs PracticeSpringOne Tour: Domain-Driven Design: Theory vs Practice
SpringOne Tour: Domain-Driven Design: Theory vs Practice
 
SpringOne Tour: Spring Recipes: A Collection of Common-Sense Solutions
SpringOne Tour: Spring Recipes: A Collection of Common-Sense SolutionsSpringOne Tour: Spring Recipes: A Collection of Common-Sense Solutions
SpringOne Tour: Spring Recipes: A Collection of Common-Sense Solutions
 

Recently uploaded

Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Strongerpanagenda
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Mark Goldstein
 
Manual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditManual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditSkynet Technologies
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demoHarshalMandlekar2
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality AssuranceInflectra
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersRaghuram Pandurangan
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersNicole Novielli
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rick Flair
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentPim van der Noll
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Farhan Tariq
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPathCommunity
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfIngrid Airi González
 

Recently uploaded (20)

Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
 
Manual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditManual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance Audit
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demo
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information Developers
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software Developers
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to Hero
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdf
 

Documenting RESTful APIs with Spring REST Docs

  • 1. Documenting RESTful APIs with Spring REST Docs By Jenn Strater @codeJENNerator 1
  • 2. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Notes For Those Viewing These Slides Online • Bulleted text like this indicates the key points mentioned on a previous slide. They may not have been included in the official presentation. • If this view does not support links, the links will work in the pdf. In speakerdeck, you can click the ‘download pdf’ button at the right. X
  • 3. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Outline • API Documentation Background • Approaches to Documentation • Considerations 2 • Test-Driven Documentation • Spring REST Docs • Examples
  • 4. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Follow Along https://speakerdeck.com/jlstrater/test-driven-docs-springone-2017 https://github.com/jlstrater/groovy-spring-boot-restdocs-example https://github.com/ratpack/example-books https://github.com/jlstrater/spring-restdocs-public-api-example 3
  • 6. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Follow Along https://speakerdeck.com/jlstrater/test-driven-docs-springone-2017 https://github.com/jlstrater/groovy-spring-boot-restdocs-example https://github.com/ratpack/example-books https://github.com/jlstrater/spring-restdocs-public-api-example 5
  • 7. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 6
  • 8. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ About Me • Co-founder of Gr8Ladies and talk about women in the Groovy Community all over the world • Passionate about bring new people into the Groovy community through free introductory workshops called Gr8Workshops. • Senior Engineer at Zenjob as of June 2017. We’re hiring! zenjob.de/careers • Spent the 2016-2017 academic year in Copenhagen working on OSS and taking classes through a Fulbright Grant. • Prior to the Fulbright Grant, I was a senior consultant at Object Partners, Inc. in Minneapolis, MN, USA. My work with Spring REST Docs started on a project at my client through them. X
  • 9. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Audience Background • Creating RESTful APIs • Spring Boot • Grails • Ratpack 7 • API Documentation • Wiki Pages, Word Documents, Confluence, etc • Asciidoc / Asciidoctor • Swagger / RAML
  • 10. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 8 src: https://flic.kr/p/rehEf5
  • 11. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 8 src: https://flic.kr/p/rehEf5 I hate writing documentation!*
  • 13. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ REST Maturity Model 10 src: http://martinfowler.com/articles/richardsonMaturityModel.html
  • 14. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ REST Maturity Model 10 src: http://martinfowler.com/articles/richardsonMaturityModel.html
  • 15. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ REST Maturity Model • I’m not really a fan of the right vs wrong REST debate, but I like this categorization of APIs. • Most of our APIS were level one or two, but we wanted to have the flexibility to use hypermedia • Spring REST docs includes support for level 3 / hypermedia • Swagger 2.0 did not support hypermedia. Swagger 3.0 (released end of July 2017) now does X
  • 16. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 11 Attribution: @Alvaro_Sanchez
  • 17. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Monolith vs Microservices As architecture evolves, many companies move from a central monolith to micro services or maybe even gateways and multi-tiered architectures. • For documentation, it was important to have: • a consistent look and feel • a way to show how the services can work together X
  • 18. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Central Information 12 Security Http Verbs Error Handling Http Status
  • 19. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Central Information Central Information • For example, security tokens, patterns for error messages, http verbs/status codes, etc • This information needs to be written out and defined once; not on every endpoint. X
  • 21. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 14
  • 22. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 15
  • 23. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Central Information Who’s seen this before? Of the people who have never used swagger before, how many understand what this means? Even our CTO who is technical, didn’t want to spend time figuring it out. Also, product teams. This is a swagger ui example but the concept is not limited to Swagger. I have seen many different APIs document in this way. It’s not just URI centric, but also very developer centric. No matter whether you leave here choosing Swagger or Spring REST Docs, think about your users! This is an example from Spring Rest Docs using Asciidoc. Notice the very different way of organizing information on the second slide. Resource centric document design organizes information by topic and includes urls in the examples only. The information from generated solutions isn’t enough. We need the handwritten information too! X
  • 25. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 17
  • 26. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 17 Definitions Swagger (OpenAPI Specification) RAML
  • 27. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 17 Definitions Swagger (OpenAPI Specification) RAML Documentation AsciiDoc Markdown Wikis
  • 28. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 17 Definitions Swagger (OpenAPI Specification) RAML Documentation AsciiDoc Markdown Wikis Swagger UI Swagger2Markup
  • 29. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 17 Definitions Swagger (OpenAPI Specification) RAML Testing MockMVC RestAssured Documentation AsciiDoc Markdown Wikis Swagger UI Swagger2Markup
  • 30. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 17 Definitions Swagger (OpenAPI Specification) RAML Testing MockMVC RestAssured Documentation AsciiDoc Markdown Wikis Swagger UI Swagger2Markup AssertJ- Swagger Contract-First
  • 31. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 17 Definitions Swagger (OpenAPI Specification) RAML Testing MockMVC RestAssured Documentation AsciiDoc Markdown Wikis Swagger UI Swagger2Markup Spring REST Docs AssertJ- Swagger Contract-First
  • 32. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 17 Definitions Swagger (OpenAPI Specification) RAML
  • 33. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 18
  • 34. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 18
  • 35. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Swagger Swagger is: — a lot of things • At the core, it is a way to standardize and define HTTP APIs over RPC. • It is very popular because of the many plugins built on top of it for things such as generating client libraries, generating docs, and much more. • In earlier versions, it did not support hypermedia. Documenting across micro services was possible, but required a bit of setup. Depending on the library, some central information is duplicated. X
  • 36. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Body Slide - Dark Background All body text is Proxima Nova Regular • Subhead (18pt) • Level Two (18pt) • Level Three (18pt) • Level Four (18pt) Use the “Decrease/Increase Indent” 
 tools to change bullet levels • Click on the Home ribbon, Paragraph tab Line spacing is set in master slides 19 Automation img src: https://flic.kr/p/eduUfU
  • 37. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Body Slide - Dark Background All body text is Proxima Nova Regular • Subhead (18pt) • Level Two (18pt) • Level Three (18pt) • Level Four (18pt) Use the “Decrease/Increase Indent” 
 tools to change bullet levels • Click on the Home ribbon, Paragraph tab Line spacing is set in master slides 20 img src: https://www.flickr.com/photos/ 24874528@N04/17125924230 SpringFox
  • 38. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ SpringFox SpringFox: • Generates a Swagger Specification from source • Is very easy to setup (in simple cases) • No OpenAPI Spec 3.0 support! X
  • 39. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Custom Swagger Specification 21 { "swagger": "2.0", "info": { "version": "1", "title": "My Service", "contact": { "name": "Company Name" }, "license": {} }, "host": "example.com", "basepath": "/docs" }
  • 40. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Swagger UI 22
  • 41. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 23
  • 42. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ SpringFox UI approaches • Use SpringFox library • Copy static files and customize X
  • 44. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Customization 25 img src: http://sergiodelamo.es/how-to-secure-your-grails-3-api-with-spring-security-rest-for-grails/
  • 45. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Customization • For any non-standard configuration, you may have to override the UI. • As one example, we were adding custom headers for oauth jwt tokens. At the time, it was not supported with springfox-ui. X
  • 46. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Object Mapping 26 img src: https://github.com/springfox/springfox/issues/281
  • 47. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 27 https://github.com/swagger-api/swagger-core/issues/97
  • 48. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Customization • In Swagger/OpenAPI Spec 2.0, there was no hypermedia support. • In OpenAPI Spec 3.0, there is some support for links X
  • 49. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 1 @Secured(‘ROLE_ALLOWED_TO_PERFORM_ACTION’)
 2 @RequestMapping(value = '/v1/serviceName/actionName', method = 3 RequestMethod.POST)
 4 @ApiOperation(value = '/actionName',
 5 notes = 'Enables or disables setting via "1" or "0", respectively')
 6 @ApiResponses(value = [
 7 @ApiResponse(code = 200, response = CustomSettingResponse, message = 8 ‘Successful setting update'),
 9 @ApiResponse(code = 400, response = ErrorResponse, message = 'Invalid 10 user input'),
 11 @ApiResponse(code = 500, response = ErrorResponse, message = 'Unexpected 12 server error')
 13 ])
 14 CustomSettingResponse setSetting(@RequestBody CustomModel settingsValue) {
 15 SaveSettingUpdateRequest request = new SaveSettingUpdateRequest (
 16 settingsValue.fieldOne,
 17 [new TransformedSetting(SettingEnum.POSSIBLE_ENUM_VALUE, 18 new Double(settingsValue.value))]
 19 )
 20 api.saveUpdatedSetting(request)
 21 }
  • 50. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 1 @Secured(‘ROLE_ALLOWED_TO_PERFORM_ACTION’)
 2 @RequestMapping(value = '/v1/serviceName/actionName', method = 3 RequestMethod.POST)
 4 @ApiOperation(value = '/actionName',
 5 notes = 'Enables or disables setting via "1" or "0", respectively')
 6 @ApiResponses(value = [
 7 @ApiResponse(code = 200, response = CustomSettingResponse, message = 8 ‘Successful setting update'),
 9 @ApiResponse(code = 400, response = ErrorResponse, message = 'Invalid 10 user input'),
 11 @ApiResponse(code = 500, response = ErrorResponse, message = 'Unexpected 12 server error')
 13 ])
 14 CustomSettingResponse setSetting(@RequestBody CustomModel settingsValue) {
 15 SaveSettingUpdateRequest request = new SaveSettingUpdateRequest (
 16 settingsValue.fieldOne,
 17 [new TransformedSetting(SettingEnum.POSSIBLE_ENUM_VALUE, 18 new Double(settingsValue.value))]
 19 )
 20 api.saveUpdatedSetting(request)
 21 } Annotation Hell
  • 51. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 1 @Secured(‘ROLE_ALLOWED_TO_PERFORM_ACTION’)
 2 @RequestMapping(value = '/v1/serviceName/actionName', method = 3 RequestMethod.POST)
 4 @ApiOperation(value = '/actionName',
 5 notes = 'Enables or disables setting via "1" or "0", respectively')
 6 @ApiResponses(value = [
 7 @ApiResponse(code = 200, response = CustomSettingResponse, message = 8 ‘Successful setting update'),
 9 @ApiResponse(code = 400, response = ErrorResponse, message = 'Invalid 10 user input'),
 11 @ApiResponse(code = 500, response = ErrorResponse, message = 'Unexpected 12 server error')
 13 ])
 14 CustomSettingResponse setSetting(@RequestBody CustomModel settingsValue) {
 15 SaveSettingUpdateRequest request = new SaveSettingUpdateRequest (
 16 settingsValue.fieldOne,
 17 [new TransformedSetting(SettingEnum.POSSIBLE_ENUM_VALUE, 18 new Double(settingsValue.value))]
 19 )
 20 api.saveUpdatedSetting(request)
 21 } Annotation Hell
  • 52. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 1 @Secured(‘ROLE_ALLOWED_TO_PERFORM_ACTION’)
 2 @RequestMapping(value = '/v1/serviceName/actionName', method = 3 RequestMethod.POST)
 4 @ApiOperation(value = '/actionName',
 5 notes = 'Enables or disables setting via "1" or "0", respectively')
 6 @ApiResponses(value = [
 7 @ApiResponse(code = 200, response = CustomSettingResponse, message = 8 ‘Successful setting update'),
 9 @ApiResponse(code = 400, response = ErrorResponse, message = 'Invalid 10 user input'),
 11 @ApiResponse(code = 500, response = ErrorResponse, message = 'Unexpected 12 server error')
 13 ])
 14 CustomSettingResponse setSetting(@RequestBody CustomModel settingsValue) {
 15 SaveSettingUpdateRequest request = new SaveSettingUpdateRequest (
 16 settingsValue.fieldOne,
 17 [new TransformedSetting(SettingEnum.POSSIBLE_ENUM_VALUE, 18 new Double(settingsValue.value))]
 19 )
 20 api.saveUpdatedSetting(request)
 21 } Annotation Hell X
  • 53. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 1 @Secured(‘ROLE_ALLOWED_TO_PERFORM_ACTION’)
 2 @RequestMapping(value = '/v1/serviceName/actionName', method = 3 RequestMethod.POST) 4 CustomSettingResponse setSetting(@RequestBody CustomModel settingsValue) {
 5 SaveSettingUpdateRequest request = new SaveSettingUpdateRequest (
 6 settingsValue.fieldOne,
 7 [new TransformedSetting(SettingEnum.POSSIBLE_ENUM_VALUE, 8 new Double(settingsValue.value))]
 9 )
 10 api.saveUpdatedSetting(request)
 11 }
  • 55. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 31
  • 56. “Try it” Button Alternatives
  • 57. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 33
  • 58. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 34
  • 59. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Curl -> curl 'http://localhost:8080/greetings' -i -H 'Content-Type: text/plain' HTTP/1.1 200 X-Application-Context: application:8080 Content-Type: application/json;charset=UTF-8 Transfer-Encoding: chunked Date:Thu, 26 Jan 2017 13:28:19 GMT [{"id":1,"message":"Hello"},{"id":2,"message":"Hi"},{"id":3,"message":"Hola"},{"id":4,"message":"Olá"},{"id":5,"message":"Hej"}] 35
  • 61. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 37 Swagger2Markup https://github.com/Swagger2Markup/swagger2markup
  • 62. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ img src: http://www.elvenspirit.com/elf/wp-content/uploads/2011/10/IMG_3013.jpg FAIL!
  • 63. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ img src: http://www.elvenspirit.com/elf/wp-content/uploads/2011/10/IMG_3013.jpg FAIL! AssertJ-Swagger https://github.com/RobWin/assertj-swagger
  • 64. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Spring Cloud Contract 39
  • 65. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 40
  • 66. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 40 Definitions Swagger (OpenAPI Specification) RAML
  • 67. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 40 Definitions Swagger (OpenAPI Specification) RAML Documentation AsciiDoc Markdown Wikis
  • 68. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 40 Definitions Swagger (OpenAPI Specification) RAML Documentation AsciiDoc Markdown Wikis Swagger UI Swagger2Markup
  • 69. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 40 Definitions Swagger (OpenAPI Specification) RAML Testing MockMVC RestAssured Documentation AsciiDoc Markdown Wikis Swagger UI Swagger2Markup
  • 70. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 40 Definitions Swagger (OpenAPI Specification) RAML Testing MockMVC RestAssured Documentation AsciiDoc Markdown Wikis Swagger UI Swagger2Markup AssertJ- Swagger Contract-First
  • 71. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 40 Definitions Swagger (OpenAPI Specification) RAML Testing MockMVC RestAssured Documentation AsciiDoc Markdown Wikis Swagger UI Swagger2Markup Spring REST Docs AssertJ- Swagger Contract-First
  • 72. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Spring REST Docs
  • 73. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Test-Driven Development Green Red Refactor
  • 74. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Test-Driven Documentation
  • 75. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Test-Driven Documentation Red
  • 76. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Test-Driven Documentation Red
  • 77. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Test-Driven Documentation Document Red
  • 78. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Test-Driven Documentation Document Red
  • 79. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Test-Driven Documentation Document Green Red
  • 80. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Test-Driven Documentation Document Green Red
  • 81. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Test-Driven Documentation Document Green Red Refactor
  • 82. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Test-Driven Documentation Document Green Red Refactor
  • 83. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Winning Solution https://flic.kr/p/5XiKxU Winning Solution
  • 84. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Winning Solution • Ensures documentation matches implementation • Encourages writing more tests • Reduces duplication in docs and tests • Removes annotations from source X
  • 85. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Spring REST Docs 44 https://flic.kr/p/5XiKxU
  • 86. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Game Changers 45 https://flic.kr/p/9Tiv3U
  • 87. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Game Changers •Generated code snippets •Tests fail when documentation is missing or out-of-date •Rest APIs with Hypermedia •Ratpack •Dynamic routing doesn’t work with Swagger X
  • 88. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ About Spring REST Docs 46
  • 89. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ About Spring REST Docs projects.spring.io/spring-restdocs 46
  • 90. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ About Spring REST Docs projects.spring.io/spring-restdocs @springrestdocs 46
  • 91. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ About Spring REST Docs projects.spring.io/spring-restdocs @springrestdocs https://github.com/spring-projects/spring-restdocs 46
  • 92. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ About Spring REST Docs •Start with reading the docs; The written docs are good! •Overview •Sponsored by Pivotal •Project Lead - Andy Wilkinson •Current Version - 2.0.0 released Nov 28 •Twitter Account and Official Logo X
  • 93. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ About Spring REST Docs • Test-Driven Documentation with Spring REST Docs (Java and Spring Boot) - Spring I/O 2016 Andy Wilkinson • Writing comprehensive and guaranteed up-to-date REST API documentation - SpringOne Platform 2016 Anders Evers X
  • 94. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Out of the Box 47
  • 95. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Out of the Box Testing Frameworks • MockMVC • RestAssured • WebTestClient - NEW! 47
  • 96. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Out of the Box Testing Frameworks • MockMVC • RestAssured • WebTestClient - NEW! 47 Build Tools • Gradle • Maven
  • 97. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Out of the Box 48
  • 98. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Out of the Box Documentation Format • AsciiDoc • Markdown 48
  • 99. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Out of the Box Documentation Format • AsciiDoc • Markdown 48 Sample Projects • Spring Boot • Grails • Slate • TestNG • And more!
  • 101. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Groovier Spring REST Docs • Spring Boot • Ratpack • Grails 50
  • 102. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Groovier Spring REST Docs Example - Spring Boot Groovy Spring Boot Project + Asciidoctor Gradle plugin + Spring REST Docs WebTestClient to Spock tests + Add to static assets during build and publish to GitHub pages 51
  • 103. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 52
  • 104. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 52
  • 105. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 52
  • 106. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Groovier Spring REST Docs Example - Spring Boot • Start with lazybones spring boot app • Add mock endpoints for example https://github.com/jlstrater/groovy-spring-boot-restdocs-example Updated to Spring Boot 2.0.0.M7 and thanks to: https://www.callicoder.com/ reactive-rest-apis-spring-webflux-reactive-mongo/ 53
  • 107. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 54
  • 108. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Endpoints @RestController @RequestMapping('/greetings') class GreetingsController { @Autowired GreetingRepository greetingsRepository @PostMapping() Mono<Greeting> createGreeting(@Valid @RequestBody Greeting greeting) { return greetingsRepository.save(greeting) } @GetMapping() Flux<Greeting> listAllGreetings() { return greetingsRepository.findAll() } @GetMapping('/{id}') Mono<Greeting> getGreetingById(@PathVariable(value = 'id') String greetingId) { greetingsRepository.findById(greetingId) } } 55
  • 109. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Endpoints @RestController @RequestMapping('/greetings') class GreetingsController { @Autowired GreetingRepository greetingsRepository @PostMapping() Mono<Greeting> createGreeting(@Valid @RequestBody Greeting greeting) { return greetingsRepository.save(greeting) } @GetMapping() Flux<Greeting> listAllGreetings() { return greetingsRepository.findAll() } @GetMapping('/{id}') Mono<Greeting> getGreetingById(@PathVariable(value = 'id') String greetingId) { greetingsRepository.findById(greetingId) } } 55 Create a new Greeting
  • 110. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Endpoints @RestController @RequestMapping('/greetings') class GreetingsController { @Autowired GreetingRepository greetingsRepository @PostMapping() Mono<Greeting> createGreeting(@Valid @RequestBody Greeting greeting) { return greetingsRepository.save(greeting) } @GetMapping() Flux<Greeting> listAllGreetings() { return greetingsRepository.findAll() } @GetMapping('/{id}') Mono<Greeting> getGreetingById(@PathVariable(value = 'id') String greetingId) { greetingsRepository.findById(greetingId) } } 55 Create a new Greeting List all greetings
  • 111. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Endpoints @RestController @RequestMapping('/greetings') class GreetingsController { @Autowired GreetingRepository greetingsRepository @PostMapping() Mono<Greeting> createGreeting(@Valid @RequestBody Greeting greeting) { return greetingsRepository.save(greeting) } @GetMapping() Flux<Greeting> listAllGreetings() { return greetingsRepository.findAll() } @GetMapping('/{id}') Mono<Greeting> getGreetingById(@PathVariable(value = 'id') String greetingId) { greetingsRepository.findById(greetingId) } } 55 Create a new Greeting List all greetings Get a greeting by id
  • 112. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 56
  • 113. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 56
  • 114. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ AsciiDoc [introduction] = Introduction The Example API is a RESTful web service that shows how Spring REST docs works. [[overview-http-verbs]] == HTTP verbs The Example API tries to adhere as closely as possible to standard HTTP and REST conventions in its use of HTTP verbs. |=== | Verb | Usage | `GET` | Used to retrieve a resource | `POST` | Used to create a new resource | `PUT` | Used to update an existing resource, overwrites all fields 57
  • 115. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Asciidoctor Gradle Plugin 58
  • 116. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ AsciiDoc Gradle Configuration apply plugin: 'org.asciidoctor.convert' asciidoctor { backends 'html5' attributes 'source-highlighter' : 'prettify', 'imagesdir':'images', 'toc':'left', 'icons': 'font', 'setanchors':'true', 'idprefix':'', 'idseparator':'-', 'docinfo1':'true', } 59
  • 117. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 60
  • 118. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 60
  • 119. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
  • 120. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 62
  • 121. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 62
  • 122. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Project Reactor and the WebTestClient 63
  • 123. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Setup @CompileStatic @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) class BaseControllerSpec extends Specification { @Autowired ApplicationContext context protected WebTestClient webTestClient void setup() { this.webTestClient = WebTestClient.bindToApplicationContext(this.context) .configureClient() .baseUrl('/greetings') .build() } } 64
  • 124. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Setup @CompileStatic @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) class BaseControllerSpec extends Specification { @Autowired ApplicationContext context protected WebTestClient webTestClient void setup() { this.webTestClient = WebTestClient.bindToApplicationContext(this.context) .configureClient() .baseUrl('/greetings') .build() } } 64 If context is null, remember to use spock-spring!!
  • 125. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ WebTestClient Call and Assertions this.webTestClient.post().uri('/') .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON) .body(BodyInserters.fromObject('{"message": "Hello SpringOne Platform!"}')) .exchange() .expectStatus().isOk() .expectBody() .jsonPath('$.id').isNotEmpty() .jsonPath('$.message').isEqualTo('Hello SpringOne Platform!') 65
  • 126. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 66
  • 127. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 66
  • 128. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Spring REST Docs Gradle Configuration dependencies { … testCompile "org.springframework.restdocs:spring-restdocs-webtestclient:${springRestDocsVersion}" asciidoctor "org.springframework.restdocs:spring-restdocs-asciidoctor:${springRestDocsVersion}" } ext { snippetsDir = file('build/generated-snippets') } test { outputs.dir "$projectDir/src/main/resources/public" } asciidoctor { dependsOn test inputs.dir snippetsDir } build { dependsOn asciidoctor } ext['spring-restdocs.version'] = springRestDocsVersion 67
  • 129. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Spring REST Docs with WebTestClient (setup) @CompileStatic @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) class BaseControllerSpec extends Specification { @Rule JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation() @Autowired ApplicationContext context protected WebTestClient webTestClient void setup() { this.webTestClient = WebTestClient.bindToApplicationContext(this.context) .configureClient() .baseUrl('/greetings') .filter(documentationConfiguration(restDocumentation)) .build() } } 68
  • 130. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Spring REST Docs with WebTestClient (setup) @CompileStatic @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) class BaseControllerSpec extends Specification { @Rule JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation() @Autowired ApplicationContext context protected WebTestClient webTestClient void setup() { this.webTestClient = WebTestClient.bindToApplicationContext(this.context) .configureClient() .baseUrl('/greetings') .filter(documentationConfiguration(restDocumentation)) .build() } } 68
  • 131. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Spring REST Docs with WebTestClient (setup) @CompileStatic @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) class BaseControllerSpec extends Specification { @Rule JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation() @Autowired ApplicationContext context protected WebTestClient webTestClient void setup() { this.webTestClient = WebTestClient.bindToApplicationContext(this.context) .configureClient() .baseUrl('/greetings') .filter(documentationConfiguration(restDocumentation)) .build() } } 68
  • 132. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Spring REST Docs with WebTestClient (tests) void 'test and document creating a greeting with a custom name'() { expect: this.webTestClient.post().uri('/') .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON) .body(BodyInserters.fromObject('{"message": "Hello SpringOne Platform!"}')) .exchange() .expectStatus().isOk() .expectBody() .jsonPath('$.id').isNotEmpty() .jsonPath('$.message').isEqualTo('Hello SpringOne Platform!') .consumeWith(document('greetings-post-example', preprocessRequest(prettyPrint()), requestFields( fieldWithPath('message').type(JsonFieldType.STRING) .description("The greeting's message")))) }` 69
  • 133. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Spring REST Docs with WebTestClient (tests) void 'test and document creating a greeting with a custom name'() { expect: this.webTestClient.post().uri('/') .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON) .body(BodyInserters.fromObject('{"message": "Hello SpringOne Platform!"}')) .exchange() .expectStatus().isOk() .expectBody() .jsonPath('$.id').isNotEmpty() .jsonPath('$.message').isEqualTo('Hello SpringOne Platform!') .consumeWith(document('greetings-post-example', preprocessRequest(prettyPrint()), requestFields( fieldWithPath('message').type(JsonFieldType.STRING) .description("The greeting's message")))) }` 69
  • 134. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Spring REST Docs with WebTestClient (tests) void 'test and document get of a list of greetings'() { expect: this.webTestClient.get().uri('/').accept(MediaType.APPLICATION_JSON) .exchange() .expectStatus().isOk() .expectBody() .consumeWith(document('greetings-list-example', preprocessResponse(prettyPrint()), responseFields(greetingList))) } FieldDescriptor[] greetingList = new FieldDescriptor().with { [fieldWithPath('[].id').type(JsonFieldType.STRING).optional() .description("The greeting's id"), fieldWithPath('[].message').type(JsonFieldType.STRING) .description("The greeting's message")] } 70
  • 135. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Spring REST Docs with WebTestClient (tests) void 'test and document get of a list of greetings'() { expect: this.webTestClient.get().uri('/').accept(MediaType.APPLICATION_JSON) .exchange() .expectStatus().isOk() .expectBody() .consumeWith(document('greetings-list-example', preprocessResponse(prettyPrint()), responseFields(greetingList))) } FieldDescriptor[] greetingList = new FieldDescriptor().with { [fieldWithPath('[].id').type(JsonFieldType.STRING).optional() .description("The greeting's id"), fieldWithPath('[].message').type(JsonFieldType.STRING) .description("The greeting's message")] } 70
  • 136. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Spring REST Docs with WebTestClient (tests) void 'test and document get of a list of greetings'() { expect: this.webTestClient.get().uri('/').accept(MediaType.APPLICATION_JSON) .exchange() .expectStatus().isOk() .expectBody() .consumeWith(document('greetings-list-example', preprocessResponse(prettyPrint()), responseFields(greetingList))) } FieldDescriptor[] greetingList = new FieldDescriptor().with { [fieldWithPath('[].id').type(JsonFieldType.STRING).optional() .description("The greeting's id"), fieldWithPath('[].message').type(JsonFieldType.STRING) .description("The greeting's message")] } 70
  • 137. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Error Messages 71
  • 138. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Error Messages 71
  • 139. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Error Messages 71
  • 140. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Error Messages 71
  • 141. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Error Messages 71
  • 143. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 
 +@WebMvcTest(controllers = GreetingsController)
 +@AutoConfigureRestDocs(
 + outputDir = "build/generated-snippets",
 + uriHost = “api.example.com”,
 + uriPort = 8080
 ) class BaseControllerSpec extends Specification { 
 // @Rule
 // JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation('src/docs/generated-snippets')
 
 + @Autowired
 protected MockMvc mockMvc
 //
 // @Autowired
 // private WebApplicationContext context
 //
 // void setup() {
 // this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
 // .apply(documentationConfiguration(this.restDocumentation))
 // .build()
 // } } 73
  • 144. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 74
  • 145. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 74
  • 146. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Generated Snippets 75 By Default When Specified curl-request.adoc response-fields.adoc http-request.adoc request-parameters.adoc httpie-request.adoc request-parts.adoc http-response.adoc path-parameters.adoc request body request-parts.adoc response body
  • 147. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ http-request.adoc [source,http,options="nowrap"] ---- POST /greetings/ HTTP/1.1 Content-Type: application/json Accept: application/json Host: localhost:8080 Content-Length: 45 { "message" : "Hello SpringOne Platform!" } ---- 76
  • 148. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ response-fields.adoc |=== |Path|Type|Description |`id` |`String` |The greeting's id |`message` |`String` |The greeting's message |=== 77
  • 149. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 78
  • 150. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 79 +
  • 151. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 79 +
  • 152. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Adding The Snippets [[overview-errors]] == Errors Whenever an error response (status code >= 400) is returned, the body will contain a JSON object that describes the problem. The error object has the following structure: include::{snippets}/error-example/response-fields.adoc[] For example, a request that attempts to delete on the greetings endpoint will produce a `405 Method Not Allowed` response: operation::error-example[snippets='curl-request,http-request,http-response'] [[resources]] = Resources include::resources/greetings.adoc[] 80
  • 153. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Adding The Snippets [[overview-errors]] == Errors Whenever an error response (status code >= 400) is returned, the body will contain a JSON object that describes the problem. The error object has the following structure: include::{snippets}/error-example/response-fields.adoc[] For example, a request that attempts to delete on the greetings endpoint will produce a `405 Method Not Allowed` response: operation::error-example[snippets='curl-request,http-request,http-response'] [[resources]] = Resources include::resources/greetings.adoc[] 80
  • 154. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Adding The Snippets [[overview-errors]] == Errors Whenever an error response (status code >= 400) is returned, the body will contain a JSON object that describes the problem. The error object has the following structure: include::{snippets}/error-example/response-fields.adoc[] For example, a request that attempts to delete on the greetings endpoint will produce a `405 Method Not Allowed` response: operation::error-example[snippets='curl-request,http-request,http-response'] [[resources]] = Resources include::resources/greetings.adoc[] 80
  • 155. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Adding The Snippets [[overview-errors]] == Errors Whenever an error response (status code >= 400) is returned, the body will contain a JSON object that describes the problem. The error object has the following structure: include::{snippets}/error-example/response-fields.adoc[] For example, a request that attempts to delete on the greetings endpoint will produce a `405 Method Not Allowed` response: operation::error-example[snippets='curl-request,http-request,http-response'] [[resources]] = Resources include::resources/greetings.adoc[] 80
  • 156. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 81
  • 157. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 81
  • 158. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Building the docs . 82 src/docs/ asciidoc index.adoc build/asciidoc/ html5 index.html .gradlew asciidoctor
  • 159. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
  • 161. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Publishing Strategies • Hook in asciidoctor with the gradle build task • Run the asciidoctor test separately (but make sure to run AFTER the tests) • Send to static resources directory in the current app or send to a remote site (for example Github Pages X
  • 162. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 85
  • 163. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 85 http://api.example.com/docs
  • 164. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ publish.gradle buildscript { repositories { jcenter() } dependencies { classpath 'org.ajoberstar:gradle-git:1.1.0' } } apply plugin: 'org.ajoberstar.github-pages' githubPages { repoUri = 'git@github.com:jlstrater/groovy-spring-boot-restdocs-example.git' pages { from(file('build/asciidoc/html5')) } } 86
  • 165. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ publish.gradle buildscript { repositories { jcenter() } dependencies { classpath 'org.ajoberstar:gradle-git:1.1.0' } } apply plugin: 'org.ajoberstar.github-pages' githubPages { repoUri = 'git@github.com:jlstrater/groovy-spring-boot-restdocs-example.git' pages { from(file('build/asciidoc/html5')) } } 86 If you use this method, remember to deploy docs at the same time as the project!
  • 166. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 87
  • 167. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 87 http://jlstrater.github.io/groovy- spring-boot-restdocs-example
  • 168. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 87 http://jlstrater.github.io/groovy- spring-boot-restdocs-example ./gradlew publish
  • 170. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Groovier Spring REST Docs • Ratpack • Grails 89
  • 171. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
  • 172. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
  • 173. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
  • 174. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Groovier Spring REST Docs Example - Ratpack • Ratpack Example Project • https://github.com/ratpack/example-books • Spring RESTdocs RestAssured • https://github.com/ratpack/example-books/pull/25 92
  • 175. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Groovier Spring REST Docs Example - Ratpack path(":isbn") {
 def isbn = pathTokens["isbn"]
 
 byMethod {
 get {
 bookService.find(isbn).
 single().
 subscribe { Book book ->
 if (book == null) {
 clientError 404
 } else {
 render book
 }
 }
 } ... }
 } 93 byMethod {
 get {
 bookService.all().
 toList().
 subscribe { List<Book> books ->
 render json(books)
 }
 }
 post {
 parse(jsonNode()).
 observe().
 flatMap { input ->
 bookService.insert(
 input.get("isbn").asText(),
 input.get("quantity").asLong(),
 input.get("price").asDouble()
 )
 }.
 single().
 flatMap {
 bookService.find(it)
 }.
 single().
 subscribe { Book createdBook ->
 render createdBook
 }
 } }
  • 176. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Groovier Spring REST Docs Example - Ratpack path(":isbn") {
 def isbn = pathTokens["isbn"]
 
 byMethod {
 get {
 bookService.find(isbn).
 single().
 subscribe { Book book ->
 if (book == null) {
 clientError 404
 } else {
 render book
 }
 }
 } ... }
 } 93 byMethod {
 get {
 bookService.all().
 toList().
 subscribe { List<Book> books ->
 render json(books)
 }
 }
 post {
 parse(jsonNode()).
 observe().
 flatMap { input ->
 bookService.insert(
 input.get("isbn").asText(),
 input.get("quantity").asLong(),
 input.get("price").asDouble()
 )
 }.
 single().
 flatMap {
 bookService.find(it)
 }.
 single().
 subscribe { Book createdBook ->
 render createdBook
 }
 } } Get a book by ISBN /api/books/1932394842
  • 177. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Groovier Spring REST Docs Example - Ratpack path(":isbn") {
 def isbn = pathTokens["isbn"]
 
 byMethod {
 get {
 bookService.find(isbn).
 single().
 subscribe { Book book ->
 if (book == null) {
 clientError 404
 } else {
 render book
 }
 }
 } ... }
 } 93 byMethod {
 get {
 bookService.all().
 toList().
 subscribe { List<Book> books ->
 render json(books)
 }
 }
 post {
 parse(jsonNode()).
 observe().
 flatMap { input ->
 bookService.insert(
 input.get("isbn").asText(),
 input.get("quantity").asLong(),
 input.get("price").asDouble()
 )
 }.
 single().
 flatMap {
 bookService.find(it)
 }.
 single().
 subscribe { Book createdBook ->
 render createdBook
 }
 } } Get a book by ISBN /api/books/1932394842 Get all books /api/books
  • 178. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Groovier Spring REST Docs Example - Ratpack path(":isbn") {
 def isbn = pathTokens["isbn"]
 
 byMethod {
 get {
 bookService.find(isbn).
 single().
 subscribe { Book book ->
 if (book == null) {
 clientError 404
 } else {
 render book
 }
 }
 } ... }
 } 93 byMethod {
 get {
 bookService.all().
 toList().
 subscribe { List<Book> books ->
 render json(books)
 }
 }
 post {
 parse(jsonNode()).
 observe().
 flatMap { input ->
 bookService.insert(
 input.get("isbn").asText(),
 input.get("quantity").asLong(),
 input.get("price").asDouble()
 )
 }.
 single().
 flatMap {
 bookService.find(it)
 }.
 single().
 subscribe { Book createdBook ->
 render createdBook
 }
 } } Get a book by ISBN /api/books/1932394842 Get all books /api/books Post to create a new book /api/books
  • 179. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 94 https://github.com/jayway/rest-assured
  • 180. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ abstract class BaseDocumentationSpec extends Specification {
 
 @Shared
 ApplicationUnderTest aut = new ExampleBooksApplicationUnderTest()
 
 @Rule
 JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation()
 
 protected RequestSpecification documentationSpec
 
 void setup() {
 this.documentationSpec = new RequestSpecBuilder()
 .addFilter(documentationConfiguration(restDocumentation))
 .build()
 }
 } 95
  • 181. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 96
  • 183. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Blog Post https://jennstrater.blogspot.com/2017/01/using-spring-rest-docs-to-document.html 98
  • 185. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Outcomes • Made it to production! :) • Team was happy with Spring REST Docs • Other dev teams like to see the examples X
  • 186. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Read the Docs for More On… • Adding Security and Headers • Documenting Constraints • Hypermedia Support • XML Support • Using Markdown instead of Asciidoc • Third Party Extensions for WireMock, Jersey, Spring Cloud Contracts, AutoRestDocs 100
  • 188. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 102 Definitions Swagger (OpenAPI Specification) RAML Testing MockMVC RestAssured Documentation AsciiDoc Markdown Wikis Swagger UI Swagger2Markup Spring REST Docs AssertJ- Swagger Contract-First
  • 189. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Conclusion • API documentation is complex • Choosing the right tool for the job not just about the easiest one to setup • Spring REST Docs is a promising tool to enforce good testing and documentation practices without muddying source code. • I still hate writing boilerplate documentation, but at least it’s a little less painful now. X
  • 190. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Next Steps • Join the Groovy Community on Slack groovycommunity.com • Join #spring-restdocs on gitter https://gitter.im/spring-projects/spring-restdocs 103
  • 191. Learn More. Stay Connected. https://speakerdeck.com/jlstrater/test-driven-docs-springone-2017 Follow on Twitter @codeJENNerator 104 #springone@s1p