In einer idealen Welt gibt es keine Probleme, keine Fehler. Wir leben jedoch in einer realen Welt, in der nicht alles, was wir tun, immer so funktioniert, wie wir es geplant oder gehofft haben. Die wichtigsten Bereiche, in denen wir in WSO2 Enterprise Integrator mit Fehlern umgehen müssen, sind Proxys und APIs. Die Fehlerbehandlung ist der Schlüssel zu einer guten Entwicklung für Ihre Dienste und APIs. Nur wenige Dinge sind frustrierender als eine unsinnige Fehlermeldung wie ‚Etwas ist schief gelaufen‘. Entwickeln Sie nicht nur für andere eine angemessene Fehlerbehandlung, sondern auch für sich selbst. Einfach deshalb, weil Sie sich ein halbes Jahr später dafür bedanken werden, dass Sie eine Fehlermeldung wie ‚Die Verbindung zum FinanceWorld Invoicing Service konnte aufgrund einer Zeitüberschreitung der Verbindung nicht hergestellt werden‘ erhalten haben und nicht ‚Es ist etwas schief gelaufen‘.
Ich werde in diesem Blog über die Fehlerbehandlung sprechen und darüber, wie Sie diese in WSO2 Enterprise Integrator konfigurieren können.
Möglichkeiten der Fehlerbehandlung
Einige Fehler treten außerhalb der Mediation auf. Wenn Sie beispielsweise zweimal versuchen, den Enterprise Integrator zu starten, erhalten Sie einen Stack-Trace, der z.B. anzeigt, dass eine Datei gesperrt ist.
Ein anderer Fehler, z.B. Speichermangel, kann die ganze Java Virtual Machine lahm legen. Auch hier können Sie nur wenig tun, außer die Speichermenge zu erhöhen und/oder andere Programme zu entfernen, die gleichzeitig laufen.
Was ich meine, ist die Fehlerbehandlung in Bezug auf den Integrationsprozess, und dazu gehören Fehler, die durch Endpunkte, Nutzdaten usw. verursacht werden.
Fehler-Reihenfolge in Integration Studio
Wenn Sie einen Proxy oder eine API erstellen und die Entwurfsansicht in Integration Studio verwenden, haben Sie vielleicht ein rotes rechteckiges Feld gesehen. Das ist die Fehlersequenz. Die Fehlersequenz wird ausgeführt, wenn ein ERROR in den EI-Komponenten auftritt, nicht zu verwechseln mit einem Fehler, der vom Back-End zurückgegeben wird. Die Fehler des Back-Ends werden in der in- oder outSequence behandelt, aber standardmäßig nicht an die Fault-Sequence gesendet!
Wir möchten also unter anderem die Nichtverfügbarkeit eines Endpunkts erfassen. Zu diesem Zweck habe ich einen Endpunkt erstellt, der auf den Echo-Dienst verweist, der im Enterprise Integrator enthalten ist. Ich schalte den Endpunkt aus. So dass er im Idealfall eine Fehlermeldung auslöst. Außerdem habe ich die Konfiguration der standardmäßigen ‚Fehler‘-Sequenz kopiert und einige Änderungen vorgenommen. Damit klar ist, dass es die benutzerdefinierte Fehlersequenz innerhalb des von mir erstellten Proxys ist, die die Informationen an die Konsole weiterleitet.
<?xml version="1.0" encoding="UTF-8"?>
<proxy name="ErrorProxy" startOnLoad="true" transports="http https" xmlns="http://ws.apache.org/ns/synapse">
<target>
<inSequence>
<send>
<endpoint key="Test"/>
</send>
</inSequence>
<outSequence>
<send/>
</outSequence>
<faultSequence>
<log level="custom">
<property name="MESSAGE" value="Executing Proxy 'fault' sequence"/>
<property expression="get-property('ERROR_CODE')" name="ERROR_CODE"/>
<property expression="get-property('ERROR_MESSAGE')" name="ERROR_MESSAGE"/>
</log>
<payloadFactory media-type="xml">
<format>
<Error>$1</Error>
</format>
<args>
<arg evaluator="xml" expression="get-property('ERROR_CODE')"/>
</args>
</payloadFactory>
<respond/>
</faultSequence>
</target>
</proxy
Dies ist die Antwort der Konsole:
[2021-06-15 16:41:50,953] INFO
{org.apache.synapse.mediators.builtin.LogMediator} - To: /services/ErrorProxy.ErrorProxyHttpSoap12Endpoint, WSAction: urn:mediate, SOAPAction: urn:mediate, MessageID: urn:uuid:cb296ee0-e738-478c-9ac4-008dcc9c4c5a, Direction: request, MESSAGE = Executing Proxy 'fault' sequence, ERROR_CODE = 303001, ERROR_MESSAGE = Currently , Address endpoint : [ Name : Test ] [ State : MAINTNENCE ], Envelope: <?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope"><soapenv:Body/></soapenv:Envelope>
Ein Fortschritt im Vergleich zu keiner Nachricht, aber immer noch ein weiter Weg. Wir haben auch eine Antwort in unserem Client.
Lassen Sie uns das im nächsten Absatz in eine Reihenfolge bringen.
Machen Sie eine generische Fehlersequenz daraus
Aber wir können mehr tun! Und wir sollten mehr für eine angemessene Fehlerbehandlung tun. Die gleiche Fehlerbehandlung kann auch in eine Sequenz verlagert werden. Wir sollten in eine solche Behandlung Dinge einbeziehen, die uns helfen zu erkennen, was schief gelaufen ist. Sie können sich Elemente vorstellen wie:
- uuid (eindeutige Nachrichten-ID)
- datetime (identifiziert den Zeitpunkt des Auftretens)
- eigener Fehlercode (Übersetzung der WSO2-Codes in Ihre eigenen Codes)
Darüber hinaus ist es notwendig, dass wir dem Kunden eine Nachricht zurückgeben, die angibt, dass etwas schief gelaufen ist. Die nicht-technischen Fehler (siehe Leere Antwort weiter unten) sollten ebenfalls enthalten sein, damit es eine Fehlersequenz gibt, die aufgerufen wird.
Fehler in einer Sequenz
Wenn Sie eine Sequenz definieren, können Sie auch die damit verbundene On-Error-Sequenz festlegen. Wenn innerhalb einer Sequenz etwas schief geht, z.B.: Sie rufen einen Endpunkt auf, können Sie immer noch eine Fehlermeldung erhalten und eine angemessene Fehlerbehandlung vornehmen. Statt eines Proxys, bei dem die Fehlermeldung ausgelöst wird, verwende ich also einen Proxy, der eine Sequenz auslöst und der dann versucht, den ausgeschalteten Endpunkt aufzurufen. Das ist derselbe Endpunkt wie zuvor. In diesem Fall sollten wir die gleiche Fehlermeldung sehen. Doch auch hier nehme ich eine Änderung innerhalb der Fehlersequenz vor, um darauf hinzuweisen, dass dies nicht die Fehlersequenz in Bezug auf den Proxy ist. Dies ist die Fehlersequenz, die erstellt wurde und die mit der Sequenz verbunden ist, die wir gerade aufrufen.
<?xml version="1.0" encoding="UTF-8"?>
<sequence name="callEndpoint" onError="callEndPointError" trace="disable" xmlns="http://ws.apache.org/ns/synapse">
<call>
<endpoint key="Test"/>
</call>
</sequence>
Sequence error
<?xml version="1.0" encoding="UTF-8"?>
<sequence name="callEndPointError" trace="disable" xmlns="http://ws.apache.org/ns/synapse">
<log level="custom">
<property name="MESSAGE" value="Executing Sequence 'fault' sequence"/>
<property expression="get-property('ERROR_CODE')" name="ERROR_CODE"/>
<property expression="get-property('ERROR_MESSAGE')" name="ERROR_MESSAGE"/>
</log>
<payloadFactory media-type="xml">
<format>
<Error>$1</Error>
</format>
<args>
<arg evaluator="xml" expression="get-property('ERROR_CODE')"/>
</args>
</payloadFactory>
<respond/>
</sequence>
Sie können die obige Sequenz so anpassen, dass sie auch auf eine generische Fehlersequenz verweist.
Fehler Proxy2
Ein zweiter Proxy ruft die Sequenz auf und antwortet.
<?xml version="1.0" encoding="UTF-8"?>
<proxy name="ErrorProxy2" startOnLoad="true" transports="http https" xmlns="http://ws.apache.org/ns/synapse">
<target>
<inSequence>
<sequence key="callEndpoint"/>
<respond/>
</inSequence>
<outSequence/>
<faultSequence>
<log level="custom">
<property name="MESSAGE" value="Executing Proxy 'fault' sequence"/>
<property expression="get-property('ERROR_CODE')" name="ERROR_CODE"/>
<property expression="get-property('ERROR_MESSAGE')" name="ERROR_MESSAGE"/>
</log>
<payloadFactory media-type="xml">
<format>
<Error>$1</Error>
</format>
<args>
<arg evaluator="xml" expression="get-property('ERROR_CODE')"/>
</args>
</payloadFactory>
<respond/>
</faultSequence>
</target>
</proxy>
Selbst wenn ich die Sequenz in die Fehlersequenz des Proxys einfüge, löst sie immer noch den Sequenzfehler aus, da sie dort aufgetreten ist.
[2021-06-15 16:44:16,818] INFO
{org.apache.synapse.mediators.builtin.LogMediator} - To: /services/ErrorProxy2.ErrorProxy2HttpSoap12Endpoint, WSAction: urn:mediate, SOAPAction: urn:mediate, MessageID: urn:uuid:a25b79ab-12ad-40d7-9817-2ea2995ad1a7, Direction: request, MESSAGE = Executing Sequence 'fault' sequence, ERROR_CODE = 303001, ERROR_MESSAGE = Currently , Address endpoint : [ Name : Test ] [ State : MAINTNENCE ], Envelope: <?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope"><soapenv:Body/></soapenv:Envelope>
Test-Endpunkt mit einem Fehlercode 101504 definiert (Verbindung wurde unterbrochen (es wurde keine Eingabe auf dieser Verbindung über den maximalen Zeitraum der Inaktivität erkannt)).
<?xml version="1.0" encoding="UTF-8"?>
<endpoint name="Test" xmlns="http://ws.apache.org/ns/synapse">
<address uri="http://localhost:8280/services/echo">
<suspendOnFailure>
<errorCodes>101504</errorCodes>
<initialDuration>-1</initialDuration>
<progressionFactor>1.0</progressionFactor>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
</markForSuspension>
</address>
</endpoint>
Wie Sie an der Antwort sehen können, erhalte ich jetzt eine Reihe von Protokollvermittlern, die den vorliegenden Fehler anzeigen. Die allgemeine Sequenz sollte die WSO2-Fehlercodes in eine Reihe von benutzerdefinierten Fehlercodes übersetzen, z.B. ‚EP_001- Endpunkt nicht verfügbar‘ oder etwas Ähnliches.
Eine leere Antwort erhalten
Doch was ist mit einer leeren Antwort, wenn Sie einen Proxy oder eine API aufrufen möchten, die Antwort aber leer ist, weil der Wert nicht gefunden werden konnte?
Wie geht man damit um? Nun, lassen Sie es uns versuchen. Wir machen einen einfachen Proxy. Wir sehen uns die Nutzdaten an. Wenn die Nutzdaten das Wort GREEN enthalten, wird dies an den Client zurückgesendet. Wenn das Wort GRÜN nicht enthalten ist, ist es eine leere Nutzlast. Im ErrorProxy3 werden wir eine einfache Fehlermeldung ‚No Color Found‘ erstellen.
<?xml version="1.0" encoding="UTF-8"?>
<proxy name="ErrorProxy3" startOnLoad="true" transports="http https" xmlns="http://ws.apache.org/ns/synapse">
<target>
<inSequence>
<call>
<endpoint>
<address uri="http://localhost:8280/services/Responseproxy">
<suspendOnFailure>
<initialDuration>-1</initialDuration>
<progressionFactor>-1</progressionFactor>
<maximumDuration>0</maximumDuration>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
</markForSuspension>
</address>
</endpoint>
</call>
<log level="full"/>
<filter xpath="$body/color!='beautiful'">
<then>
<payloadFactory media-type="xml">
<format>
<error xmlns="">No Color Found</error>
</format>
<args/>
</payloadFactory>
</then>
</filter>
<respond/>
</inSequence>
<outSequence/>
<faultSequence/>
</target>
</proxy>
<?xml version="1.0" encoding="UTF-8"?>
<proxy name="Responseproxy" startOnLoad="true" transports="http https" xmlns="http://ws.apache.org/ns/synapse">
<target>
<inSequence>
<filter xpath="$body/color='GREEN'">
<then>
<property name="result" value="beautiful"/>
</then>
<else>
<property name="result" value=""/>
</else>
</filter>
<payloadFactory media-type="xml">
<format>
<color xmlns="">$1</color>
</format>
<args>
<arg evaluator="xml" expression="$ctx:result"/>
</args>
</payloadFactory>
<respond/>
</inSequence>
<outSequence/>
<faultSequence/>
</target>
</proxy>
Fazit
Das sind einfache Beispiele, die zeigen, wie die Fehlerbehandlung funktioniert.
Eine bessere Herangehensweise ist es jedoch, eine generische Fehlerbehandlungssequenz zu erstellen, die eine homogene Fehlerreaktion sowohl für Backend-Fehler als auch für Fehler aus der Fehlersequenz ermöglicht. Diese Sequenz kann für eine Reihe von Diensten oder eine bestimmte Dienstgruppe definiert werden, die die Standardfehlerfelder mit bestimmten Werten füllt. Die Fehlerbehandlung erfordert einen umfassenden Überblick über die Fehlertypen (Fehler, Backend-Fehler, schwerwiegende Fehler, die die generische Fehlersequenz auslösen), aber auch über die Art der Informationen, die zur Verfügung stehen und die benötigt werden, um die Fehler beheben zu können.
Je nach Art der Nachrichten, der Art der Aufrufe und anderer Parameter können Sie die benötigten Informationen ermitteln und Kerninformationen und optionale Informationen, z.B. spezifische Verbindungsinformationen, definieren.