Challenge
Documentation helps the consumer understand how to use your API.
Launch the Starter Project
OpenAPI
OpenAPI is a standard format that defines the capabilities of a REST API.
Below is a snippet from an OpenAPI specification that describes:
- The path for one of the operations, as well as a description of what it does.
- Parameters to be included for the operation to succeed.
- The response to expect if the client makes a good request.
Computers can read the OpenAPI spec and generate human-friendly documentation.
In turn, consumers can read the documentation and learn how to use your API.
Purpose of this Challenge
In this challenge, you will generate documentation for the Contact API.
Dependencies
The starter project includes the OpenAPI dependency.
Side Note
If you remove the version, Maven will not know which version of your dependency to grab:
Conversely, the parent POM (Spring Boot Starter Parent) takes care of dependency management for Spring Boot starters.
Task 1
Run the application, and navigate to http://localhost:8080/v3/api-docs
.
An OpenAPI spec that documents your application is autogenerated. If you format the JSON, notice that it detects and documents every operation:
Navigate to http://localhost:8080/swagger-ui/index.html
.
Task 2
The next task is to configure the OpenAPI definition:
- Create a new folder called
config
. - Create a new class called
OpenApiConfig
. - Mark this class as a source of bean definitions (hint: see cheat sheet from the beans section).
- Create a bean definition named:
openAPI
that returns anOpenAPI
object.
Task 3
Behind the scenes, Spring Boot can leverage the OpenAPI bean to update the:
- Title.
- Version.
- Description of what the API does.
Consult the Spring Documentation, and scroll down until it discusses the OpenAPI bean. Take inspiration from the docs, and configure your OpenAPI bean to achieve the following output:
Task 4
@Tag
can group operations together.
If you look inside the current OpenAPI definition, every operation has a contact-controller
tag.
As a result, Swagger
groups the operations under the same tag.
Your next exercise is to apply the @Tag(name = "name")
annotation to each operation.
Task 5
@Tag can be applied at the class or method level.
Given that @Tag
has attributes of name
and description
:
- Group every operation under the tag: Contact Controller.
- Provide a general description of:
"Create and retrieve contacts"
.
Task 6
Use @Operation
at the method level to provide each operation with a summary and description.
getContacts
- summary: Retrieves contacts
- description: Provides a list of all contacts
getContact
- summary: Get contact by Id
- description: Returns a contact based on an ID
createContact
- summary: Create Contact
- description: Creates a contact from the provided payload
Task 7
@ApiResponse
documents how each operation responds.
Apply it at the level of each method:
getContacts
import io.swagger.v3.oas.annotations.media.*; import io.swagger.v3.oas.annotations.responses.ApiResponse; @ApiResponse(responseCode = "200", description = "Successful retrieval of contacts", content = @Content(array = @ArraySchema(schema = @Schema(implementation = Contact.class))))
This reads like english. The operation will:
- Return a status code of 200.
- Retrieve all contacts from the datastore.
- Return a JSON Array of Contact resources.
getContact
@ApiResponses(value = {
@ApiResponse(responseCode = "404", description = "Contact doesn't exist", content = @Content(schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(responseCode = "200", description = "Successful retrieval of contact", content = @Content(schema = @Schema(implementation = Contact.class))),
})
Since getContact
is also prone to a 404 response, it must be documented to the consumer as well
createContact
@ApiResponses(value = {
@ApiResponse(responseCode = "201", description = "Successful creation of contact"),
@ApiResponse(responseCode = "400", description = "Bad request: unsuccessful submission", content = @Content(schema = @Schema(implementation = ErrorResponse.class)))
})
Task 8
Add the following attribute to each @RequestMapping
:
@GetMapping(value = "/contact/all",
produces = MediaType.APPLICATION_JSON_VALUE)
This will specify that the operation produces a JSON.
Final Remarks
Congratulations! You just documented your API. Consumers can use it to understand how it works.