Verarbeiten von Webhooks mit Java, Spring Cloud Function und Azure Functions
Lesezeit: 5 Minuten
Wenn du über die Twilio-API eine SMS oder eine WhatsApp-Nachricht senden möchtest, ist das dafür erforderliche Programmieren unkompliziert: Du rufst die API auf und die Nachricht wird gesendet. Beim Antworten auf eingehende Nachrichten sieht die Sache schon anders aus. Wenn die Nachricht eintrifft, muss Twilio wissen, wie sie verarbeitet werden soll. Wir verwenden dafür ein Verfahren namens Webhook. Du konfigurierst deine Twilio-Nummer mit einer URL, und die Plattform stellt eine Anfrage und liefert Details zur eingehenden Nachricht. Was als Nächstes passiert, richtet sich nach der Reaktion deiner Anwendung.
Du brauchst also für deine Anwendung eine öffentliche URL, die wiederum gehostet werden muss. In den letzten Jahren ist die Beliebtheit von serverlosen Plattformen für diese Zwecke gestiegen, weil sie deutlich weniger Kopfzerbrechen bereiten als das typische Hosting. Du erstellst Code zur Verarbeitung einer einzelnen Anfrage, und die Plattform übernimmt das Weiterleiten, Skalieren und die meisten anderen Schritte. Auch bei Java ist dieser Trend zu beobachten. Spring Cloud Function wurde konzipiert, um Java-Entwicklern ein konsistentes Programmiermodell für serverlose Plattformen bereitzustellen. Dabei können sie auch auf andere beliebte Funktionen von Spring zurückgreifen, z. B. Dependency Injection.
In diesem Blog-Beitrag zeige ich, wie man mit Spring Cloud Function eine serverlose Java-Funktion erstellt und sie auf Azure Functions bereitstellt. Die Funktion dient als Webhook, über den Twilio angewiesen wird, wie die Reaktion auf eine eingehende SMS aussehen sollte. Relativ einfach also, aber wenn du erstmal eine serverlose Funktion zum Reagieren auf SMS hast, kannst du das gesamte Potenzial von Java nutzen.
Voraussetzungen
Um mitzuentwickeln, benötigst du:
- Java 8 oder höher – Ich verwende SDKMAN!, um meine Java-Installationen zu verwalten, und genau dieses Tool empfehle ich auch dir!
- Eine Java IDE – Ich mag IntelliJ IDEA, aber andere Entwicklungsumgebungen sind genauso gut geeignet.
- Ein Azure-Konto und die Azure Functions Core Tools.
- Ein Twilio-Konto und eine Telefonnummer.
Wenn du gleich zum Ende springen möchtest, findest du den vollständigen Code für dieses Projekt hier auf GitHub. Wenn du wissen möchtest, wie der Code geschrieben wird, lies weiter!
Los geht's
Ich verwende immer den Spring Initializr, um ein neues Spring-Projekt zu starten. Mit diesem Link werden ein paar wichtige Aspekte vorab ausgewählt, darunter die Spring Cloud Function-Abhängigkeit.
Generiere das Projekt, entpacke es und öffne es in deiner IDE. Die Spring-Vorlage spart viel Zeit, und du kannst gleich mit dem Programmieren beginnen. Erstelle ein neues Paket mit dem Namen com.example.webhooks.functions
und füge ihm eine Klasse namens WebhookHandler
hinzu.
Beachte bitte, dass die Funktion respondToSms
keine Argumente benötigt und eine java.util.Function
zurückgibt, die den String in einen anderen String umwandelt – und das ist die eigentliche Funktion, die die Anfragen verarbeitet. Ich habe für den Anfang einen Methodenverweis verwendet. Wenn du später etwas Komplexeres brauchst, kannst du ihn in einen Lambda-Ausdruck ändern.
Diese Funktion ist eigentlich für die Cloud gedacht, aber sie kann auch lokal ausgeführt werden. Füge dazu die Abhängigkeit spring-cloud-starter-function-web unter <dependencies>
in der Datei pom.xml
hinzu, die sich im Stammverzeichnis deines Projektverzeichnisses befindet:
Führe in einem Terminal im Stammverzeichnis des Projekts ./mvnw spring-boot:run
aus, warte auf das ASCII-Art Spring-Logo und teste es dann mit diesem Befehl in einem anderen Terminal-Fenster:
Als Antwort wird „HELLO FUNCTION“ angezeigt, ganz so, wie man es vom Befehl String::toUpperCase
erwarten würde.
Eine noch nützlichere Funktion
Du kannst weitere Klassen hinzufügen und sie mit Spring DI-Annotationen wie @Bean
und @Autowired
miteinander verbinden. Darüber hinaus kannst du pom.xml
um zusätzliche Abhängigkeiten erweitern, um deine Funktion noch nützlicher zu gestalten. Probiere das gerne aus – dank der in diesem Beitrag verwendeten Maven-Konfiguration werden die Funktionen alle bei der Bereitstellung auf der serverlosen Plattform funktionieren, aber ich gehe in diesem Post nicht weiter darauf ein.
Bereitstellen in Azure Functions
Es wird Zeit, dass ich mein Versprechen aus der Einleitung einhalte: Wir stellen diese Funktion in Azure Functions bereit, um dem zugehörigen Code eine öffentliche URL zuzuweisen.
Zum Bereitstellen in Azure brauchen wir einen Adapter, der die Spring Cloud Function als Azure Function verpackt. Dafür sind eine neue Abhängigkeit und eine neue Klasse erforderlich.
Du musst pom.xml
die folgende Abhängigkeit hinzufügen:
Erstelle ein neues Paket mit dem Namen com.example.webhooks.azure
und lege darin eine Klasse namens AzureFunctionWrapper
an. Im Prinzip spielt der Name keine Rolle, aber das sind die Namen, für die ich mich entschieden habe. Diese Klasse dient zur Erweiterung von AzureSpringBootRequestHandler<String, String>
– die Typenparameter entsprechen denen der Funktion respondToSms
. Ebenfalls benötigt wird eine Methode, die mit @FunctionName
versehen wird. Der betreffende Wert stimmt mit dem Namen der Methode der Spring Cloud Function überein, wie hier gezeigt:
[Code auf GitHub, inklusive der Importanweisungen]
Es sind nun ein paar Konfigurationen nötig, um alles miteinander zu verbinden:
- Erstelle eine Verzeichnis namens
azure
insrc/main
und fügehost.json
undlocal.settings.json
hinzu. Beide kannst du von hier kopieren. Du brauchst diese Dateien nicht zu bearbeiten. - Füge diesen großen Brocken XML in
pom.xml
unter</dependencies>
hinzu und ersetze dabei die Abschnitte<dependencyManagement>
und<build>
, die sich bereits dort befinden. Dadurch wird die Konfiguration für das Maven Plugin für Azure Functions hinzugefügt. Damit kannst du deine Funktion über die Befehlszeile programmieren und bereitstellen. Eine Bearbeitung ist nicht erforderlich.
Abschließend fügst du dem Abschnitt <properties>
von pom.xml
einige Werte hinzu:
Nach der Installation der Azure Functions Core Tools kannst du diese Funktion erneut lokal ausführen, wobei du diesmal statt der Spring-Tools die Azure-Tools verwendest. Der Befehl lautet:
Hinweis: Mit diesem Befehl werden zahlreiche Abhängigkeiten heruntergeladen, daher kann seine Ausführung eine Weile dauern. Der Befehl ist abgeschlossen, wenn du in der Ausgabe Folgendes siehst: respondToSms: [GET,POST] http://localhost:7071/api/respondToSms
. Bei Maven werden die heruntergeladenen Abhängigkeiten zwischengespeichert, d. h., nach dem ersten Ausführen laufen alle weiteren Ausführungen deutlich schneller.
Teste nun Folgendes:
Hinweis: Die Anfrage sieht anders aus als zuvor – so stellt Azure die Funktion nach der Bereitstellung zur Verfügung. Die Antwort erfolgt natürlich weiterhin über String::toUpperCase
:
Bereitstellen in Azure
Die gesamte Konfiguration für den Upload und die Konfiguration in Azure liegt nun vor, du musst also nur den folgenden Befehl ausführen:
Eventuell wirst du gebeten, dich über deinen Browser bei Azure anzumelden. Wenn die Bereitstellung abgeschlossen ist, siehst du die vollständige öffentliche URL der Funktion:
Über curl sendest du genau wie zuvor eine Anfrage an die Funktion in Azure – du ersetzt dabei einfach die Localhost-URL durch die öffentliche Azure-URL.
Es scheint zu funktionieren – perfekt!
Serverlose Kaltstarts
Ist dir aufgefallen, dass die Reaktion beim ersten Mal recht langsam war? Das kann bei serverlosen Plattformen passieren, wenn eine Funktion eine Zeit lang nicht aufgerufen wurde. Dieses Phänomen wird auch als „Kaltstart“ bezeichnet. Die Häufigkeit und das Ausmaß der Kaltstarts hängen von zahlreichen Faktoren ab. Twilio wartet bei einer Webhook-HTTP-Anfrage 15 Sekunden lang auf eine Antwort. Bei mir ist es noch nicht vorgekommen, dass eine Azure Function so langsam war, dass es bei Twilio einen Timeout gab, und diese Studie zeigt, dass der Großteil der Java-Funktionen in unter 15 Sekunden ausgeführt wird. Wenn du das Kaltstartproblem ganz vermeiden möchtest, könnte der Azure Function Premium Plan eine Lösung sein. Er bietet garantierte Warmstarts, allerdings gegen eine Gebühr. Alle anderen Aspekte dieses Blog-Beitrags werden bequem von der kostenlosen Version von Azure abgedeckt.
Konfigurieren von Twilio für den Einsatz deiner SMS-Antwortfunktion
Falls du noch keines hast, erstelle ein kostenloses Twilio-Konto und hol dir eine Telefonnummer. Auf der Seite zum Konfigurieren der Telefonnummer wählst du als Verhalten für „a message comes in“ eine GET-Anfrage an die Azure Functions-URL aus:
Das war's Teste deine Funktion jetzt mit einer SMS:
Zusammenfassung
Falls du mitentwickelt hast, herzlichen Glückwunsch! Du hast jetzt eine funktionierende Spring Cloud Function in Azure, die mit Twilio integriert ist und Antworten auf eine SMS liefert. Das kannst du nun als Grundlage für weitere nützliche Funktionen nutzen! Twilio übermittelt neben dem Body
auch die From
-Nummer der eingehenden Nachricht und andere Metadaten, sodass du personalisierte Antworten erstellen, Informationen in deiner Kundendatenbank oder anderen Web-APIs suchen kannst – lass deiner Kreativität freien Lauf.
Wenn du mit serverlosem Java und Twilio arbeitest, würde ich gerne mehr darüber erfahren – ich freue mich, von dir zu hören. Viel Spaß beim Programmieren!
Verwandte Posts
Ähnliche Ressourcen
Twilio Docs
Von APIs über SDKs bis hin zu Beispiel-Apps
API-Referenzdokumentation, SDKs, Hilfsbibliotheken, Schnellstarts und Tutorials für Ihre Sprache und Plattform.
Ressourcen-Center
Die neuesten E-Books, Branchenberichte und Webinare
Lernen Sie von Customer-Engagement-Experten, um Ihre eigene Kommunikation zu verbessern.
Ahoy
Twilios Entwickler-Community-Hub
Best Practices, Codebeispiele und Inspiration zum Aufbau von Kommunikations- und digitalen Interaktionserlebnissen.