Werkzeuge für OpenAPI-Spezifikationen

1. OpenAPI (Swagger) Editor

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 eine IDE nicht 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 OpenAPI (Swagger) Editor für IntelliJ und OpenAPI (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.

2. OpenAPI Generator

Es ist möglich, automatisch Code aus einer OpenAPI 3.0-Spezifikation zu generieren. Die IsyFact sieht hierzu 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 Ergebnis in die Anwendung zu kopieren.

2.1. Verwendung der Konsole

Für die Nutzung über die Konsole ist es erforderlich, den OpenAPI Generator zu installieren.

Der Befehl besteht aus folgenden Teilen:

openapi-generator-cli 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:

openapi-generator-cli generate
-i mitarbeiter_suche.yaml
-g typescript-angular
-o mitarbeiter_suche/angular

Spring MVC:

openapi-generator-cli generate
-i mitarbeiter_suche.yaml
-g spring --library spring-mvc
-o mitarbeiter_suche/mvc

Spring Webflux:

openapi-generator-cli generate
-i mitarbeiter_suche.yaml
-g java --library webclient
-o mitarbeiter_suche/webclient

Anschließend kann der generierte Code in das Projekt manuell übernommen werden.

2.2. Verwendung von Maven

Auch in bereits existierenden Maven-Projekt kann der OpenAPI Generator über das offizielle Maven-Plugin 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.

Listing 1. Beispielhafte Maven-Konfiguration
<build>
    <plugins>
        <plugin>
            <groupId>org.openapitools</groupId>
            <artifactId>openapi-generator-maven-plugin</artifactId>
            <version>${version}</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 library.

Tabelle 1. Parameter für die vorgesehenen Frameworks
Framework generatorName library

Spring MVC

spring

spring-mvc

Spring Web Webflux

java

webclient

Angular

typescript-angular

-

Die anderen Parameter für die Basis-Nutzung sind:

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.

3. Deployment der OpenAPI-Spezifikation als Maven-Submodul (SST-Artifact)

Eine OpenAPI-Spezifikation wird häufig projektübergreifend genutzt, z.B. wenn mehrere Anwendungen dieselbe Schnittstelle konsumieren. Um die Spezifikation zentral und versioniert bereitzustellen, empfiehlt es sich, diese als eigenständiges Maven-Submodul (im Folgenden als SST-Artifact bezeichnet, für Service-Schnittstelle) zu modellieren und in ein Maven-Repository zu deployen. Dadurch wird die Spezifikation von den konsumierenden Projekten entkoppelt: Änderungen an der Schnittstelle werden über neue Artifact-Versionen ausgeliefert, statt die YAML-Datei manuell zwischen Projekten zu kopieren.

3.1. Struktur des Submoduls

Das Submodul enthält typischerweise folgende Bestandteile:

  • die OpenAPI-Spezifikation im YAML-Format (z.B. openapi.yaml)

  • ein Changelog, das die Änderungen an der Spezifikation über die Versionen hinweg dokumentiert (z.B. CHANGELOG.md)

  • eine pom.xml, welche die Spezifikation (und ggf. das Changelog) als Artifact-Inhalt deklariert

Eine mögliche Verzeichnisstruktur sieht wie folgt aus:

meine-sst/
├── pom.xml
├── CHANGELOG.md
└── src/
    └── main/
        └── resources/
            └── openapi.yaml
Listing 2. Beispielhafte pom.xml-Konfiguration für das SST-Submodul
<project xmlns="http://maven.apache.org/POM/4.0.0">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>de.bund.example</groupId>
        <artifactId>meine-anwendung</artifactId>
        <version>1.0.0</version>
    </parent>

    <artifactId>meine-sst</artifactId>
    <packaging>jar</packaging>

    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>openapi.yaml</include>
                </includes>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-deploy-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

Die Spezifikation wird über die resources-Konfiguration in das Artifact aufgenommen, sodass sie später aus dem Jar heraus referenziert werden kann (siehe Client-Generierung über ein deploytes SST-Artifact).

3.2. Einbindung des Changelogs

Das CHANGELOG.md dokumentiert alle Änderungen an der OpenAPI-Spezifikation, analog zu einem Anwendungs-Changelog. Es wird im Wurzelverzeichnis des Submoduls gepflegt und mit jeder Änderung an der Spezifikation aktualisiert. Da das Changelog nicht Teil der Laufzeitartefakte ist, muss es nicht zwingend in das Jar eingebunden werden, es sollte jedoch als Bestandteil des Submoduls versioniert und im Repository (z.B. Git) mitgeführt werden, sodass Konsumenten des Artifacts die Änderungshistorie einer Version nachvollziehen können.

3.3. Deployment in ein Maven-Repository

Das Submodul wird wie jedes andere Maven-Modul über die üblichen Maven-Mechanismen (mvn deploy) in ein Maven-Repository deployt. Voraussetzung ist eine entsprechende <distributionManagement>-Konfiguration im Eltern-POM sowie die Konfiguration der Zugangsdaten in der settings.xml. Mit jedem Deployment wird eine neue, eindeutige Version des Artifacts (z.B. 1.0.0, 1.1.0, …​) im Repository bereitgestellt, die anschließend von konsumierenden Projekten referenziert werden kann (siehe Client-Generierung über ein deploytes SST-Artifact).

4. Client-Generierung über ein deploytes SST-Artifact

Wurde die OpenAPI-Spezifikation wie in Deployment der OpenAPI-Spezifikation als Maven-Submodul (SST-Artifact) beschrieben als SST-Artifact deployt, kann sie in konsumierenden Projekten als reguläre Maven-Dependency eingebunden werden, anstatt eine lokale Kopie der YAML-Datei zu pflegen. Dies stellt sicher, dass immer die zentral versionierte und freigegebene Fassung der Spezifikation für die Code-Generierung verwendet wird.

Dazu wird das SST-Artifact als <dependency> des openapi-generator-maven-plugin eingebunden. Das Plugin extrahiert die im Artifact enthaltene YAML-Datei automatisch aus dem Classpath, sodass im <inputSpec>-Tag lediglich der relative Pfad der Datei innerhalb des Artifacts (z.B. openapi.yaml) angegeben werden muss, anstatt eines Pfads im lokalen Dateisystem.

Listing 3. Beispielhafte Maven-Konfiguration im konsumierenden Projekt
<plugin>
    <groupId>org.openapitools</groupId>
    <artifactId>openapi-generator-maven-plugin</artifactId>
    <version>${version}</version>
    <executions>
        <execution>
            <goals>
                <goal>generate</goal>
            </goals>
            <configuration>
                <inputSpec>openapi.yaml</inputSpec>
                <generatorName>generator-name</generatorName>
                <library>eingesetzte-library</library>
            </configuration>
        </execution>
    </executions>
    <dependencies>
        <dependency>
            <groupId>de.bund.example</groupId>
            <artifactId>meine-sst</artifactId>
            <version>1.0.0</version>
        </dependency>
    </dependencies>
</plugin>

Die übrigen Konfigurationsparameter (generatorName, library, etc.) entsprechen den in Verwendung von Maven beschriebenen Parametern. Über die version der Dependency wird gesteuert, welche Version der Spezifikation für die Generierung verwendet wird. Ein Update der Schnittstelle im konsumierenden Projekt erfolgt somit allein durch das Anheben dieser Versionsnummer.