Open Credo

July 28, 2015 | Microservices

Documenting REST APIs – a tooling review

Recently I co-presented a talk at Goto Amsterdam on lessons learnt whilst developing with a Microservices architecture; one being the importance of defining and documenting your API contracts as early as possible in the development cycle. During the talk I mentioned a few API documentation tools that I’d used and, based on feedback and questions from attendees, I realised that this topic merited a blog post. So, the purpose of this is to introduce 5 tools which help with designing, testing and documenting APIs.

WRITTEN BY

Stephen Judd

Stephen Judd

I’ve spent the last few months leading a team developing a Microservices application using the Spring Boot framework, so all tools will be discussed in the context of their support for Spring Boot, however, only 2 of the tools are purely for Spring, the other 3 support a range of languages and frameworks.

The criteria used to review these tools covers:

The tools are:

  1. Swagger
  2. Spring REST Docs
  3. RAML
  4. ApiDocJS
  5. SpringRestDoc

For each of the above I used an example Spring Boot Rest service application to demonstrate how it documents the API contracts, what the resulting documentation looks like and provide insight on when it might be appropriate to use. The example app exposes a set of CRUD APIs for storing details about books (apologies for lack of originality) and it can be downloaded/cloned from this Git repo: https://github.com/cyberbliss/springboot-rest-example .

To run it requires you to have Java and Maven installed (I’ve tested using Java 8 and Maven 3.2). Once you have cloned/downloaded the source, use this command from your CLI to run the application:

mvn spring-boot:run

Once started you can access the APIs on localhost:9080, e.g.

http://localhost:9080/api/books

Swagger

http://swagger.io

This tool is probably the most well-known of them all for documenting Rest APIs – its basically a REST API ecosystem consisting of several aspects:

  • The Swagger spec: a way of documenting APIs using JSON
  • An Editor for designing API contracts first, i.e. before any code
  • A Web UI which takes a Swagger spec and dynamically converts it into API documentation in a web page
  • Many plugins for integrating Swagger with your language/framework of choice
  • Code generators for turning a Swagger spec into skeleton code (server and client)

I’ve used Swagger with a Java library called Springfox (http://springfox.github.io/springfox/docs/current/) which is designed to generate a Swagger spec from APIs built using the Spring framework. It does this by recognising the Spring REST annotations and converting these to the appropriate Swagger spec elements and then exposing an endpoint which, when called, returns the spec in json format. Springfox also supports the Swagger annotations (@Api, @ApiOperation etc) which enables you to provide additional details, e.g. descriptions.
The instructions below summarise how to integrate Springfox with a Spring Boot app and there is a working version in my example app:

  1. Add this dependency to your application’s pom:

<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.0.2</version>
</dependency>

  1. Create a SwaggerConfig class (there is an example in the example Books application)
  1. If you are using Swagger UI to generate your app’s API documentation using the Springfox endpoint you will need to define a CORS filter (if Swagger UI is running from a different host domain). An example CORSFilter class is provided in the Books application.
  1. Download Swagger UI and access it by opening path/to/swagger-ui/dist/index.html in your browser
  1. Launch Books app, e.g. from the command line with mvn spring-boot:run
  1. Load Swagger UI by opening dist/index.html in your browser
  1. The URL to retrieve the Book app’s Swagger 2 spec is http://localhost:9080/v2/api-docs. Paste it into the field at the top of the Swagger UI page and hit Enter; you should then see something similar to the screenshot below:

Swagger UI screenshot

It is fairly straight-forward to integrate Springfox into Spring and clearly a major benefit is that there is no requirement to write anything extra as Springfox uses the Spring REST annotations already present in your code. Of course, the downside to this is that you have to have written the code first, or at least enough to include all the annotations. Another downside is that in order for Swagger UI to pick up the API spec the Spring application has to be running in order that the endpoint is available.

An alternative to Springfox (which I haven’t tried) is a Swagger Maven plugin (http://kongchen.github.io/swagger-maven-plugin/) which scans the Spring app for Swagger annotations and writes to a file the generated Swagger spec – this could be configured to run at build time, for example. Unfortunately this plugin doesn’t recognise Spring’s REST annotations.

Sadly, the current Swagger spec (v2.0) has no support for HATEOAS and there doesn’t seem much intent to do so in the future.

Spring REST Docs

http://docs.spring.io/spring-restdocs/docs/1.0.0.M1/reference/html5

This is an official Spring project, the aim of which is to assist with the production of REST API documentation by hooking into the Spring MVC Test library. The idea is you write a test for each resource which describes the expected request and response and, if the actual matches the expected then documentation will be generated in Asciidoctor format. The deliberate consequence of this is that the API documentation will match reality. The project also provides the ability to manually add further documentation and supports HATEOAS (with out of the box support for Atom and HAL formats).

Integrating with Spring was straight-forward and the documentation is helpful. The instructions below summarise how to integrate Spring REST Docs with a Spring Boot app and there is a working version in my example app:

  1. Add this dependency to your application’s pom:

<dependency>
<groupId>org.springframework.restdocs</groupId>
<artifactId>spring-restdocs</artifactId>
<version>1.0.0.M1</version>
<scope>test</scope>
</dependency>

  1. Define the output directory for the documentation files using a Maven property in your pom, e.g.

<snippetsDirectory>
${project.build.directory}/generated-ascii-doc
</snippetsDirectory>

  1. Write a Test class which both tests and documents your APIs, There is an example class, SpringRestDocsAPIDocumentationTest, in the Books application. Running the tests in this class will not only test the API contracts but also, if they pass, write the various details about the APIs (request, response, fields etc) to Asciidoc format files in the previously specified snippets directory.
  2. Create an Asciidoc format file which contains the API descriptions and use Asciidoc’s include command to insert the generated Asciidoc files in the appropriate places. There is an example in src/main/asciidoc
  3. Use the Asciidoctor Maven plugin (http://asciidoctor.org/docs/asciidoctor-maven-plugin/) to publish the API documentation in HTML format. To do this for the example Book application execute mvn package – this will create the HTML file in target/generated-html-docs/api-documentation.html

An example of the documentation produced is shown below:

Spring REST Docs screenshot

RAML

http://raml.org

RAML (RESTful API Modelling Language) provides a yaml based specification for describing REST APIs. On GitHub there are many projects providing tools for use with RAML: parsers for various languages, e.g. Java, Python, Javascript, Ruby; UIs to help write your API spec; documentation generators and libraries to help test whether an API implementation matches its RAML definition.

Despite being a fan of yaml I discovered that using it to describe APIs was not at all fun; akin to handcrafting a SOAP WSDL (for those old enough to remember). Fortunately there are a few tools to help reduce the pain, e.g. a syntax highlighter for Sublime and API Designer which is a browser based editor to help write the yaml. The RAML spec file which describes the Book APIs can be found in src/main/resources/api.yaml in the example app.
This screenshot shows a fragment of the yaml within the API Designer tool:

RAML API Designer screenshot

There are a few projects on GitHub for converting a RAML spec into human readable documentation, unfortunately none support Asciidoc. Instead I used raml2html – a command line tool which produces HTML – the resulting web page looks like this:

Spring REST Docs documentation screenshot

There is no support in the current RAML spec for HATEOAS, although, judging by the comments in their forum, it is on the radar for a future release.

Other tools

In the course of my investigations I came across a couple of other tools that, whilst nowhere near as feature-rich as the previous 3 are still worthy of mention.

ApiDocJS

http://apidocjs.com

This tool is written as an NPM module (so you’ll need Node installed to use it) and supports a wide number of languages including Java, Go, C++, Ruby, PHP and Python. Essentially you document your APIs using pseudo annotations within a comment block in your code – the tool then parses these comment blocks and generates some static web pages containing the actual documentation.

The following is an example of using the pseudo annotations:

/**
* @api {get} /api/book/:isbn Get a book via its ISBN code
* @apiName getBookByIsbn
* @apiGroup Books
*
* @apiParam {String} isbn The book's unique ISBN code
*
* @apiSampleRequest http://localhost:8095/api/book/111-1
*
* @apiSuccess {String} isbn Book's ISBN
* @apiSuccess {String} title Title of book
* @apiSuccess {String} author Book's author
* @apiSuccessExample {json} Success-Response:
*     HTTP/1.1 200 OK
*     {
"isbn": "111-1",
"title": "Java 8 Lamdas",
"author": "Richard Warburton"
}
*
*/

As I create an Interface class for each of my Spring Rest Controllers, I found putting the ApiDocJS style comments in the Interface effective and it was straightforward to include Maven tasks in the application’s pom to call the tool and publish the generated artefacts to an nginx server.

ApiDocJS has a very small learning curve, generates clean, modern looking web pages and its usage documentation is clear. I also like the fact that the documentation is close to the code and that you can write it without having first written any code (I don’t count creating an empty Interface as writing code). However, the obvious downside to this tool is that the quality of the documentation will only be as good as the quality of the comments manually entered by the developers; so, if your developers are not diligent about keeping the comments updated when the APIs are changed the documentation will quickly become useless. The tool makes no effort to generate example requests and responses so the onus is on the developer to provide these using the annotations: @apiParamExample and @apiSuccessExample – one annoyance is that no pretty print style formatting is done on the supplied json, so you have to do the indenting manually.

There is nothing in the tool to inherently support HATEOAS, so you would need to use the @apiSuccessExample annotation to provide an example.

To generate the documentation via the command line use this Maven command:

mvn exec:exec

This generates all the necessary html, css, javascript within the ./target/apidocs directory – to view it in your browser load ./target/apidocs/index.html

SpringRestDoc

https://bitbucket.org/tritales/springrestdoc/overview

As its name suggests this is a tool specifically aimed at Spring; like Springfox it is Spring REST annotation aware and will generate API documentation, in Asciidoctor format, for any class annotated with @RestController. It takes advantage of Spring’s support for MockMVC and so execution requires creating a mock (pun intended) test which essentially interrogates the Spring MVC RequestMappingHandlerMapping object for details of the REST API methods and outputs the result in json or AsciiDoc format.
The instructions below summarise how to integrate SpringRestDoc with a Spring Boot app and there is a working version in the example Books app:

  1. Add this dependency to your application’s pom:


<dependency>
<groupId>nl.tritales.springrestdoc</groupId>
<artifactId>springrestdoc</artifactId>
<version>0.1.0</version>
<scope>test</scope>
</dependency>

  1. Create a Mock test class to setup MockMvc and SpringRestDoc to write out to a file the API documentation (in either json or AsciiDoc format). There is an example class, SpringRestDocAPIDocumentationTest, in the Books application. Run this class and it will create a target/generated-ascii-doc/spring-restdoc.asciidoc file.
  1. Inevitably there is an Asciidoctor plugin for Maven which converts the output to HTML. To convert the file produced above into a web page execute this Maven command via the CLI:mvn asciidoctor:process-asciidocThis will generate an HTML file in target/generated-ascii-doc.

This project is in its early stages and is the product of one developer. The documentation produced is minimal, too much so to be particularly useful. Hopefully this will change with future releases.

Summary / Rest API tooling review

Out of the 5 rest API tools I’ve investigated there are 3 which I would seriously consider next time I need to document some APIs: Swagger, Spring Rest Docs and RAML and in the table below I’ve summarised why and when you might choose one instead of another.

Rest API tooling review Swagger Spring Rest Docs RAML
Best used for Both top-down (contract first) and bottom up (code first) design Ensuring that your API documentation accurately reflects your Spring REST API implementation Contract first design
Language support Documenting an API contract is language neutral, but there is tooling for: Javascript, Java, Clojure, Go, .Net, Perl, PHP, Python, Ruby Java (Spring MVC) Documenting an API contract is language neutral, but there is tooling for: Java, Javascript, .Net, PHP, Python, Ruby
Hypermedia support No Yes No
Build phase integration Yes, via Maven plugins Straightforward with Maven or Gradle To a degree – there are some CLI tools to convert spec to documentation
Related GitHub projects approx. 1300 N/A approx. 400

RETURN TO BLOG

SHARE

Twitter LinkedIn Facebook Email

SIMILAR POSTS

Blog