Document RESTful services by combining hand-written documentation with auto-generated snippets produced with Spring MVC Test.

Introduction

The aim of Spring REST Docs is to help you to produce documentation for your RESTful services that is accurate and readable.

Writing high-quality documentation is difficult. One way to ease that difficulty is to use tools that are well-suited to the job. To this end, Spring REST Docs uses Asciidoctor. Asciidoctor processes plain text and produces HTML, styled and layed out to suit your needs.

Spring REST Docs makes use of snippets produced by tests written with Spring MVC Test. This test-driven approach helps to guarantee the accuracy of your service’s documentation. If a snippet is incorrect the test that produces it will fail.

Documenting a RESTful service is largely about describing its resources. Two key parts of each resource’s description are the details of the HTTP requests that it consumes and the HTTP responses that it produces. Spring REST Docs allows you to work with these resources and the HTTP requests and responses, shielding your documentation from the inner-details of your service’s implementation. This separation helps you to document your service’s API rather than its implementation. It also frees you to evolve the implementation without having to rework the documentation.

Getting started

This section describes how to get started with Spring REST Docs.

Sample applications

If you want to jump straight in, there are two sample applications available. One sample uses Spring HATEOAS and the other uses Spring Data REST. Both samples use Spring REST Docs to produce a detailed API guide and a getting started walkthrough.

Each sample contains a file named api-guide.adoc that produces an API guide for the service, and a file named getting-started-guide.adoc that produces a getting started guide that provides an introductory walkthrough.

The code that produces the generated snippets can be found in src/test/java. ApiDocumentation.java produces the snippets for the API guide. GettingStartedDocumentation.java produces the snippets for the getting started guide.

Build configuration

The first step in using Spring REST Docs is to configure your project’s build.

Gradle build configuration

The Spring HATEOAS sample contains a build.gradle file that you may wish to use as a reference. The key parts of the configuration are described below.

plugins { (1)
	id "org.asciidoctor.convert" version "1.5.2"
}

dependencies { (2)
	testCompile 'org.springframework.restdocs:spring-restdocs-mockmvc:1.0.2.RELEASE'
}

ext { (3)
	snippetsDir = file('build/generated-snippets')
}

test { (4)
	outputs.dir snippetsDir
}

asciidoctor { (5)
	attributes 'snippets': snippetsDir (6)
	inputs.dir snippetsDir (7)
	dependsOn test (8)
}
1 Apply the Asciidoctor plugin.
2 Add a dependency on spring-restdocs-mockmvc in the testCompile configuration.
3 Configure a property to define the output location for generated snippets.
4 Configure the test task to add the snippets directory as an output.
5 Configure the asciidoctor task
6 Define an attribute named snippets that can be used when including the generated snippets in your documentation.
7 Configure the snippets directory as an input.
8 Make the task depend on the test task so that the tests are run before the documentation is created.

Packaging the documentation

You may want to package the generated documentation in your project’s jar file, for example to have it served as static content by Spring Boot. You can do so by configuring the jar task to depend on the asciidoctor task and to copy the generated documentation into the jar’s static directory:

jar {
	dependsOn asciidoctor
	from ("${asciidoctor.outputDir}/html5") {
		into 'static/docs'
	}
}

Maven build configuration

The Spring Data REST sample contains a pom.xml file that you may wish to use as a reference. The key parts of the configuration are described below.

<dependency> (1)
	<groupId>org.springframework.restdocs</groupId>
	<artifactId>spring-restdocs-mockmvc</artifactId>
	<version>1.0.2.RELEASE</version>
	<scope>test</scope>
</dependency>

<properties> (2)
	<snippetsDirectory>${project.build.directory}/generated-snippets</snippetsDirectory>
</properties>

<build>
	<plugins>
		<plugin> (3)
			<groupId>org.apache.maven.plugins</groupId>
			<artifactId>maven-surefire-plugin</artifactId>
			<configuration>
				<includes>
					<include>**/*Documentation.java</include>
				</includes>
			</configuration>
		</plugin>
		<plugin> (4)
			<groupId>org.asciidoctor</groupId>
			<artifactId>asciidoctor-maven-plugin</artifactId>
			<version>1.5.2</version>
			<executions>
				<execution>
					<id>generate-docs</id>
					<phase>prepare-package</phase> (6)
					<goals>
						<goal>process-asciidoc</goal>
					</goals>
					<configuration>
						<backend>html</backend>
						<doctype>book</doctype>
						<attributes>
							<snippets>${snippetsDirectory}</snippets> (5)
						</attributes>
					</configuration>
				</execution>
			</executions>
		</plugin>
	</plugins>
</build>
1 Add a dependency on spring-restdocs-mockmvc in the test scope.
2 Configure a property to define the output location for generated snippets.
3 Add the SureFire plugin and configure it to include files whose names end with Documentation.java.
4 Add the Asciidoctor plugin
5 Define an attribute named snippets that can be used when including the generated snippets in your documentation.
6 Using prepare-package allows the documentation to be included in the package.

Packaging the documentation

You may want to package the generated documentation in your project’s jar file, for example to have it served as static content by Spring Boot.

Configure Maven’s resources plugin to copy the generated documentation into a location where it’ll be included in the project’s jar:

<plugin> (1)
	<groupId>org.asciidoctor</groupId>
	<artifactId>asciidoctor-maven-plugin</artifactId>
	<!-- … -->
</plugin>
<plugin> (2)
	<artifactId>maven-resources-plugin</artifactId>
	<version>2.7</version>
	<executions>
		<execution>
			<id>copy-resources</id>
			<phase>prepare-package</phase>
			<goals>
				<goal>copy-resources</goal>
			</goals>
			<configuration>
				<outputDirectory>
					${project.build.outputDirectory}/static/docs
				</outputDirectory>
				<resources>
					<resource>
						<directory>
							${project.build.directory}/generated-docs
						</directory>
					</resource>
				</resources>
			</configuration>
		</execution>
	</executions>
</plugin>
1 The existing declaration for the Asciidoctor plugin.
2 The resource plugin must be declared after the Asciidoctor plugin as they are bound to the same phase (prepare-package) and the resource plugin must run after the Asciidoctor plugin.

Generating documentation snippets

Spring REST Docs uses Spring’s MVC Test framework to make requests to the service that you are documenting. It then produces documentation snippets for request and resulting response.

Setting up Spring MVC test

The first step in generating documentation snippets is to declare a public RestDocumentation field that’s annotated as a JUnit @Rule. The RestDocumentation rule is configured with the output directory into which generated snippets should be written. This output directory should match the snippets directory that you have configured in your build.gradle or pom.xml file.

For Maven (pom.xml that will typically be target/generated-snippets:

@Rule
public RestDocumentation restDocumentation = new RestDocumentation("target/generated-snippets");

And for Gradle (build.gradle) it will typically be build/generated-snippets:

@Rule
public RestDocumentation restDocumentation = new RestDocumentation("build/generated-snippets");

Next, provide an @Before method that creates a MockMvc instance:

@Autowired
private WebApplicationContext context;

private MockMvc mockMvc;

@Before
public void setUp() {
	this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
			.apply(documentationConfiguration(this.restDocumentation))
			.build();
}

The MockMvc instance is configured using a RestDocumentationMockMvcConfigurer. An instance of this class can be obtained from the static documentationConfiguration() method on org.springframework.restdocs.mockmvc.MockMvcRestDocumentation. RestDocumentationMockMvcConfigurer applies sensible defaults and also provides an API for customizing the configuration. Refer to the configuration section for more information.

Invoking the RESTful service

Now that a MockMvc instance has been created, it can be used to invoke the RESTful service and document the request and response. For example:

this.mockMvc.perform(get("/").accept(MediaType.APPLICATION_JSON)) (1)
	.andExpect(status().isOk()) (2)
	.andDo(document("index")); (3)
1 Invoke the root (/) of the service and indicate that an application/json response is required.
2 Assert that the service produced the expected response.
3 Document the call to the service, writing the snippets into a directory named index that will be located beneath the configured output directory. The snippets are written by a RestDocumentationResultHandler. An instance of this class can be obtained from the static document method on org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.

By default, three snippets are written:

  • <output-directory>/index/curl-request.adoc

  • <output-directory>/index/http-request.adoc

  • <output-directory>/index/http-response.adoc

Refer to Documenting your API for more information about these and other snippets that can be produced by Spring REST Docs.

Using the snippets

The generated snippets can be included in your documentation using the include macro. The snippets attribute specified in the build configuration can be used to reference the snippets output directory. For example:

include::{snippets}/index/curl-request.adoc[]

Documenting your API

This section provides more details about using Spring REST Docs to document your API.

Hypermedia

Spring REST Docs provides support for documenting the links in a Hypermedia-based API:

this.mockMvc.perform(get("/").accept(MediaType.APPLICATION_JSON))
	.andExpect(status().isOk())
	.andDo(document("index", links( (1)
			linkWithRel("alpha").description("Link to the alpha resource"), (2)
			linkWithRel("bravo").description("Link to the bravo resource")))); (3)
1 Configure Spring REST docs to produce a snippet describing the response’s links. Uses the static links method on org.springframework.restdocs.hypermedia.HypermediaDocumentation.
2 Expect a link whose rel is alpha. Uses the static linkWithRel method on org.springframework.restdocs.hypermedia.HypermediaDocumentation.
3 Expect a link whose rel is bravo.

The result is a snippet named links.adoc that contains a table describing the resource’s links.

When documenting links, the test will fail if an undocumented link is found in the response. Similarly, the test will also fail if a documented link is not found in the response and the link has not been marked as optional.

If you do not want to document a link, you can mark it as ignored. This will prevent it from appearing in the generated snippet while avoiding the failure described above.

Two link formats are understood by default:

  • Atom – links are expected to be in an array named links. Used by default when the content type of the response is compatible with application/json.

  • HAL – links are expected to be in a map named _links. Used by default when the content type of the response is compatible with application/hal+json.

If you are using Atom or HAL-format links but with a different content type you can provide one of the built-in LinkExtractor implementations to links. For example:

.andDo(document("index", links(halLinks(), (1)
		linkWithRel("alpha").description("Link to the alpha resource"),
		linkWithRel("bravo").description("Link to the bravo resource"))));
1 Indicate that the links are in HAL format. Uses the static halLinks method on org.springframework.restdocs.hypermedia.HypermediaDocumentation.

If your API represents its links in a format other than Atom or HAL you can provide your own implementation of the LinkExtractor interface to extract the links from the response.

Request and response payloads

In addition to the hypermedia-specific support described above, support for general documentation of request and response payloads is also provided. For example:

this.mockMvc.perform(get("/user/5").accept(MediaType.APPLICATION_JSON))
	.andExpect(status().isOk())
	.andDo(document("index", responseFields( (1)
			fieldWithPath("contact").description("The user's contact details"), (2)
			fieldWithPath("contact.email").description("The user's email address")))); (3)
1 Configure Spring REST docs to produce a snippet describing the fields in the response payload. To document a request requestFields can be used. Both are static methods on org.springframework.restdocs.payload.PayloadDocumentation.
2 Expect a field with the path contact. Uses the static fieldWithPath method on org.springframework.restdocs.payload.PayloadDocumentation.
3 Expect a field with the path contact.email.

The result is a snippet that contains a table describing the fields. For requests this snippet is named request-fields.adoc. For responses this snippet is named response-fields.adoc.

When documenting fields, the test will fail if an undocumented field is found in the payload. Similarly, the test will also fail if a documented field is not found in the payload and the field has not been marked as optional. For payloads with a hierarchical structure, documenting a field is sufficient for all of its descendants to also be treated as having been documented.

If you do not want to document a field, you can mark it as ignored. This will prevent it from appearing in the generated snippet while avoiding the failure described above.

By default, Spring REST Docs will assume that the payload you are documenting is JSON. If you want to document an XML payload the content type of the request or response must be compatible with application/xml.

JSON payloads

JSON field paths

JSON field paths use either dot notation or bracket notation. Dot notation uses '.' to separate each key in the path; a.b, for example. Bracket notation wraps each key in square brackets and single quotes; ['a']['b'], for example. In either case, [] is used to identify an array. Dot notation is more concise, but using bracket notation enables the use of . within a key name; ['a.b'], for example. The two different notations can be used in the same path; a['b'], for example.

With this JSON payload:

{
	"a":{
		"b":[
			{
				"c":"one"
			},
			{
				"c":"two"
			},
			{
				"d":"three"
			}
		],
		"e.dot" : "four"
	}
}

The following paths are all present:

Path Value

a

An object containing b

a.b

An array containing three objects

['a']['b']

An array containing three objects

a['b']

An array containing three objects

['a'].b

An array containing three objects

a.b[]

An array containing three objects

a.b[].c

An array containing the strings one and two

a.b[].d

The string three

a['e.dot']

The string four

['a']['e.dot']

The string four

A response that uses an array at its root can also be documented. The path [] will refer to the entire array. You can then use bracket or dot notation to identify fields within the array’s entries. For example, [].id corresponds to the id field of every object found in the following array:

[
	{
		"id":1
	},
	{
		"id":2
	}
]
JSON field types

When a field is documented, Spring REST Docs will attempt to determine its type by examining the payload. Seven different types are supported:

Type Description

array

The value of each occurrence of the field is an array

boolean

The value of each occurrence of the field is a boolean (true or false)

object

The value of each occurrence of the field is an object

number

The value of each occurrence of the field is a number

null

The value of each occurrence of the field is null

string

The value of each occurrence of the field is a string

varies

The field occurs multiple times in the payload with a variety of different types

The type can also be set explicitly using the type(Object) method on FieldDescriptor. The result of the supplied Object's toString method will be used in the documentation. Typically, one of the values enumerated by JsonFieldType will be used:

.andDo(document("index", responseFields(
		fieldWithPath("contact.email")
				.type(JsonFieldType.STRING) (1)
				.optional()
				.description("The user's email address"))));
1 Set the field’s type to string.

XML payloads

XML field paths

XML field paths are described using XPath. / is used to descend into a child node.

XML field types

When documenting an XML payload, you must provide a type for the field using the type(Object) method on FieldDescriptor. The result of the supplied type’s toString method will be used in the documentation.

Request parameters

A request’s parameters can be documented using requestParameters. Request parameters can be included in a GET request’s query string. For example:

this.mockMvc.perform(get("/users?page=2&per_page=100")) (1)
	.andExpect(status().isOk())
	.andDo(document("users", requestParameters( (2)
			parameterWithName("page").description("The page to retrieve"), (3)
			parameterWithName("per_page").description("Entries per page") (4)
	)));
1 Perform a GET request with two parameters, page and per_page in the query string.
2 Configure Spring REST Docs to produce a snippet describing the request’s parameters. Uses the static requestParameters method on org.springframework.restdocs.request.RequestDocumentation.
3 Document the page parameter. Uses the static parameterWithName method on org.springframework.restdocs.request.RequestDocumentation.
4 Document the per_page parameter.

Request parameters can also be included as form data in the body of a POST request:

this.mockMvc.perform(post("/users").param("username", "Tester")) (1)
	.andExpect(status().isCreated())
	.andDo(document("create-user", requestParameters(
			parameterWithName("username").description("The user's username")
	)));
1 Perform a POST request with a single parameter, username.

In both cases, the result is a snippet named request-parameters.adoc that contains a table describing the parameters that are supported by the resource.

When documenting request parameters, the test will fail if an undocumented request parameter is used in the request. Similarly, the test will also fail if a documented request parameter is not found in the request.

If you do not want to document a request parameter, you can mark it as ignored. This will prevent it from appearing in the generated snippet while avoiding the failure described above.

Path parameters

A request’s path parameters can be documented using pathParameters. For example:

this.mockMvc.perform(get("/locations/{latitude}/{longitude}", 51.5072, 0.1275)) (1)
	.andExpect(status().isOk())
	.andDo(document("locations", pathParameters( (2)
			parameterWithName("latitude").description("The location's latitude"), (3)
			parameterWithName("longitude").description("The location's longitude") (4)
	)));
1 Perform a GET request with two path parameters, latitude and longitude.
2 Configure Spring REST Docs to produce a snippet describing the request’s path parameters. Uses the static pathParameters method on org.springframework.restdocs.request.RequestDocumentation.
3 Document the parameter named latitude. Uses the static parameterWithName method on org.springframework.restdocs.request.RequestDocumentation.
4 Document the parameter named longitude.

The result is a snippet named path-parameters.adoc that contains a table describing the path parameters that are supported by the resource.

To make the path parameters available for documentation, the request must be built using one of the methods on RestDocumentationRequestBuilders rather than MockMvcRequestBuilders.

When documenting path parameters, the test will fail if an undocumented path parameter is used in the request. Similarly, the test will also fail if a documented path parameter is not found in the request.

If you do not want to document a path parameter, you can mark it as ignored. This will prevent it from appearing in the generated snippet while avoiding the failure described above.

HTTP headers

The headers in a request or response can be documented using requestHeaders and responseHeaders respectively. For example:

this.mockMvc
		.perform(get("/people").header("Authorization", "Basic dXNlcjpzZWNyZXQ=")) (1)
		.andExpect(status().isOk())
		.andDo(document("headers",
				requestHeaders( (2)
						headerWithName("Authorization").description(
								"Basic auth credentials")), (3)
				responseHeaders( (4)
						headerWithName("X-RateLimit-Limit").description(
								"The total number of requests permitted per period"),
						headerWithName("X-RateLimit-Remaining").description(
								"Remaining requests permitted in current period"),
						headerWithName("X-RateLimit-Reset").description(
								"Time at which the rate limit period will reset"))));
1 Perform a GET request with an Authorization header that uses basic authentication
2 Configure Spring REST Docs to produce a snippet describing the request’s headers. Uses the static requestHeaders method on org.springframework.restdocs.headers.HeaderDocumentation.
3 Document the Authorization header. Uses the static headerWithName method on `org.springframework.restdocs.headers.HeaderDocumentation.
4 Produce a snippet describing the response’s headers. Uses the static responseHeaders method on org.springframework.restdocs.headers.HeaderDocumentation.

The result is a snippet named request-headers.adoc and a snippet named response-headers.adoc. Each contains a table describing the headers.

When documenting HTTP Headers, the test will fail if a documented header is not found in the request or response.

Documenting constraints

Spring REST Docs provides a number of classes that can help you to document constraints. An instance of ConstraintDescriptions can be used to access descriptions of a class’s constraints. For example:

public void example() {
	ConstraintDescriptions userConstraints = new ConstraintDescriptions(UserInput.class); (1)
	List<String> descriptions = userConstraints.descriptionsForProperty("name"); (2)
}

static class UserInput {

	@NotNull
	@Size(min = 1)
	String name;

	@NotNull
	@Size(min = 8)
	String password;
}
1 Create an instance of ConstraintDescriptions for the UserInput class
2 Get the descriptions of the name property’s constraints. This list will contain two descriptions; one for the NotNull constraint and one for the Size constraint.

The ApiDocumentation class in the Spring HATEOAS sample shows this functionality in action.

Finding constraints

By default, constraints are found using a Bean Validation Validator. Currently, only property constraints are supported. You can customize the Validator that’s used by creating ConstraintDescriptions with a custom ValidatorConstraintResolver instance. To take complete control of constraint resolution, your own implementation of ConstraintResolver can be used.

Describing constraints

Default descriptions are provided for all of the Bean Validation 1.1’s constraints:

  • AssertFalse

  • AssertTrue

  • DecimalMax

  • DecimalMin

  • Digits

  • Future

  • Max

  • Min

  • NotNull

  • Null

  • Past

  • Pattern

  • Size

To override the default descriptions, or to provide a new description, create a resource bundle with the base name org.springframework.restdocs.constraints.ConstraintDescriptions. The Spring HATEOAS-based sample contains an example of such a resource bundle.

Each key in the resource bundle is the fully-qualified name of a constraint plus .description. For example, the key for the standard @NotNull constraint is javax.validation.constraints.NotNull.description.

Property placeholder’s referring to a constraint’s attributes can be used in its description. For example, the default description of the @Min constraint, Must be at least ${value}, refers to the constraint’s value attribute.

To take more control of constraint description resolution, create ConstraintDescriptions with a custom ResourceBundleConstraintDescriptionResolver. To take complete control, create ConstraintDescriptions with a custom ConstraintDescriptionResolver implementation.

Using constraint descriptions in generated snippets

Once you have a constraint’s descriptions, you’re free to use them however you like in the generated snippets. For example, you may want to include the constraint descriptions as part of a field’s description. Alternatively, you could include the constraints as extra information in the request fields snippet. The ApiDocumentation class in the Spring HATEOAS-based sample illustrates the latter approach.

Default snippets

A number of snippets are produced automatically when you document a call to MockMvc.perform:

Snippet Description

curl-request.adoc

Contains the curl command that is equivalent to the MockMvc call that is being documented

http-request.adoc

Contains the HTTP request that is equivalent to the MockMvc call that is being documented

http-response.adoc

Contains the HTTP response that was returned

You can configure which snippets are produced by default. Please refer to the configuration section for more information.

Using parameterized output directories

The output directory used by document can be parameterized. The following parameters are supported:

Parameter Description

{methodName}

The unmodified name of the test method

{method-name}

The name of the test method, formatted using kebab-case

{method_name}

The name of the test method, formatted using snake_case

{ClassName}

The unmodified name of the test class

{class-name}

The name of the test class, formatted using kebab-case

{class_name}

The nome of the test class, formatted using snake_case

{step}

The count of calls to MockMvc.perform in the current test

For example, document("{class-name}/{method-name}") in a test method named creatingANote on the test class GettingStartedDocumentation, will write snippets into a directory named getting-started-documentation/creating-a-note.

A parameterized output directory is particularly useful in combination with Spring MVC Test’s alwaysDo functionality. It allows documentation to be configured once in a setup method:

@Before
public void setUp() {
	this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
			.apply(documentationConfiguration(this.restDocumentation))
			.alwaysDo(document("{method-name}/{step}/"))
			.build();
}

With this configuration in place, every call to MockMvc.perform will produce the default snippets without any further configuration. Take a look at the GettingStartedDocumentation classes in each of the sample applications to see this functionality in action.

Customizing the output

Customizing the generated snippets

Spring REST Docs uses Mustache templates to produce the generated snippets. Default templates are provided for each of the snippets that Spring REST Docs can produce. To customize a snippet’s content, you can provide your own template.

Templates are loaded from the classpath in the org.springframework.restdocs.templates package and each template is named after the snippet that it will produce. For example, to override the template for the curl-request.adoc snippet, create a template named curl-request.snippet in src/test/resources/org/springframework/restdocs/templates.

Including extra information

There are two ways to provide extra information for inclusion in a generated snippet:

  1. Use the attributes method on a descriptor to add one or more attributes to it.

  2. Pass in some attributes when calling curlRequest, httpRequest, httpResponse, etc. Such attributes will be associated with the snippet as a whole.

Any additional attributes are made available during the template rendering process. Coupled with a custom snippet template, this makes it possible to include extra information in a generated snippet.

A concrete example of the above is the addition of a constraints column and a title when documenting request fields. The first step is to provide a constraints attribute for each field that you are documenting and to provide a title attribute:

.andDo(document("create-user", requestFields(
		attributes(
				key("title").value("Fields for user creation")), (1)
		fieldWithPath("name")
				.description("The user's name")
				.attributes(
						key("constraints").value("Must not be null. Must not be empty")), (2)
		fieldWithPath("email")
				.description("The user's email address")
				.attributes(
						key("constraints").value("Must be a valid email address"))))); (3)
1 Configure the title attribute for the request fields snippet
2 Set the constraints attribute for the name field
3 Set the constraints attribute for the email field

The second step is to provide a custom template named request-fields.snippet that includes the information about the fields' constraints in the generated snippet’s table and adds a title:

.{{title}} (1)
|===
|Path|Type|Description|Constraints (2)

{{#fields}}
|{{path}}
|{{type}}
|{{description}}
|{{constraints}} (3)

{{/fields}}
|===
1 Add a title to the table
2 Add a new column named "Constraints"
3 Include the descriptors' constraints attribute in each row of the table

Customizing requests and responses

There may be situations where you do not want to document a request exactly as it was sent or a response exactly as it was received. Spring REST Docs provides a number of preprocessors that can be used to modify a request or response before it’s documented.

Preprocessing is configured by calling document with an OperationRequestPreprocessor, and/or an OperationResponsePreprocessor. Instances can be obtained using the static preprocessRequest and preprocessResponse methods on Preprocessors. For example:

this.mockMvc.perform(get("/")).andExpect(status().isOk())
		.andDo(document("index", preprocessRequest(removeHeaders("Foo")), (1)
				preprocessResponse(prettyPrint()))); (2)
1 Apply a request preprocessor that will remove the header named Foo.
2 Apply a response preprocessor that will pretty print its content.

Alternatively, you may want to apply the same preprocessors to every test. You can do so by configuring the preprocessors in your @Before method and using the support for parameterized output directories:

@Before
public void setup() {
	this.document = document(
			"{method-name}", (1)
			preprocessRequest(removeHeaders("Foo")),
			preprocessResponse(prettyPrint()));
	this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
			.alwaysDo(this.document) (2)
			.build();
}
1 Create the RestDocumentationResultHandler, configured to preprocess the request and response.
2 Create the MockMvc instance, configured to always call the documentation result handler.

Then, in each test, the RestDocumentationResultHandler can be configured with anything test-specific. For example:

this.document.snippets( (1)
		links(linkWithRel("self").description("Canonical self link")));
this.mockMvc.perform(get("/")) (2)
		.andExpect(status().isOk());
1 Document the links specific to the resource that is being tested
2 The perform call will automatically produce the documentation snippets due to the use of alwaysDo above.

Various built in preprocessors, including those illustrated above, are available via the static methods on Preprocessors. See below for further details.

Preprocessors

Pretty printing

prettyPrint on Preprocessors formats the content of the request or response to make it easier to read.

If you’re documenting a Hypermedia-based API, you may want to encourage clients to navigate the API using links rather than through the use of hard coded URIs. One way to do this is to limit the use of URIs in the documentation. maskLinks on Preprocessors replaces the href of any links in the response with …​. A different replacement can also be specified if you wish.

Removing headers

removeHeaders on Preprocessors removes any occurrences of the named headers from the request or response.

Replacing patterns

replacePattern on Preprocessors provides a general purpose mechanism for replacing content in a request or response. Any occurrences of a regular expression are replaced.

Writing your own preprocessor

If one of the built-in preprocessors does not meet your needs, you can write your own by implementing the OperationPreprocessor interface. You can then use your custom preprocessor in exactly the same way as any of the built-in preprocessors.

If you only want to modify the content (body) of a request or response, consider implementing the ContentModifier interface and using it with the built-in ContentModifyingOperationPreprocessor.

Configuration

Documented URIs

The default configuration for URIs documented by Spring REST Docs is:

Setting Default

Scheme

http

Host

localhost

Port

8080

This configuration is applied by RestDocumentationMockMvcConfigurer. You can use its API to change one or more of the defaults to suit your needs:

this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
		.apply(documentationConfiguration(this.restDocumentation).uris()
				.withScheme("https")
				.withHost("example.com")
				.withPort(443))
		.build();
To configure a request’s context path, use the contextPath method on MockHttpServletRequestBuilder.

Snippet encoding

The default encoding used by Asciidoctor is UTF-8. Spring REST Docs adopts the same default for the snippets that it generates. If you require an encoding other than UTF-8, use RestDocumentationMockMvcConfigurer to configure it:

this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
		.apply(documentationConfiguration(this.restDocumentation).snippets()
				.withEncoding("ISO-8859-1"))
		.build();
When Spring REST Docs converts a request or response’s content to a String, the charset specified in the Content-Type header will be used if it is available. In its absence, the JVM’s default Charset will be used. The JVM’s default Charset can be configured using the file.encoding system property.

Default snippets

Three snippets are produced by default:

  • curl-request

  • http-request

  • http-response

This default configuration is applied by RestDocumentationMockMvcConfigurer. You can use its API to change the configuration. For example, to only produce the curl-request snippet by default:

this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
		.apply(documentationConfiguration(this.restDocumentation).snippets()
				.withDefaults(curlRequest()))
		.build();

Working with Asciidoctor

This section describes any aspects of working with Asciidoctor that are particularly relevant to Spring REST Docs.

Including snippets

The include macro is used to include generated snippets in your documentation. The snippets attribute specified in the build configuration can be used to reference the snippets output directory, for example:

include::{snippets}/index/curl-request.adoc[]

Customizing tables

Many of the snippets contain a table in its default configuration. The appearance of the table can be customized, either by providing some additional configuration when the snippet is included or by using a custom snippet template.

Formatting columns

Asciidoctor has rich support for formatting a table’s columns. For example, the widths of a table’s columns can be specified using the cols attribute:

[cols=1,3] (1)
include::{snippets}/index/links.adoc[]
1 The table’s width will be split across its two columns with the second column being three times as wide as the first.

Configuring the title

The title of a table can be specified using a line prefixed by a .:

.Links (1)
include::{snippets}/index/links.adoc[]
1 The table’s title will be Links.

Further reading

Refer to the Tables section of the Asciidoctor user manual for more information about customizing tables.

Contributing

Spring REST Docs is intended to make it easy for you to produce high-quality documentation for your RESTful services. However, we can’t achieve that goal without your contributions.

Questions

You can ask questions about Spring REST Docs on StackOverflow using the spring-restdocs tag. Similarly, we encourage you to help your fellow Spring REST Docs users by answering questions.

Bugs

If you believe you have found a bug, please take a moment to search the existing issues. If no one else has reported the problem, please open a new issue that describes the problem in detail and, ideally, includes a test that reproduces it.

Enhancements

If you’d like an enhancement to be made to Spring REST Docs, pull requests are most welcome. The source code is on GitHub. You may want to search the existing issues and pull requests to see if the enhancement is already being worked on. You may also want to open a new issue to discuss a possible enhancement before work on it begins.