
14. Mai 2025
AsyncAPI – Schlüssel zu testbarer und entwicklungsfreundlicher Schnittstellendefinition
In unserer zunehmend vernetzten Welt sind Schnittstellen das zentrale Element, das verschiedene Systeme miteinander verbindet. Eine präzise und durchdachte Schnittstellenspezifikation ist daher unerlässlich.
In einem unserer Projekte haben wir dies durch den Einsatz von AsyncAPI, einem Standard für die Spezifikation der asynchronen Kommunikation, erreicht. In Kombination mit JSON Schema, einem Standard zur Definition des Aufbaus von JSON-Dateien, haben wir eine testbare AsyncAPI-Spezifikation erstellt, die viele positive Nebeneffekte mit sich brachte.
AsyncAPI trifft auf erste Herausforderungen
Zu Beginn des Projekts stand uns eine Anforderungsübersicht zur Verfügung, mit Vorgaben zur technischen Umsetzung: Die Kommunikation sollte über das MQTT-Protokoll erfolgen, und der Nachrichten-Payload sollte im JSON-Format sein, um eine losere Kopplung der Systeme zu ermöglichen.
Die initiale Schnittstellen-Definition wurde uns als Excel-Liste überreicht. Diese Liste enthielt unter anderem ein Mapping zwischen den Anforderungen und den zu sendenden Nachrichten, die entsprechenden Topics, Beispiele für den JSON-Payload, sowie die Datentypen der meisten Objekt-Eigenschaften.
Für einen ersten Prototyp nutzten wir diese Vorlage als Ausgangspunkt und entwickelten einen Client, der sowohl Nachrichten senden als auch empfangen konnte.
Entwicklung einer robusten Lösung mit AsyncAPI
Im weiteren Projektverlauf stellte sich heraus, dass auf der Gegenseite bisher nur die initialen Nachrichten implementiert waren. Weitere Topics standen noch nicht zur Verfügung. Daher entschieden wir uns, die Gegenseite zunächst zu simulieren. Wir entwickelten einen Simulator, der mithilfe von Konfigurationsdateien Szenarien nachstellen und das erwartete Schnittstellenverhalten simulieren konnte.
Um sicherzustellen, dass der Simulations-Payload den Erwartungen entspricht, integrierten wir die Validierung der Nachrichten durch JSON Schema-Dateien in den Simulator. Diese Schemas mussten wir allerdings basierend auf der Excel-Liste selbst erstellen.
Dank unserer Entwicklungsmethoden waren wir in der Lage, mit dem Testen zu beginnen, obwohl die Cloud-Gegenseite noch instabil war und keine verlässlichen Tests zuließ.
Im MQTT sind alle Clients gleichberechtigt und können selbst steuern, welche Topics sie abonnieren und auf welchen sie senden. Dies ermöglicht auch das Mocking unseres Clients. Dadurch konnten wir über den Simulator überprüfen, ob sich die Cloud gemäß den Erwartungen aus der Dokumentation verhält und beide Mock-Implementierungen im Sinne des Contract Testings gegenseitig auf Konsistenz testen.
Diese Tests ließen sich außerdem hervorragend in Integration-Tests integrieren und automatisiert als Teil der Build-Pipeline ausführen. Ebenso konnten wir die JSON Schema-Dateien direkt in Unit-Tests einsetzen, um die von unserem Code erzeugten Nachrichten zu validieren.
AsyncAPI für präzise Dokumentation und Feedback
Ein weitere Herausforderung war die Dokumentation: Zusätzliche Features oder Anpassungen in der Cloud führten meist zu Änderungen an der Excel-Liste oder später in einem Word-Dokument, jedoch selten zu Release-Notes. Ein nachvollziehbares Änderungsmanagement war kaum möglich.
Mit AsyncAPI lösten wir dieses Problem: Alle relevanten Informationen wurden aus dem Word-Dokument in ein AsyncAPI-Specification YAML übertragen, wobei die vorhandenen JSON Schema-Dateien für die entsprechenden Nachrichten referenziert wurden. Auf diese Weise konnten wir alle technischen Informationen übertragen und erweitern. Durch einen iterativen Ansatz konnten wir hier die Genauigkeit und Qualität der Schnittstellendefinition stetig verbessern.
Der Wechsel zu AsyncAPI erlaubt es außerdem, Änderungen leicht nachzuverfolgen. YAML und JSON Schema-Dateien befinden sich zusammen mit dem Code im Repository und sind somit versioniert. Abweichungen zwischen Spezifikation und Implementierung werden durch unsere Tests schnell erkannt.
Das AsyncAPI-Dokument ermöglicht uns zudem eine schnelle und gut lesbare Dokumentationserstellung, sei es interaktiv als HTML oder statisch als Markdown. Dies wurde fester Bestandteil unserer Gesamt-Dokumentation.
Die Herausforderungen und Zukunft mit AsyncAPI
Nicht alles lief reibungslos: AsyncAPI befindet sich noch in der Entwicklung und einige von uns benötigte Features wurden erst später ergänzt. Daher war es wichtig, sich auf eine bestimmte Version zu einigen, zumindest bis zum Projektende.
Die Nutzung von JSON Schema-Dateien bietet Flexibilität, diese Dokumente auch getrennt von AsyncAPI zu verwenden. Allerdings besteht die Herausforderung, diese korrekt zu referenzieren, damit alle Tools darauf zugreifen können. Ein Unterschied besteht hierbei zwischen inline angegebenen Schemas in AsyncAPI und extern referenzierten JSON Schema-Dateien. Die Inline-Notation mit AsyncAPI Schema, einem Superset von JSON Schema, war für uns keine Option, da wir die Schemas getrennt verwenden wollten.
Für JSON Schema existieren verschiedene Bibliotheken für diverse Programmiersprachen, jedoch werden teilweise unterschiedliche Schema-Versionen implementiert oder bieten unterschiedlichen Funktionsumfang. So stießen wir beispielsweise auf Probleme mit den If-Then-Else-Konstrukten in unserer C++-Codebase, die mit der verwendeten Bibliothek validiert wurden, während diese bei der C#-Bibliothek im Simulator ignoriert wurden.
Den Namen AsyncAPI entsprechend, eignet sich der Standard weniger zur Abbildung von Nachrichten-Abhängigkeiten und Abläufen. Es ist schwierig darzustellen, dass eine Nachricht eine Antwort auf eine andere ist. Wir arbeiten hier mit Referenzen in der Beschreibung; dennoch ist das Tooling in diesem Bereich ausbaufähig.
AsyncAPI: Der Weg zu einer erfolgreichen Implementierung
Am Ende wurde das Projekt mit einer umfassenden Schnittstellenspezifikation abgeschlossen, und die Einführung von AsyncAPI und JSON Schema brachte uns folgende Vorteile:
-
Eine Testumgebung für die schnellere Entwicklung von Features
-
Prüfung zur Laufzeit, ob die verarbeiteten Nachrichten valide sind
-
Unit- und Integration-Tests zur Stabilisierung unserer Implementierung und zur Verhinderung von Regressionen
-
Möglichkeit zur Prüfung der Cloud-Instanz
-
Versionierte Schnittstellenspezifikation nahe am Code
Durch unsere Erfahrung mit AsyncAPI konnten wir nicht nur die Entwicklung unserer Schnittstelle effektiv vorantreiben, sondern auch ein tieferes Verständnis für moderne Schnittstellen-Technologien gewinnen. AsyncAPI half uns dabei, die Kommunikation zwischen unseren Systemen effizient zu gestalten und unser Projekt erfolgreich abzuschließen
asyncapi.yaml
deviceStatusPayload.json
Autor & Ansprechpartner
Ihr habt Fragen, Ideen oder Feedback zu diesem Thema? Kontaktiert uns gerne!