Nutzungsvorgaben REST
Diese Seite ist ein Teil der IsyFact-Standards. Alle Inhalte der Seite, insbesondere Texte und Grafiken, sind urheberrechtlich geschützt. Alle urheberrechtlichen Nutzungs- und Verwertungsrechte liegen beim Bundesverwaltungsamt.
Die Nutzung ist unter den Lizenzbedingungen der Creative Commons Namensnennung 4.0 International gestattet.
1. Einleitung
Die OpenAPI-Spezifikation (OAS) definiert eine standardmäßige, sprachunabhängige Schnittstelle zu RESTful-APIs, die es sowohl Menschen als auch Computern ermöglicht, die Schnittstellen ohne Zugriff auf Quellcode, Dokumentation oder durch Überprüfung des Netzwerkverkehrs zu erkennen und zu verstehen. Die verwendete Version der OpenAPI-Spezifikation ist OpenAPI 3.0.
Anhand einer OpenAPI-Definition können Server und Clients in verschiedenen Programmiersprachen generiert und eine verständliche (fachliche) Schnittstellenbeschreibung erzeugt werden. Dieses Dokument beschreibt die Best Practices dafür, wie Schnittstellen als OpenAPI-Spezifikation definiert werden und welche Tools dabei verwendet werden sollten.
2. Erstellung von OpenAPI-Spezifikationen
2.1. Toolauswahl
Die OpenAPI-Spezifikation wird im yaml-Format erstellt, da YAML aufgrund der übersichtlichen Syntax leichter und schneller zu erfassen ist. Für die Bearbeitung ist keine IDE zwingend erforderlich, ein einfacher Texteditor (z.B. Notepad++) reicht aus. Wir empfehlen jedoch den Einsatz des Swagger-Editors, der sowohl die syntaktische Korrektheit der yaml-Vorgaben, als der OpenAPI-Vorgaben prüft und mögliche Fehler in der Spezifikation in Echtzeit aufdeckt.
Swagger Editor ist ein Tool zum Bearbeiten von OpenAPI-Spezifikationen und unterstützt OpenAPI 3.0. Swagger Editor validiert die eingegebene Spezifikation und bietet darüber hinaus weitere Funktionalität, wie z.B. Auto-Completion. Wir empfehlen das entsprechende IntelliJ und Eclipse Plugins dieses Editors (siehe Swagger Editor für IntelliJ und Swagger Editor für Eclipse). Die Verwendung dieser Plugins ist besonders sinnvoll, da sie die Integration der Spezifikation in das Projekt ermöglicht und die Verwaltung mit Version Control erleichtert.
Weitere Informationen zu OpenAPI 3.0 (Beschreibung und Vorgaben) finden Sie unter Swagger Spezifikation). Bei der Erstellung der Spezifikation sind die Vorgaben der IsyFact (siehe Konzept REST) zu beachten. Relevante Vorgaben beziehen sich u.a. auf den Aufbau der URls und der Anfrage, die Verwendung der http-Verben und Statuscodes.
2.2. Mapping von fachlicher Schnittstellenbeschreibung auf OpenAPI-Spezifikation
Die Schnittstellenbeschreibung, die im Rahmen der Systemspezifikation erstellt wird, spezifiziert die angebotene(n) Nachbarsystemschnittstelle(n) (NST) aus fachlicher Sicht und gibt keine Auskunft über technische Details. Für das Erstellen dieser fachlichen Schnittstellenbeschreibung wird die IsyFact-Vorlage Schnittstellendokumentation verwendet. Die fachlichen Schnittstellenbeschreibungen nach den Vorgaben der IsyFact enthalten in erster Linie die verwendeten Entitäten sowie Eingabe und Ausgabe Parameter. Ergänzt werden diese durch weitere Spezifika (z.B. Kurzbeschreibung, Synchron/Asynchron, Online/Offline…). Diese Schnittstellenbeschreibung soll im Rahmen des Systementwurfs technisch als eine OpenAPI-Spezifikation konzipiert und bereitgestellt werden.
Im Folgenden stellen wir ein Vorgehen zum Mappen der fachlichen Schnittstellenbeschreibung auf eine OpenAPI-Spezifikation vor. Alle Schnittstellen einer Anwendung sollen in einer einzigen OpenAPI-Spezifikation beschrieben werden.
Die Entitäten und die Datentypen in den fachlichen Schnittstellenbeschreibungen werden mithilfe der OpenAPI Schemaobjekte definiert. Schemaobjekte können Objekte, aber auch primitive Datentypen und Listen (Arrays) sein. Schemaobjekte unterstützen auch Polymorphismus. Dies ermöglicht auch Vererbung- und Kompositionsrelationen zwischen den Objekten. Diese Entitäten können so an beliebiger Stelle in der Spezifikation als Referenzobjekte genutzt werden.
Die Eingabe/Ausgabe Parameter in den fachlichen Schnittstellenbeschreibungen sind Entitäten oder Datentypen. Diese Parameter werden zuerst als Schemaobjekte definiert. Anschließend werden sie als Parameterobjekte oder als Request-Body-Objekte den Schnittstellen zugewiesen, je nachdem wie sie bei der Eingabe/Ausgabe benötigt werden.
IsyFact Schnittstellen-beschreibung | OpenAPI 3 Spezifikation | Beispiel und Bemerkung |
---|---|---|
NST_Schnittstelle |
path |
NST_Mitarbeiter_suchen
Der Pfadname muss den Vorgaben zur Ressourcenorientierung im REST Konzept entsprechen. |
NSE_Entität (Input) |
schema oder type |
NSE_Mitarbeiter_Suchkriterien:
oder
Es wird empfohlen, die Attribute der Eingabe-Entitäten, die als Abfrageparameter (z.B. Suchkriterien) verwendet werden, als Query Parameters zu definieren. Es wird empfohlen, Entitäten mit komplexen oder vertraulichen Suchkriterien als Schemaobjekt zu spezifizieren, um das Erfassen dieser Informationen, z.B. durch Logger, zu vermeiden. Die Eingabe-Entitäten, die im Body verarbeitet werden (z.B. Hinzufügen einer neuen Entität oder Bearbeiten einer vorhandenen Entität), werden als Schemaobjekt definiert. |
NSE_Entität (Output) |
responses mit schema |
Mit Schemaobjekt für NSE_Mitarbeiter:
|
NSA_Attribut |
property |
|
DTY_Datentyp (einfach) |
type |
DTY_Ganzzahl:
|
DTY_Datentyp (komplex) |
schema |
DTY_Bundesland
|
Kurz- beschreibung |
description |
|
Offline/Online |
keine Entsprechung |
|
Synchron/ Asynchron |
keine Entsprechung |
|
Schnittstellen- typ |
verb |
get, post, put, delete Das passende Verb, um die Art der Transaktion zu beschreiben (Lese-, Schreib- oder Löschvorgang). Vorgaben zur Wahl des Verbs finden sich im Konzept REST. |
Die für die Mapping-Tabelle genutzte Beispiel-Schnittstellenbeschreibung und das Ergebnis als OpenAPI-Spezifikation ist als im Beispiel im Anhang zusammenfassend dargestellt.
2.3. Übertragung von Metadaten
Metadaten werden als Header-Parameter übertragen. Zu Metadaten gehören u.a. Daten wie Benutzerkennung, Rolle, Tags, externe IDs. Nur die Metadaten, die nicht durch die IsyFact standardisiert werden, sind Teil der OpenAPI-Spezifikation.
Zur Spezifizierung von Header-Parametern wird der Eintrag „in: header“ genutzt, wie das unten stehenden Beispiel zeigt.
Beispiel: Eine externe Id in NST_Mitarbeiter_suchen.
Anforderung: Es muss immer eine externe Id mitgeschickt werden, wenn eine Schnittstelle der Anwendung aufgerufen wurde.
…
paths:
/mitarbeiter/sucheNachSuchkriterien:
get:
summary: "Suche Mitarbeiter nach Suchkriterien"
description: "Diese Schnittstelle bietet Nachbarsystemen die Möglichkeit, Mitarbeiter zu suchen und deren Daten abzufragen. Die Auswahl der Mitarbeiter erfolgt anhand einer Reihe von optionalen Suchkriterien."
operationId: "sucheMitarbeiterNachSuchkriterien"
parameters:
- name: "externeId"
in: "header"
schema:
type: "integer"
format: "int64"
…
2.4. Übertragung fachlicher Informationen bei GET- und DELETE-Anfragen
Bei Anfragen zum Lesen (GET) oder Löschen (DELETE) werden gemäß REST-Konzept (siehe Konzept REST) keine Informationen im Body übertragen. In einigen Fällen kann es jedoch vorkommen, dass der Server weitere Informationen benötigt, um die Anfrage erfolgreich bearbeiten zu können. Ein mögliches Szenario ist die Protokollierung der Zugriffshistorie inkl. Zugriffsgrund. Daher sollen in diesem Szenario die erforderlichen Informationen als URL-Parameter gesendet werden.
Zur Spezifizierung von URL-Parametern wird der Eintrag „in: path“ genutzt, wie das unten stehenden Beispiel zeigt.
Beispiel: Protokollierung in NST_Mitarbeiter_suchen.
Anforderung: Es muss immer der Zugriffsgrund protokolliert werden, wenn die Schnittstelle der Mitarbeitersuche aufgerufen wurde. Für die Protokollierung dieser Schnittstelle wird zusätzlich der Zugriffsgrund benötigt.
…
paths:
/mitarbeiter/sucheNachSuchkriterien:
get:
summary: "Suche Mitarbeiter nach Suchkriterien"
description: "Diese Schnittstelle bietet Nachbarsystemen die Möglichkeit, Mitarbeiter zu suchen und deren Daten abzufragen. Die Auswahl der Mitarbeiter erfolgt anhand einer Reihe von optionalen Suchkriterien."
operationId: "sucheMitarbeiterNachSuchkriterien"
parameters:
- name: "zugriffsgrund"
in: "path"
schema:
type: "string"
…
Falls die zu übermittelnden Informationen vertraulich sind, sollte ein Wechsel des http-Verbs zu POST und die Übermittlung der Informationen im Body statt in der URL eruiert werden.
3. Verwendung von OpenAPI Generator
Es ist möglich, automatisch Code aus einer OpenAPI 3.0-Spezifikation zu generieren. Die IsyFact sieht den Einsatz des OpenAPI-Generators vor. Für die automatische Generierung muss eine gültige OpenAPI 3.0-Spezifikation als Eingabe bereitgestellt werden. Der Generator liest diese Spezifikation ein und generiert daraus automatisch eine entsprechende Client- oder Server-Implementierung. Der Generator unterstützt alle verwendeten REST-Frameworks der IsyFact: Angular (Client), Spring Web Webflux (Client) und Spring MVC (Server).
Der präferierte Weg ist, den Generator über Maven oder direkt über die Konsole zu verwenden. Die Verwendung von Maven ist sinnvoll, wenn eine neue Anwendung von Grund auf neu entwickelt wird oder die Generierung in einen bestehenden Prozess integriert werden soll, z.B. in einen automatischen Prozess zur Generierung von fachlicher Dokumentation. Sollen neue Schnittstellen zu einer bereits bestehenden Anwendung hinzufügt werden, wird empfohlen, den Generator von der Konsole aus auszuführen und die benötigten Teile aus dem Generat in die Anwendung zu kopieren.
3.1. Die Konsole
Für die Nutzung über die Konsole ist es erforderlich, vorher die Generator-JAR-Datei von der Website des Generators zu installieren. Der Befehl besteht aus folgenden Teilen:
java -jar <Pfad der Jar-Datei OpenAPI-generator-cli.jar> generate
-i <Pfad der Input-Datei (OpenAPI 3.0 Spezifikation)>
-g <der Name des Generators>
-o <Pfad für den zu erstellenden Code>
Beispiele für die verwendeten Frameworks:
Angular:
java -jar …/OpenAPI-generator-cli.jar generate
-i …/mitarbeiter_suche.yaml
-g typescript-angular
-o …/mitarbeiter_suche/Angular
Spring MVC:
java -jar …/OpenAPI-generator-cli.jar generate
-i …/mitarbeiter_suche.yaml
-g spring --library spring-mvc
-o …/mitarbeiter_suche/Angular
Spring Web Webflux:
java -jar …/OpenAPI-generator-cli.jar generate
-i …/mitarbeiter_suche.yaml
-g java --library webclient
-o …/mitarbeiter_suche/Angular
Anschließend kann der generierte Code in das Projekt manuell übernommen werden.
3.2. Maven
Auch in bereits existierenden Maven-Projekt kann der OpenAPI-Generator aufgerufen werden. Es ist jedoch wichtig zu beachten, dass der generierte Code ein eigenes Projekt darstellt. Daher sollte die Integration des neuen Codes in das bereits bestehende Projekt noch manuell erfolgen. Ein Beispiel für die Maven-Konfiguration:
<build>
<plugins>
<plugin>
<groupId>org.OpenAPItools</groupId>
<artifactId>OpenAPI-generator-maven-plugin</artifactId>
<version>5.3.0</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>.../mitarbeiter_suche.yaml</inputSpec>
<generatorName>spring</generatorName>
<library>spring-mvc</library>
<generateModelTests>true</generateModelTests>
<generateApiTests>true</generateApiTests>
<configOptions>
<sourceFolder>src/gen/java/main</sourceFolder>
</configOptions>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Die Konfigurationsparameter für den Generator sind die Tags „generatorName“ und der Tag „library“. Die Parameter für die verwendeten Frameworks sind folgende:
generatorName | library | |
---|---|---|
Spring MVC |
spring |
spring-mvc |
Spring Web Webflux |
java |
webclient |
Angular |
typescript-angular |
- |
Die anderen Parameter für die Basis-Nutzung sind in der folgenden Auflistung beschrieben:
inputSpec |
Der Pfad von der eingegebenen OpenAPI 3.0 Spezifikation. |
---|---|
generateModelTests |
Gibt an, ob Tests für das Model generiert werden sollen. Es ist möglich, dass keine Tests generiert werden. Die Ergebnisse hängen davon ab, ob das verwendete Template diese Funktionalität unterstützt oder nicht. |
generateApiTests |
Gibt an, ob Tests für die Api generiert werden sollen. Es ist möglich, dass keine Tests generiert werden. Die Ergebnisse hängen davon ab, ob das verwendete Template diese Funktionalität unterstützt oder nicht. |
configOptions/ sourceFolder |
Der Pfad für den zu generierenden Code. |
4. Veröffentlichung und Verwaltung der OpenAPI 3.0 Spezifikation
4.1. Verwaltung
Die OpenAPI Schnittstellenspezifikation ist jeweils Bestandteil der spezifischen Projektdokumentation.
Damit die OpenAPI Schnittstellenspezifikation verfügbar sein kann, muss diese auch verwaltet werden. In den jeweiligen Spring Projekten wird die OpenAPI Schnittstellenspezifikation unter folgendem Pfad gespeichert: /src/main/resources/openapi.yml.
Falls es Änderungen innerhalb der OpenAPI Schnittstellenspezifikation geben sollte, werden diese automatisch vom Versionskontrollsystem verwaltet.
4.2. Veröffentlichung
Die OpenAPI Spezifikationen werden mit jeder Veröffentlichung (Release) der Anwendung ausgeliefert. Für die Auslieferung und Veröffentlichung der OpenAPI Spezifikation ergeben sich unterschiedliche Möglichkeiten, die in den folgenden Kapiteln beschrieben werden.
4.2.1. Artifactory
Die Auslieferung erfolgt als ein Teil vom zentral generierten Artefakt. Der Zugriff auf das Artefakt ist über das entsprechende Artifactory und/oder GitHub (für Open-Source gestellte Bausteine) möglich.
4.2.2. Antora
Antora ist eine Dokumentationspipeline, die es Dokumentations-, Produkt- und Entwicklungsteams ermöglicht, Dokumentationsseiten zu erstellen, zu verwalten und zu veröffentlichen, die in AsciiDoc erstellt und aus mehreren versionierten Repositories bezogen wurden.
Mithilfe des OpenAPI Generators kann aus der OpenAPI Spezifikation (YAML Datei) AsciiDoc generiert/erstellt werden. Allgemeine Informationen zum OpenAPI Generator finden sich im Kapitel Verwendung von OpenAPI Generator. Die generierten AsciiDoc-Dateien können dann in den Antora-Dokumentenbuild aufgenommen und gemeinsam mit der übrigen Dokumentation des Bausteins oder der Anwendung generiert und veröffentlicht werden.
Für die Generierung der Schnittstellenbeschreibung im AsciiDoc-Format ist der Generator „asciidoc“ zu wählen.
Neben der generierten OpenAPI Spezifikation als AsciiDoc-Datei, empfehlt es sich auch die OpenAPI Spezifikation im YAML-Format im Dokumentenbuild zu verlinken.
Die Integration in den Antora-Dokumentenbuild ermöglicht somit:
-
einen einfachen Zugriff auf verschiedene Versionen der OpenAPI Spezifikationen
-
das Herunterladen der OpenAPI Spezifikationen für technische Benutzer (YAML-Format)
-
den Zugang zu einer verständlichen Schnittstellen-Spezifikation für nicht technisch versierte Benutzer (AsciiDoc-Format)
Die generierte Dokumentation (HTML) kann auf einem Webserver oder auf GitHub/GitLab-Pages veröffentlicht werden und ist dann mit einem Webbrowser erreichbar. Hierzu müssen entsprechende Jobs in der Build-Pipeline angelegt werden.
4.2.3. Definition eines Endpunktes
Für den Betrieb in Testumgebungen ist es empfehlenswert, die OpenAPI Spezifikation im YAML-Format über eine Schnittstelle bereitzustellen. Dazu wird ein eigener Endpunkt implementiert, der die im Ressourcen-Verzeichnis liegende OpenAPI Spezifikation bereitstellt. Über einen Webbrowser kann so auf die aktuelle OpenAPI Spezifikation der Anwendung im Betrieb zugegriffen werden, um z.B. Testwerkzeuge zu konfigurieren.
Es wird empfohlen, für die URL des Endpunktes einen klar verständlichen Begriff wie z.B. /openapi-spezifikation-download zu verwenden.
5. Setzen der Korrelations-ID in den HTTP-Header
Beim Versenden einer REST-Anfrage ist der Schlüssel "X-Correlation-Id" mit dem Wert der Korrelations-ID in den Header zu setzen. Die Anwendung, welche die REST-Anfragen stellt, muss dieses Verhalten implementieren. In diesem Abschnitt wird ein Beispiel für die Implementierung gegeben.
Für das Setzen des korrekten Werts in den HTTP-Header sind folgende Schritte auszuführen:
-
Die bestehende Korrelations-ID wird aus dem MdcHelper ausgelesen.
-
Eine neue UUID wird erzeugt und
-
an die bestehende Korrelations-ID angehängt
-
dem MdcHelper übergeben.
-
-
Die aktualisierte Korrelations-ID wird als Wert für den Schlüssel "X-Correlation-Id" im Header der REST-Anfrage gesetzt.
Für REST-Anfragen sieht die IsyFact Spring WebClient vor.
Für die folgende Beispielimplementierung wird daher angenommen, dass eine Bean vom Typ org.springframework.web.reactive.function.client.WebClient
existiert.
Zunächst wird das Interface ExchangeFilterFunction
implementiert:
ExchangeFilterFunction correlationIdAddingFilter =
(clientRequest, nextFilter) -> {
StringBuilder correlationIdBuilder = new StringBuilder();
String existingCorrelationId = MdcHelper.liesKorrelationsId();
if (existingCorrelationId != null && !existingCorrelationId.isEmpty()) {
correlationIdBuilder.append(existingCorrelationId).append(";");
}
String newCorrelationId = UUID.randomUUID().toString();
correlationIdBuilder.append(newCorrelationId);
MdcHelper.pushKorrelationsId(newCorrelationId);
ClientRequest filteredRequest = ClientRequest.from(clientRequest)
.header("X-Correlation-Id", correlationIdBuilder.toString())
.build();
return nextFilter.exchange(filteredRequest);
};
Anschließend wird die zuvor definierte ExchangeFilterFunction
zur WebClient
-Bean hinzugefügt:
@Bean
public WebClient webClient() {
return WebClient.builder()
.filter(correlationIdAddingFilter)
.build();
}
Nachdem eine Anfrage bearbeitet wurde, sorgt der HttpHeaderNestedDiagnosticContextFilter
im Rahmen seiner
afterRequest()
-Methode dafür, dass die Korrelations-ID aus dem MdcHelper entfernt wird. Dies erfolgt durch den Aufruf
von MdcHelper.entferneKorrelationsIds()
, der alle zuvor gesetzten Korrelations-IDs zurücksetzt.
Anhang
Anhang A: Zusammenfassung des Beispiels (NST_Mitarbeiter_suchen):
Kurzbeschreibung |
Diese Schnittstelle bietet Nachbarsystemen die Möglichkeit, Mitarbeiter zu suchen und deren Daten abzufragen. Die Auswahl der Mitarbeiter erfolgt anhand einer Reihe von optionalen Suchkriterien. |
---|---|
Verwendete Entitätstypen (Input) |
NSE_Mitarbeiter_Suchkriterien |
Verwendete Entitätstypen (Output) |
NSE_Mitarbeiterdaten |
Aufgerufene Anwendungsfälle |
AWF_Mitarbeiter_suchen |
Eingabeparameter
Name |
NSE_Mitarbeiter_Suchkriterien |
---|---|
Kurzbeschreibung |
Die Kriterien zur Selektion von Mitarbeiter. Alle Attribute dieses Typs sind optional. Nicht befüllte Attribute werden daher nicht in die Suche einbezogen. Es dürfen beliebige Kombinationen von Attributen angegeben werden. |
Name | Datentyp |
---|---|
NSA_Bundesland_Schlüssel |
DTY_Bundesland |
NSA_Ort |
DTY_Zeichenkette |
NSA_Treffer_Anzahl |
DTY_Ganzzahl |
Ausgabeparameter
Name |
NSE_Mitarbeiterdaten |
---|---|
Kurzbeschreibung |
Dies ist die Rückgabeentität mit den Daten eines Mitarbeiters. |
Name | Datentyp |
---|---|
NSA_Name |
DTY_Zeichenkette |
NSA_Vorname |
DTY_Zeichenkette |
NSA_Bundesland_Schlüssel |
DTY_Bundesland |
NSA_Telefonnummer |
DTY_Zeichenkette |
Das Ergebnis vom Mapping zur OpenAPI 3.0 Spezifikation:
OpenAPI: 3.0.0
info:
description: "Ein Beispiel für das Mapping einer fachlichen Schnittstelle"
version: "1.0.0"
title: "Beispiel Anwendung"
paths:
/mitarbeiter/sucheNachSuchkriterien:
get:
summary: "Suche Mitarbeiter nach Suchkriterien"
description: "Diese Schnittstelle bietet Nachbarsystemen die Möglichkeit, Mitarbeiter zu suchen und deren Daten abzufragen. Die Auswahl der Mitarbeiter erfolgt anhand einer Reihe von optionalen Suchkriterien."
operationId: "sucheMitarbeiterNachSuchkriterien"
parameters:
- in: "query"
name: "bundeslandSchluessel"
schema:
$ref: '#/components/schemas/Bundesland'
- name: "ort"
in: "query"
schema:
type: "string"
- name: "trefferAnzahl"
in: "query"
schema:
type: "integer"
responses:
'200':
description: successful operation
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Mitarbeiter'
'405':
description: "Ungültige Suchkriterien"
components:
schemas:
Mitarbeiter:
type: "object"
properties:
id:
type: "integer"
format: "int64"
name:
type: "string"
vorname:
type: "string"
bundeslandSchluessel:
$ref: '#/components/schemas/Bundesland'
telefonnummer:
type: "string"
Bundesland:
type: string
enum:
- BW
- BY
- BE
- BB
- HB
- HH
- HE
- MV
- NI
- NW
- RP
- SL
- SN
- ST
- SH
- TH