# Dokumentation
Um eine API benutzen zu können, muss man wissen, wie man sie aufrufen kann – also welche Endpunkte gibt es, welche Parameter sind zu übergeben, was kommt zurück. Deshalb sollte eine Dokumentation der API angefertigt werden. Es gibt mehrere Arten dies zu tun, die aufwändigste wäre sicherlich das manuelle Zusammenschreiben in einem mehr oder weniger definiertem Format.
Da das niemand tun möchte, wird hier eine Möglichkeit vorgestellt, anhand des Codes (@RestController etc.) ein maschinenlesbares (JSON, YAML), standardisiertes Format zu erzeugen, was auch übersichtlich dargestellt werden kann. Die Rede ist von OpenAPI (opens new window) (Version 3, die Version 2 hieß früher Swagger). Dort wurde ein Format (opens new window) spezifiziert, welches von diversen Tools und Projekten unterstützt wird. Das einerseits, um die API-Dokumentation anhand des Codes zu erstellen, andererseits aber auch, um Client-Bibliotheken anhand der Doku zu erzeugen.
Für Spring (Web und Webflux) gibt es springdoc-openapi (opens new window). Diese Bibliothek stellt dem Entwickler automatische Endpunkte für seine Anwendung zur Verfügung, bei denen u. a. das maschinenlesbare Format ausgeliefert wird. Aber auch ein Browser-Interface in Form einer interaktiven Dokumentation wird mitgeliefert (eine Demo davon findet man hier (opens new window)).
# Installation
Folgende Dependencies sind dem Projekt hinzuzufügen (ggf. neuere Versionen einsetzen):
// https://mvnrepository.com/artifact/org.springdoc/springdoc-openapi-webflux-ui
implementation("org.springdoc:springdoc-openapi-webflux-ui:1.5.3")
// https://mvnrepository.com/artifact/org.springdoc/springdoc-openapi-data-rest
implementation("org.springdoc:springdoc-openapi-data-rest:1.5.3")
// https://mvnrepository.com/artifact/org.springdoc/springdoc-openapi-kotlin
implementation("org.springdoc:springdoc-openapi-kotlin:1.5.3")
# Endpunkte
Damit sind standardmäßig die folgenden Endpunkte aktiviert:
/v3/api-docs: die API-Spezifikation im JSON Format/v3/api-docs.yaml: dasselbe im YAML Format/swagger-ui.html: leitet zur grafischen Dokumentation weiter, wo die APIs auch ausprobiert werden können/v3/api-docs/swagger-config: Konfiguration für Swagger UI (wo die Spezifikation zu finden ist, UI Einstellungen)
# Konfiguration
Es können in application.properties viele Einstellungen von springdoc-openapi, OpenAPI und Swagger UI festgelegt werden. Unter anderem können die Standardpfade der Endpunkte überschrieben werden:
#springdoc.api-docs.path=/api/openapi
#springdoc.swagger-ui.path=/api/ui
springdoc.override-with-generic-response=false
springdoc.swagger-ui.display-request-duration=true
springdoc.default-produces-media-type=application/json
springdoc.swagger-ui.tags-sorter=alpha
springdoc.swagger-ui.operations-sorter=alpha
In der Dokumentation (opens new window) von springdoc-openapi sind die möglichen Einstellungen beschrieben. Man kann z. B. nur bestimmte Packages scannen lassen oder nur bestimmt Pfade inkludieren.
Den meisten Einfluss auf den Inhalt der generierten Spezifikation hat man aber mit Annotationen.
# Annotationen
Da die Dokumentation anhand des Codes erstellt wird, kann dieser mit bestimmten Annotationen versehen werden. Ein Überblick der Annotationen ist in der swagger-core Wiki (opens new window) zu finden.
# Allgemeines
Sachen wie der Titel der API, die Beschreibung etc. müssen nicht für jeden @RestController sondern nur einmal definiert. Hierfür wird ein @Configuration Bean mit erstellt und die @OpenAPIDefinition Annotation befüllt:
@Configuration
@OpenAPIDefinition(
info = Info(
title = "My Awesome API",
description = "An awesome API that everybody loves.",
contact = Contact(
name = "John Doe",
email = "john@doe.emailme"
),
version = "v1"
),
externalDocs = ExternalDocumentation(
description = "Additional Documentation",
url = "https://more.docs"
)
)
class ApiDocs : OpenApiCustomiser {
override fun customise(openApi: OpenAPI) {
openApi.components.schemas = openApi.components.schemas.toSortedMap()
}
}
Wie man sieht, kann man dort auch die Generierung der Spezifikation beeinflussen, z. B. die Schemas alphabetisch sortieren. Es gibt noch mehr Sachen, die in der Annotation eingestellt werden können, siehe dazu den entsprechenden Abschnitt (opens new window) in der OpenAPI Spezifikation.
# Tag
Einzelne Operationen werden in Gruppen zusammengefasst, Tags genannt. Ohne weiteres Zutun sind das die @RestController Klassen (deren Namen in kebab-case, also bindestrichgetrennt, umgewandelt wird). Der Pfad wird automatisch aus der @RequestMapping Annotation ausgelesen.
Um Sachen wie den Namen anzupassen, wird die Klasse mit @Tag annotiert. Tags können u. a. eine kurze Zusammenfassung sowie eine längere Beschreibung enthalten.
@RestController
@RequestMapping("/my-api/user")
@Tag(
name = "user",
description = "API methods for users"
)
class UserApi
// ...
Einzelne Methoden können anderen Tags zugeordnet werden, indem sie auch mit @Tag markiert werden. Das wird normalerweise aber nicht gemacht.
# Operation
In den Tags / Gruppen werden die einzelnen Endpunkte aufgelistet, markiert nach HTTP-Methode (GET, POST, …). Diese wird der entsprechenden Annotation (GetMapping etc.) entnommen, genau wie der Pfad. Auch Parameter (Pfad, Query, Body) werden automatisch ausgelesen.
@GetMapping
@Operation(
summary = "List all users",
description = "This endpoints returns a list of all users."
)
fun getAllUsers() // ...
# @Hidden
Um einzelne Methoden oder ganze Controller von der Dokumentation auszuschließen, kann @Hidden verwendet werden.
# Gradle Plugin
Mit dem springdoc-openapi-gradle-plugin (opens new window) ist es möglich die API-Dokumentation zur Build-Zeit zu erzeugen, falls man sie stattdessen oder zusätzlich irgendwo hosten möchte.