Es ist an der Zeit, über SOAP zu sprechen. Nein, nicht das Reinigungsprodukt, sondern das Simple Object Access Protocol. SOAP ist ein gängiges Protokoll, das in Webservices verwendet wird, und wenn wir uns die aktuelle Version von WSO2 Enterprise Integrator ansehen, ist es auch die grundlegende Technologie, die in diesem Produkt verwendet wird. SOAP basiert auf XML und eine SOAP-Nachricht besteht aus einem Umschlag mit einem Header und einem Body. Dieser Blog befasst sich mit der Web Service Description Language (WSDL), die häufig zur Beschreibung der Schnittstelle eines SOAP-Dienstes verwendet wird.
WSO2 Enterprise Integrator
SOAP hat zwar etwas von seiner Popularität an JSON verloren, wird aber immer noch in vielen Webservices eingesetzt. Wenn wir das Akronym betrachten und das Wort „einfach“ finden, werden wir in gewisser Weise in die Irre geführt. SOAP ist nämlich gar nicht so einfach, vor allem wenn man es mit JSON vergleicht. Trotzdem verwenden wir immer noch SOAP-Dienste und werden dies auch in absehbarer Zukunft tun. Schauen wir uns einmal die Web Service Description Language (WSDL) an, die häufig zur Beschreibung der Schnittstelle eines SOAP-Dienstes verwendet wird. Ich werde nicht näher darauf eingehen, wie man WSO2 Enterprise Integrator oder Integration Studio installiert oder wie man einen Proxy mit Hilfe einer Autodatei auf WSO2 Enterprise Integrator erstellt und einsetzt, dafür gibt es die eingefügten Links.
WSDL
In einer WSDL wird das Interface eines Webservice definiert. Ein Interface setzt sich aus Operationen und Nachrichten zusammen. Diese Nachrichten werden über SOAP versendet. Es beschreibt im Wesentlichen den Inhalt des SOAP-Bodys in Bezug auf die zu verwendenden XML-Elemente usw. Ziel ist es, Sie bei der Erstellung einer Nachricht mit der richtigen Struktur und dem richtigen Inhalt zu unterstützen. Bei der Nutzung eines SOAP-Service können Sie oft eine WSDL-Datei finden oder beziehen, die Ihnen hilft, die richtige Nachricht zu erstellen. Schauen wir uns einmal eine WSDL-Datei an, die in Enterprise Integrator enthalten ist. Es handelt sich dabei um den Echo-Service, der Teil des Produkts ist.
Hier sehen Sie die Übersicht über die bereitgestellten Services von WSO2 Enterprise Integrator. Wie Sie sehen können, ist der Echo-Dienst weder ein Proxy noch eine API, sondern ein axis2-Dienst, die Web-Engine, die in WSO2 Enterprise Integrator verwendet wird. Schauen wir uns nun die WSDL v1.1 Definition an. Wenn Sie auf den WSDL-Link klicken, wird er im Chrome-Browser geöffnet (in Firefox wird der Inhalt nicht angezeigt). So sieht sie aus (aus Gründen der Übersichtlichkeit gekürzt):
Wie Sie erkennen können, gibt es ein Element namens echoString, das ein Element namens ‚in‘ hat, das einen String-Wert annimmt. Wenn wir mit Hilfe der WSDL ein SOAP-Projekt in SoapUI erstellen, wird diese Definition in die unten gezeigte Nachricht umgewandelt:
Validierung
Es gibt verschiedene Möglichkeiten zu überprüfen, ob eine Nachricht mit der zugehörigen WSDL übereinstimmt. Sie können einzelne Elemente im Soap-Body untersuchen, um z. B. zu sehen, ob die XML-Tags korrekt sind, wenn die Nachricht in Enterprise Integrator eingeht.
Erstellen wir einen einfachen Proxy, der überprüft, ob ein korrektes echoString-Tag in der Nachricht vorhanden ist. Wir verwenden den WSO2 Enterprise Integrator 6.5.0 und das WSO2 Integration Studio.
Dazu habe ich einen einfachen Pass-Through-Proxy erstellt, der auf den Endpunkt des Echo-Service zeigt. Sobald die Nachricht in EI eingeht, ist der SOAP-Body im Proxy verfügbar, und ich kann ihn mit einem Full Log Mediator anzeigen. Der Quelltext ist einfach, daher werde ich nur die grafische Ansicht zeigen.
Diesen Proxy rufe ich mit SoapUI unter Verwendung der ursprünglichen WSDL des Echo-Service auf. Ich habe nämlich keine WSDL für den Proxy-Service veröffentlicht, sodass dieser eine Standard-WSDL mit einem leeren Textkörper bereitstellt. Dies zu ändern bedeutet, zwei Parameter hinzuzufügen, die angeben, dass wir die WSDL aus dem Backend verwenden oder die WSDL selbst definieren möchten. Wenn der Dienst mit der von SOAPUI generierten Nachricht aufgerufen wird, erhalte ich eine Antwort in SoapUI und eine Nachricht auf der Konsole.
Ein Teil der Nachricht wird auf der Konsole angezeigt:
[2019-07-01 10:13:08,535] [EI-Core] INFO - LogMediator To: /services/WSDLCheck1,
WSAction: urn:echoString, SOAPAction: urn:echoString, MessageID: urn:uuid:e70f26c7-
19ec-433a-90d5-99fe42bc3328 correlation_id : 502325b8-ab98-4056-b8f1-939b86871d76,
Direction: request, Envelope: <?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns_soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns_echo="http://echo.services.core.carbon.wso2.org"><soapenv:Body>
<echo:echoString>
<!--Optional:-->
<in>test</in>
</echo:echoString>
</soapenv:Body></soapenv:Envelope>
Wie Sie sehen können, wurde eine vollständige Nachricht gesendet. Jetzt fügen wir einen Filter-Mediator hinzu, um eine von zwei Situationen zu bestimmen:
- In der Nachricht gibt es ein Tag namens echoString
- In der Nachricht gibt es ein Tag namens echoString
Der Filter-Mediator ist für diese Art von Einrichtung ideal geeignet, da es nur zwei mögliche Ergebnisse gibt. Um zu testen, ob die Zeichenfolge verfügbar ist, können wir Xpath verwenden. Xpath ist für XML-Nachrichten das, was SQL für eine Datenbank ist, mit anderen Worten eine Sprache, die es uns ermöglicht, Informationen aus – in diesem Fall – einer Nachricht abzurufen. Sollten Sie mit Xpath nicht vertraut sein, was ich mir vorstellen kann, gibt es online einige Tools, die Ihnen helfen, Ihr Wissen über diese wichtige Sprache, die in Enterprise Integrator und jeder Art von XML-basierten Nachrichten verwendet wird, zu erweitern.
Das Tool heißt https://www.freeformatter.com/xpath-tester.html und ermöglicht es Ihnen, alle möglichen Xpath-Anweisungen auszuprobieren, um die gewünschten Informationen aus einer XML-Nachricht abzurufen. Sie kopieren einfach die Nachricht aus SoapUI in den Xpath-Tester und testen Ihre XPath-Anweisung. Beachten Sie jedoch, dass Namespaces einbezogen werden müssen, wenn Sie Xpath zum Abrufen von Werten verwenden.
Ich möchte also die eingehende Nachricht filtern und grundsätzlich feststellen, ob die Nachricht der WSDL entspricht, zumindest für ein Element. Der von mir verwendete Mechanismus besteht darin, den Inhalt des echoString-Elements zu überprüfen. Wenn ein Element namens echoString vorhanden ist, wird dessen Inhalt zurückgegeben (auch wenn es leer ist).
Die Expression-Anweisung, die ich verwende, um dies zu bestimmen, ist die folgende:
<property expression="descendant::echo:echoString/in" name="CHKWSDL1" xmlns_echo=http://echo.services.core.carbon.wso2.org />
Was tue ich also hier? Wir verfügen über einen Property-Mediator mit einer Expression, die den Wert des XML-Elements „in“ abruft, das im echoString-Element enthalten ist. In der Nachricht, die an den Proxy gesendet wird, ist das in-Element zu sehen. Ich benutze eine sogenannte XPath-Achse, um das echo:echoString-Element irgendwo im Nachrichtentext zu finden und das ‚in‘-Element darin zu erhalten.
Das echoString-Element ist in einem Namespace definiert, der das Präfix „echo“ hat, und wir müssen den Namespace in der XPath-Anweisung angeben, um das Element abrufen zu können.
Einfach ausgedrückt: Wir suchen nach dem Tag <echoString> im Textkörper und ermitteln sein untergeordnetes Element namens <in> und geben dessen Wert zurück.
Wenn der oder die Tags, nach denen ich suche, nicht existieren, erhalte ich einen leeren Rückgabewert, und dann kann ich eine Fehlerbehandlung durchführen. In diesem Falle möchte ich einen Soap-Fehler mit Hilfe des Fault Mediators erzeugen und die Fehlermeldung an den Client zurückschicken. Sollte ich keine leere Rückmeldung erhalten, obwohl der Wert innerhalb der <in>-Tags leer ist, werde ich ihn einfach an das Backend senden.
Aus grafischer Sicht sieht das folgendermaßen aus:
<?xml version="1.0" encoding="UTF-8"?>
<proxy name="WSDLCheck1" startOnLoad="true" transports="http https"
xmlns=http://ws.apache.org/ns/synapse
xmlns:echo="http://echo.services.core.carbon.wso2.org">
<target>
<endpoint>
<address uri="http://localhost:8280/services/echo"/>
</endpoint>
<inSequence>
<log>
<property expression="descendant::echo:echoString/in" name="CHKWSDL1" />
</log>
<filter xpath="descendant::echo:echoString/in">
<then>
<log level="custom">
<property name="Outcome" value="Yes"/>
<property expression="descendant::echo:echoString/in" name="CHKWSDL1" />
</log>
</then>
<else>
<log level="custom">
<property name="Outcome" value="No"/>
<property expression="descendant::echo:echoString/in" name="CHKWSDL1" />
</log>
<makefault version="soap11">
<code value="soap11Env:Client" xmlns:soap11Env="http://schemas.xmlsoap.org/soap/envelope/"/>
<reason value="Message not according to WSDL, <echoString> is missing"/>
<detail>Sending incorrect message</detail>
</makefault>
<respond/>
</else>
</filter>
</inSequence>
<outSequence>
<send/>
</outSequence>
<faultSequence/>
</target>
</proxy>
In der Quellenansicht können wir die einzelnen Schritte klar erkennen. Zunächst zeigen wir den Wert auf dem Bildschirm mit dem ersten Log-Mediator, der den Wert abruft. Anschließend prüfen wir im Filter-Mediator, ob das Element existiert. Wenn nicht, führen wir den else-Zweig des Filter-Mediators aus, protokollieren eine Meldung auf der Konsole, erzeugen einen SOAP-Fehler mit dem Fault-Mediator und geben die Meldung mit einem Respond-Mediator zurück. Wenn das Element existiert, protokollieren wir die Nachricht auf der Konsole und leiten die Nachricht implizit an den Echo-Service im Backend weiter.
Ein einfacher Ansatz
Auf diese Weise lässt sich sehr einfach überprüfen, ob eine Nachricht das in der WSDL angegebene Element enthält. Wenn Sie beispielsweise ein schließendes oder öffnendes Tag vermissen, wird beim Parsen der Nachricht auf einer niedrigeren Ebene ein Fehler ausgelöst. Die Nachricht erreicht deshalb nicht den Proxy. Ein Parsing-Fehler wird von WSO2 Enterprise Integrator automatisch an den Client zurückgegeben.
Im nächsten Blog werden wir uns eine andere Möglichkeit ansehen, eine Nachricht zu validieren, um zu sehen, ob sie mit der zugehörigen WSDL übereinstimmt, nämlich mit Hilfe des validate Mediators, der als Teil des WSO2 Enterprise Integrator-Sets von Mediatoren verfügbar ist.