fb
WSO2 Enterprise Integrator 14 Minuten

Einfache Anwendungen erstellen, die „gut genug“ sind

Rob Blaauboer
Rob Blaauboer
Integration Consultant & WSO2 Trainer
Creating simple solutions that are good enough
Scrollen

Während der Covidpandemie gab es zahlreiche Beispiele für Fälle, in denen schnelles Handeln erforderlich war. Ein gutes Beispiel sind etwa Restaurants, die plötzlich nicht mehr öffnen durften, sondern nur noch Essen zum Mitnehmen anbieten durften. 

Aufgrund der plötzlichen Umstände, in denen wir uns damals befanden, brauchten wir keine perfekte Lösung, aber wir brauchten eine Lösung, die „gut genug“ war. Jeden Tag, an dem diese Lösung noch nicht zur Verfügung stand, bedeutete einen massiven Umsatzverlust. Wenn wir mehr Zeit gehabt hätten, hätten wir diese Lösung noch viel besser machen können, aber zu diesem Zeitpunkt funktionierte sie. 

Ein anderes Beispiel für eine solche Lösung ist eine Eisdiele, die es den Kunden ermöglichte, online zu bestellen und im Laden abzuholen. Das gehörte nicht zu den üblichen Arbeitsweisen. Aber es ermöglichte dem Restaurant zumindest ein gewisses Geschäft.

Schnelle Lösung zur Registrierung von Kundendaten – Microsoft 

Vor einiger Zeit hat einer meiner Microsoft-Kontakte auf LinkedIn ein Beispiel dafür gegeben, wie vorhandene Microsoft-Tools und -Anwendungen zur schnellen Registrierung von Kundendaten genutzt werden können, was eine weitere wichtige Voraussetzung in Zeiten von Covid ist. Die Regierung hat beschlossen, dass Gastronomen nun die Daten von Besuchern registrieren müssen, um eine mögliche Virenverbreitung zu verfolgen und zu verwalten. 

Stift und Papier reichen nicht aus

Natürlich ist die einfachste Lösung etwas, das es schon immer gab: Stift und Papier. Wenn Sie Ihre Informationen jedoch digital speichern, können Sie die Qualität verbessern. Wenn Sie es richtig anstellen, können Sie außerdem dafür sorgen, dass die Daten nach einer bestimmten Zeit, sagen wir, nach ein oder zwei Wochen, gelöscht werden. Wir möchten keine unnötigen Daten speichern oder Daten länger als nötig aufbewahren.

Wie kann man eine Lösung zur schnellen Datenspeicherung mit WSO2-Produkten einrichten? 

Ich möchte mit diesem Blog zeigen, wie einfach es ist und wie schnell wir eine Lösung zum Ausprobieren entwickeln können. Ich möchte nicht vorschlagen, dass wir eine ständige Betaversion haben, aber es ist recht einfach, etwas zu entwickeln, das man ausprobieren und in der Eile verwenden kann. Es ist einfach, die PostNL-API hinzuzufügen, aber es wird Ihnen ermöglichen, Daten zu validieren und zu verbessern und, was noch wichtiger ist, den Prozess zu verkürzen. 

Eine einfache Einrichtung, die Daten speichert 

Ich möchte demonstrieren, dass wir ein sehr einfaches Setup erstellen können, das es Ihnen ermöglicht, Daten zu speichern und bis zu einem gewissen Grad auch Daten in Bezug auf die eingegebenen Daten zu überprüfen, z. B. die Postleitzahl, und das in nur wenigen Stunden. Wir benötigen dazu ein einfaches Frontend und ein paar APIs sowie ein einfaches Datenbankmanagementsystem, einige gespeicherte Prozeduren und natürlich die Produkte von WSO2. 

Enterprise Integrator 

Ich werde WSO2 Enterprise Integrator verwenden. In diesem Falle werde ich das Setup mit einem Micro Integrator verwenden. So kann ich es in einer Docker-Umgebung anbieten, wodurch mehr Skalierbarkeit möglich ist, aber auch die Funktionalität des Enterprise Integrators zur Verfügung steht.

MariaDB

Was brauchen wir also für den Anfang? Zuerst brauchen wir natürlich einen Ort zum Speichern der Daten. In diesem Falle verwende ich ein Datenbankmanagementsystem wie MariaDB, das einfach zu bedienen ist und viele der benötigten Funktionen ausführen kann. 

Beginnen wir mit der Einrichtung der Datenbank. Was ich benötige, sind: Vorname, Nachname, Postleitzahl, eine NL-Handynummer und eine E-Mail-Adresse. Selbstverständlich muss auch ein Zeitstempel für das Datum vorhanden sein. Wenn die Informationen in die Datenbank eingegeben werden, wird der Datumszeitstempel verwendet, um die Daten zu einem bestimmten Zeitpunkt zu löschen. Mit dem Löschen der Daten meine ich: die Einhaltung der Gesetze und Vorschriften für die Speicherung dieser Daten. 

Das ist eine recht einfache Konfiguration, die Ihnen zeigt, wie schnell Sie so etwas einrichten können. Ich erstelle einen Primärschlüssel, der natürlich eindeutig sein muss und bei dem es sich um eine automatisch inkrementierte Zahl handelt. Die Datenbankerstellung ist unten dargestellt. Wir benutzen das Wort Postleitzahl, das in den USA das Äquivalent zur Postleitzahl ist, zumindest aus einer semantischen Perspektive.

#coronapostcode


CREATE DATABASE IF NOT EXISTS coronapostcode;
USE coronapostcode;

CREATE TABLE IF NOT EXISTS guests (
   GID INTEGER NOT NULL AUTO_INCREMENT,
   NAME VARCHAR(40) NOT NULL,
   CELLPHONE VARCHAR(10) NOT NULL,
   ADDRESS VARCHAR (50) NOT NULL,
   HOUSENR VARCHAR (5) NOT NULL,
   POSTCODE VARCHAR(50) NOT NULL,
   TOWN VARCHAR(50) NOT NULL,
   DTSTAMP datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
   PRIMARY KEY (GID)
);
SET insert_id=2020;

INSERT INTO guests (name,cellphone,address,housenr,postcode,town) VALUES ('Jill Doe', '0612345678','Rokin','12','1002AB','Amsterdam');

select * from guests;

Ok, der Datenbank-Primärschlüssel ist also erstellt. Um zu sehen, ob das funktioniert, habe ich einen Datensatz eingefügt. Jetzt müssen wir die Soap Services generieren. Wie das geht, können Sie in diesem Video sehen.

Wichtig ist, dass die Erstellung des Datendienstes, die wir gerade durchgeführt haben, weniger als zwei Minuten gedauert hat und bereits eine SOAP-Schnittstelle bietet, über die wir Daten in die Datenbank einfügen können. Durch eine einfache Front-End-Entwicklung, die den SOAP-Dienst aufruft, sind wir also bereit, den Dienst zu nutzen. Ich möchte hier nicht ins Detail gehen, da die Front-End-Entwicklung nicht mein Fachgebiet ist und den Rahmen dieses Blogs sprengen würde (wir konzentrieren uns auf die Integration).

Enterprise Integrator kann den SOAP-Dienst auch über eine API bereitstellen, so dass wir einen RESTful-Aufruf durchführen können, der moderner und für ein Frontend-Entwicklungsteam einfacher zu realisieren ist.

API erstellen

Und jetzt muss ich natürlich die API erstellen. Warum eine API? Nun, es ist die naheliegendste Lösung. Wenn Sie Informationen speichern wollen, sind APIs die beste Lösung. Sie sind unkompliziert. Sie werden von vielen Entwicklern genutzt, und natürlich sind sie recht einfach zu erstellen. In unserem Fall werden wir nur ein HTTP POST mit Informationen als JSON-Nutzlast durchführen, um sie der Datenbank hinzuzufügen. Die API wird auf dem Enterprise Integrator erstellt, weil ich die Nutzdaten vermitteln möchte.

Von API zu Soap

Die Erstellung einer API, die mit einem SOAP-Backend verbunden ist, ist eigentlich recht einfach. Sie müssen: 

  1. Einen Header hinzufügen und auf die entsprechende Aktion setzen
  2. Fügen Sie den PayloadFactory Mediator hinzu
  3. Fügen Sie einen Call Mediator und einen Endpunkt hinzu
  4. Antworten Sie dem Client zurück

Das Video zeigt das Einrichten der High-Level-Struktur. 

Die Payload können wir sehen, wenn wir die WSDL z.B. in SoapUI verwenden.

Der Quellcode zeigt die Details. 

<?xml version="1.0" encoding="UTF-8"?>
<api context="/add" name="Customer" xmlns="http://ws.apache.org/ns/synapse">
    <resource methods="POST">
        <inSequence>
            <header name="Action" scope="default" value="insert"/>
            <payloadFactory media-type="xml">
                <format>
                    <soapenv:Envelope xmlns:dat="http://ws.wso2.org/dataservice" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
                        <soapenv:Header/>
                        <soapenv:Body>
                            <dat:insert>
                                <dat:name>$1</dat:name>
                                <dat:cellphone>$2</dat:cellphone>
                                <dat:address>$3</dat:address>
                                <dat:housenr>$4</dat:housenr>
                                <dat:town>$5</dat:town>
                                <dat:postcode>$6</dat:postcode>
                            </dat:insert>
                        </soapenv:Body>
                    </soapenv:Envelope>
                </format>
                <args>
                    <arg evaluator="xml" expression="$body//name"/>
                    <arg evaluator="xml" expression="$body//cellphone"/>
                    <arg evaluator="xml" expression="$body//address"/>
                    <arg evaluator="xml" expression="$body//housenr"/>
                    <arg evaluator="xml" expression="$body//town"/>
                    <arg evaluator="xml" expression="$body//postcode"/>
                </args>
            </payloadFactory>
            <call>
                <endpoint>
                    <address format="soap11" uri="http://localhost:8280/services/Guest">
                        <suspendOnFailure>
                            <initialDuration>-1</initialDuration>
                            <progressionFactor>-1</progressionFactor>
                            <maximumDuration>0</maximumDuration>
                        </suspendOnFailure>
                        <markForSuspension>
                            <retriesBeforeSuspension>0</retriesBeforeSuspension>
                        </markForSuspension>
                    </address>
                </endpoint>
            </call>
            <respond/>
        </inSequence>
        <outSequence/>
        <faultSequence/>
    </resource>
</api>

Aber das ist noch nicht alles. Denn wir können die Daten, die in unsere API kommen, validieren.

Validierung der Daten mit POSTNL API

Um die Daten zu überprüfen, können wir eine API wie die von PostNL verwenden. Sie haben mehrere APIs, um ihre Dienste wie Versand und Sendungsverfolgung in alle möglichen Systeme wie Webshops usw. zu integrieren. Die APIs finden Sie online, wo Sie auch Ihren eigenen Trial API Key anfordern können, um sie selbst auszuprobieren. 

Die Lösung, die wir entwickelt haben, ist streng genommen „gut genug“. Wir können Daten in einer Datenbank speichern, und wir können die Informationen abrufen. Wir können es uns auch einfacher machen, da in den Niederlanden die Kombination aus Postleitzahl und Nummer (z. B. 1119 PT, 16) uns die Adresse liefert, wenn die Kombination existiert. So können wir einfach nach dem Namen, der Telefonnummer und der Postleitzahl/Hausnummer fragen und es unseren Kunden leichter machen, automatisch die Straße und den Ort zu ermitteln.
Ich bin angemeldet, um die API für Benelux Address Control zu testen. Damit kann ich die API ausprobieren. Ich habe es mit SoapUI ausprobiert, um zu sehen, welche Art von Informationen ich für unser eigenes Büro zurückbekomme. Auch wenn Postman eher für APIs geeignet ist, benutze ich SoapUI, weil ich es auch zum Kopieren der SOAP-Nachricht in der Payload Factory verwendet habe. PostNL bietet Postman-Sammlungen online an, so dass Sie Postman auch erforschen können, wenn Sie möchten.

Good enough solutions 1

Dies erfordert jedoch einige Arbeit. 

Wir müssen zunächst die ursprüngliche Nachricht (die einzelnen Felder) speichern und die PostNL-API aufrufen. Die URL und die Parameter finden wir in der Dokumentation. Wir erzeugen die benötigte Payload (wie oben gezeigt, fügen den apiKey als Header hinzu und rufen die API auf). Die Antwort, die wir zurückbekommen, enthält die benötigten Informationen. Die Mehrzahl der Felder in der API-Definition sind optional, so dass Sie auch weitere Informationen validieren können. In der Dokumentation finden Sie weitere Informationen über die PostNL-API.

Ich gehe in diesem Blog davon aus, dass ich eine korrekte Postleitzahl und Hausnummer eingebe, was normalerweise natürlich auch eine Korrektur der Fehler erfordert. Der Einfachheit halber lasse ich dies weg. Außerdem mache ich zwei Fehler in den Originaldaten, wenn ich die API später aufrufe (Sciphol und Beachavenue, beide falsch geschrieben). Indem wir die Daten von PostNL als Grundlage nehmen (sie sind die Quelle), kann ich die Eingaben des Kunden jederzeit überschreiben, damit sie mit der Antwort der PostNL-API übereinstimmen. 

Der Code ist einfach. Hier ist die grafische Übersicht.

Good enough solutions 2

Im Code sieht es so aus.

<?xml version="1.0" encoding="UTF-8"?>
<api context="/add" name="Customer" xmlns="http://ws.apache.org/ns/synapse">
    <resource methods="POST">
        <inSequence>
            <propertyGroup>
                <property expression="$body//name" name="orgname" scope="default" type="STRING"/>
                <property expression="$body//cellphone" name="orgcellphone" scope="default" type="STRING"/>
                <property expression="$body//address" name="orgaddress" scope="default" type="STRING"/>
                <property expression="$body//housenr" name="orghousenr" scope="default" type="STRING"/>
                <property expression="$body//town" name="orgtown" scope="default" type="STRING"/>
                <property expression="$body//postcode" name="orgpostcode" scope="default" type="STRING"/>
            </propertyGroup>
            <payloadFactory media-type="json">
                <format>{
   "CountryIso": "NL", 
 "HouseNumber": "$1",
"PostalCode": "$2"
}
</format>
                <args>
                    <arg evaluator="xml" expression="$ctx:orghousenr"/>
                    <arg evaluator="xml" expression="$ctx:orgpostcode"/>
                </args>
            </payloadFactory>
            <propertyGroup>
                <property name="messageType" scope="axis2" type="STRING" value="application/json"/>
                <property name="apikey" scope="transport" type="STRING" value="**Fill in the API key you received by requesting a trial API key**"/>
            </propertyGroup>
            <call>
                <endpoint>
                    <http method="post" uri-template="https://api.postnl.nl/address/benelux/v1/validate">
                        <suspendOnFailure>
                            <initialDuration>-1</initialDuration>
                            <progressionFactor>-1</progressionFactor>
                            <maximumDuration>0</maximumDuration>
                        </suspendOnFailure>
                        <markForSuspension>
                            <retriesBeforeSuspension>0</retriesBeforeSuspension>
                        </markForSuspension>
                    </http>
                </endpoint>
            </call>
            <propertyGroup>
                <property expression="$body//City" name="City" scope="default" type="STRING"/>
            </propertyGroup>
            <filter xpath="$ctx:orgtown!=$ctx:City">
                <then>
                    <property expression="$ctx:City" name="orgtown" scope="default" type="STRING"/>
                </then>
            </filter>
            <header name="Action" scope="default" value="insert"/>
            <payloadFactory media-type="xml">
                <format>
                    <soapenv:Envelope xmlns:dat="http://ws.wso2.org/dataservice" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
                        <soapenv:Header/>
                        <soapenv:Body>
                            <dat:insert>
                                <dat:name>$1</dat:name>
                                <dat:cellphone>$2</dat:cellphone>
                                <dat:address>$3</dat:address>
                                <dat:housenr>$4</dat:housenr>
                                <dat:town>$5</dat:town>
                                <dat:postcode>$6</dat:postcode>
                            </dat:insert>
                        </soapenv:Body>
                    </soapenv:Envelope>
                </format>
                <args>
                    <arg evaluator="xml" expression="$ctx:orgname"/>
                    <arg evaluator="xml" expression="$ctx:orgcellphone"/>
                    <arg evaluator="xml" expression="$ctx:orgaddress"/>
                    <arg evaluator="xml" expression="$ctx:orghousenr"/>
                    <arg evaluator="xml" expression="$ctx:orgtown"/>
                    <arg evaluator="xml" expression="$ctx:orgpostcode"/>
                </args>
            </payloadFactory>
            <call>
                <endpoint>
                    <address format="soap11" uri="http://localhost:8280/services/Guest">
                        <suspendOnFailure>
                            <initialDuration>-1</initialDuration>
                            <progressionFactor>-1</progressionFactor>
                            <maximumDuration>0</maximumDuration>
                        </suspendOnFailure>
                        <markForSuspension>
                            <retriesBeforeSuspension>0</retriesBeforeSuspension>
                        </markForSuspension>
                    </address>
                </endpoint>
            </call>
            <payloadFactory media-type="json">
                <format>{ "record status": "added" }</format>
                <args/>
            </payloadFactory>
            <respond/>
        </inSequence>
        <outSequence/>
        <faultSequence/>
    </resource>
</api>

Senden wir eine Nachricht an die API

Die folgende Payload soll etwas sein, das ein Gast auf seinem mobilen Gerät ausgefüllt hat. Ich verwende SoapUI, um die Nachricht zu imitieren. 

Good enough solutions 3

Überprüfung der Daten

Wenn wir einen Datensatz in eine Datenbank einfügen und keine andere Antwort als die Standardantwort 202 erhalten haben, sollten wir prüfen, ob die Daten korrekt gespeichert wurden. 

Good enough solutions 4

Eine kurze Auswahl in der Datenbank (select * from guests) zeigt, dass die Daten vorhanden sind. Ein aufmerksamer Leser wird sehen, dass Beachavenue nicht geändert wurde, eine zusätzliche Filteranweisung sollte dies korrigieren. Alternativ, und auch das ist eine Möglichkeit, überschreiben Sie die Daten des Kunden immer mit der Antwort von PostNL.

Fazit

Es ist leicht, „ausreichend gute“ Anwendungen zu erstellen. Selbstverständlich handelt es sich hier um ein vereinfachtes Beispiel, das kein Frontend und keine grundlegende Fehlerbehandlung vorsieht. Es ist aber auch einfach, es später zu einer minimalen lebensfähigen Integration zu erweitern. Für den Moment ist es aber gut genug.

Den Quellcode finden Sie auf der Yenlo Bitbucket Seite