-
Notifications
You must be signed in to change notification settings - Fork 1
Documenting a Spring REST API following the OpenAPI specification
The OpenAPI specification defines how to write HTTP APIs that can be consumed by any programming language and provide insight into the APIs’ functionality without access to source code or documentation. In other words, following the specification makes it easier for consumers to understand what it does and how to use it. Tools, such as Swagger, can then be used to display documentation without developers maintaining documentation separate from an API’s code.
springdoc-openapi is a library that automatically generates documentation for OpenAPI-compliant REST APIs built with Spring. It inspects an application’s code at runtime, looking at HTTP endpoints, their annotations, and returned objects, and uses this information to generate documentation.
The library provides support for standard Spring web code (e.g. endpoints defined in @RestControllers/@Controllers) and Spring Webflux.
To top everything off, springdoc-openapi can start a Swagger UI based on the documentation it generates, making it even easier for users to understand and interact with your APIs.
We need add the following dependencies
{
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.4'
}
Spring Boot-related libraries scan @RestControllers (and @Controllers) for HTTP endpoints, generating OpenAPI related documentation based on the scan results.
@RestController
@RequestMapping("/people")
public class PersonController {
private final PersonRepository personRepository;
PersonController(PersonRepository personRepository) {
this.personRepository = personRepository;
}
@GetMapping
public ResponseEntity<Iterable<Person>> all() {
return ResponseEntity.ok(personRepository.findAll());
}
@GetMapping("/{id}")
public ResponseEntity<Person> get(@PathVariable("id") UUID id) {
return personRepository.findById(id).map(ResponseEntity::ok)
.orElseThrow(() -> new NoSuchElementException("Person with id: " + id + " does not exist"));
}
@PostMapping
public ResponseEntity<Person> post(@RequestBody Person person) {
Person saved = personRepository.save(
new Person(
UUID.randomUUID(),
person.getFirstName(),
person.getLastName()
)
);
URI uri =
MvcUriComponentsBuilder.fromController(getClass())
.path("/{id}")
.buildAndExpand(saved.getId())
.toUri();
return ResponseEntity.created(uri).body(saved);
}
@PutMapping("/{id}")
public ResponseEntity<Person> put(@PathVariable("id") UUID id, @RequestBody Person person) {
if (!personRepository.existsById(id)) {
return ResponseEntity.notFound().build();
} else {
Person saved = personRepository.save(
new Person(
id,
person.getFirstName(),
person.getLastName()
)
);
return ResponseEntity.ok(saved);
}
}
@DeleteMapping("/{id}")
public ResponseEntity<Void> delete(@PathVariable("id") UUID id) {
if (!personRepository.existsById(id)) {
return ResponseEntity.notFound().build();
} else {
personRepository.deleteById(id);
return ResponseEntity.noContent().build();
}
}
}
The output for the controller above is shown below: